💻OpenAPI 서버 제작기

웹 서비스에서 입력창을 통한 해킹(SQL 인젝션, XSS)을 방어

데메즈 2026. 5. 28. 10:04
반응형

1. SQL 인젝션 (SQL Injection) 방어

악의적인 SQL 구문을 입력해 DB 데이터를 탈취하거나 조작하는 공격입니다.

✅ 체크리스트

  • MyBatis XML 매퍼에서 파라미터를 받을 때 ${} 기호를 사용하고 있지 않은가?
  • ORDER BY 절이나 테이블명을 동적으로 바꿀 때, 사용자 입력을 그대로 연결(Concatenation)하고 있지 않은가?

🛠️ 구현 방법

① 반드시 #{} (PreparedStatement) 사용하기 MyBatis에서 #{}을 사용하면 내부적으로 입력값을 문자열(String)로 안전하게 바인딩하여 쿼리 구조 자체를 변경할 수 없게 만듭니다.

XML
 
SELECT * FROM wtr_api_artcl_info WHERE api_nm = '${apiNm}'

SELECT * FROM wtr_api_artcl_info WHERE api_nm = #{apiNm}

 

 

② 동적 쿼리(ORDER BY 등)는 화이트리스트 검증 ORDER BY 구문에는 #{}을 쓸 수 없어서 어쩔 수 없이 ${}를 써야 할 때가 있습니다. 이때는 입력값을 그대로 넣지 말고, 서버 단에서 허용된 문자열(화이트리스트)인지 무조건 체크해야 합니다.

// Controller나 Service에서 검증
String sortType = commandParm.getSortType();

// 허용된 정렬 기준이 아니면 기본값으로 강제 변경
if (!"clot_cnt".equals(sortType) && !"api_nm".equals(sortType)) {
    sortType = "api_no"; // 기본값
}

 

2. 크로스 사이트 스크립팅 (XSS) 방어

게시판이나 입력창에 <script>alert('해킹')</script> 같은 태그를 넣어, 다른 사용자가 조회할 때 악성 스크립트가 실행되게 만드는 공격입니다.

✅ 체크리스트

  • 화면(JSP 등)에 데이터를 출력할 때 HTML 태그가 그대로 렌더링되도록 방치하고 있지 않은가?
  • API(JSON) 통신 시, 클라이언트에서 보낸 < , > 기호가 그대로 DB에 들어가고 있는가?

🛠️ 구현 방법

① JSP 화면 출력 시 이스케이프 처리 만약 JSP를 사용 중이라면 데이터 출력 시 무조건 <c:out>을 사용하세요. < 기호를 &lt;로 자동 변환하여 스크립트 실행을 막아줍니다.

<div>${apiInfo.apiNm}</div>

<div><c:out value="${apiInfo.apiNm}" /></div>

 

② JSON API 통신 시 Jackson XSS 처리 (가장 중요) 앞서 작성하셨던 @RequestBody나 @ResponseBody를 통한 API 통신의 경우, JSON 데이터를 변환할 때 스크립트 태그를 무력화하는 MessageConverter를 설정해야 합니다.

가장 널리 쓰이는 방법은 네이버에서 만든 Lucy XSS Filter를 적용하거나, Jackson ObjectMapper를 커스터마이징하는 것입니다.

 

Jackson ObjectMapper 커스텀 예시 (설정 파일에 추가):

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        
        // HTML 문자를 이스케이프 처리하는 모듈 등록 (별도 클래스 구현 필요)
        objectMapper.getFactory().setCharacterEscapes(new HtmlCharacterEscapes());
        
        converter.setObjectMapper(objectMapper);
        converters.add(converter);
    }
}

 

③ 정규식(Regex)을 통한 입력 원천 차단 가장 강력한 프론트엔드/백엔드 방어입니다. VO 객체에서 아예 특수문자나 영문 스크립트가 들어오지 못하도록 @Pattern으로 막아버립니다.

public class PrecipitationStationVO {

    // 한글, 영문, 숫자, 공백만 허용 (<, >, script 등 원천 차단)
    @Pattern(regexp = "^[a-zA-Z0-9가-힣\\s]*$", message = "특수문자는 입력할 수 없습니다.")
    private String searchKeyword;
}

 

💡 요약하자면

  1. SQL 방어: MyBatis에서 무조건 #{} 쓴다.
  2. XSS 방어: 입력받을 때 정규식으로 특수문자를 튕겨내거나, 출력할 때 <c:out> / ObjectMapper로 문자열을 치환한다.
반응형