XSS(Cross-Site Scripting)는 웹에서 가장 흔하게 발생하는 보안 취약점 중 하나입니다. Spring Boot 환경에서도 View 처리 방식에 따라 발생 가능성이 있으며, 정확한 이해와 사전 대응이 매우 중요합니다.
이번 포스팅에서는 Java 11 기반 Spring Boot 애플리케이션에서 발생할 수 있는 XSS 취약점의 원리와 대응 전략을 취약한 코드 vs 안전한 코드 형식으로 명확하게 비교합니다. 실제 코드를 기반으로 Request Wrapper 및 XSS Filter 도입 방법까지 설명드리겠습니다.
바로가기 목차
1. XSS란 무엇인가?
XSS(Cross-Site Scripting)는 공격자가 웹페이지에 악의적인 스크립트를 삽입해, 다른 사용자의 브라우저에서 실행되도록 유도하는 대표적인 보안 취약점입니다. 보통 입력 폼, 게시판, 댓글, 검색창 등 사용자 데이터를 렌더링하는 위치에서 발생합니다.
Spring Boot와 같은 Java 기반 웹 프레임워크에서도 Thymeleaf, JSP, JSON 응답 등 다양한 출력 경로에서 XSS가 발생할 수 있으며, 적절한 Escape 처리나 필터링이 없을 경우 심각한 정보 탈취나 세션 하이재킹으로 이어질 수 있습니다.
2. 입력값 검증 없는 출력 - 취약한 코드 예제
사용자의 입력값을 escape 처리 없이 모델에 바로 추가하여 View에서 그대로 출력하는 경우 XSS 공격이 발생할 수 있습니다. 특히 관리자 페이지 또는 공용 게시판에서 매우 치명적입니다.
@Controller
public class CommentController {
@PostMapping("/comment")
public String postComment(@RequestParam String message, Model model) {
// 사용자 입력값을 escape 없이 출력에 사용
model.addAttribute("msg", message);
return "result"; // result.html에서 ${msg} 그대로 출력
}
}
이 코드는 입력값 검증이나 이스케이프 없이 템플릿에 노출되기 때문에 사용자가 ` <script_>alert('XSS')</script_> ` 와 같은 코드를 입력하면 해당 스크립트가 실행되어 다른 사용자에게 악성 행동을 유발할 수 있습니다.
3. XSS 필터 적용으로 안전한 코드 구현
Spring Boot의 Filter와 RequestWrapper를 활용하여 요청 파라미터를 전역에서 감지하고 HTML 특수문자를 이스케이프 처리할 수 있습니다. 이 구조는 View, JSON 등 출력방식과 무관하게 XSS를 일괄 방지할 수 있는 실무적 방식입니다.
// XSSFilter.java – 전역 필터 등록
@Component
public class XSSFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
chain.doFilter(new XSSRequestWrapper(req), response);
}
}
// XSSRequestWrapper.java – 파라미터 정제
public class XSSRequestWrapper extends HttpServletRequestWrapper {
public XSSRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
return cleanXSS(super.getParameter(name));
}
private String cleanXSS(String value) {
if (value != null) {
value = value.replaceAll("&", "&");
value = value.replaceAll("<", "<");
value = value.replaceAll(">", ">");
value = value.replaceAll("\"", """);
value = value.replaceAll("'", "'");
}
return value;
}
}
// WebConfig.java – 필터 등록
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean xssFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean<>();
registration.setFilter(new XSSFilter());
registration.addUrlPatterns("/*");
return registration;
}
}
이 구조는 필터 레벨에서 모든 입력값을 감지하여 HTML 태그를 이스케이프 처리하므로 Spring Boot의 Controller, View, REST 응답 등 출력 방식에 관계없이 XSS 공격을 근본적으로 차단할 수 있는 효과적인 방법입니다.
4. 실무 Q&A – Spring Boot 필터 적용
적용됩니다. XSSRequestWrapper
는 getParameter()
를 통해 요청값을 읽는 모든 컨트롤러와 API 응답에 영향을 미칩니다. 단, JSON Body는 별도 처리 또는 Jackson 모듈과 연동해야 합니다.
기본적으로 th:text
는 자동으로 HTML Escape 처리되지만, th:utext
를 사용할 경우 이스케이프가 되지 않아 취약해질 수 있습니다. 외부 데이터가 utext
로 출력되는 경우 반드시 필터를 병행해야 합니다.
필수는 아니지만 매우 권장됩니다. CSP는 브라우저에서 스크립트 실행을 제어하는 보안 헤더로 XSS를 차단하는 2차 방어선 역할을 합니다. 특히 외부 JS 불허, inline-script 제한 등이 효과적입니다.
스프링 시큐리티 등 다른 필터 체인보다 먼저 등록되지 않으면 실행 순서에서 밀릴 수 있습니다. FilterRegistrationBean
의 setOrder()
를 통해 우선순위를 설정하세요.
5. 마무리 요약 및 체크리스트
XSS는 단순하지만 매우 강력한 보안 취약점으로, 사용자 입력을 출력하는 모든 포인트에서 발생할 수 있습니다. Spring Boot 환경에서도 필터 기반 구조를 통해 효과적으로 대응할 수 있습니다.
- 입력값은 항상 Escape 또는 필터 처리
- Thymeleaf 사용 시 utext 대신 text 사용 권장
- RequestWrapper 기반 XSS 필터 적용
- REST 응답은 ObjectMapper 설정 또는 Escape 처리 필수
- 가능하면 CSP 설정으로 이중 방어 구성
'시큐어코딩 > JAVA' 카테고리의 다른 글
[시큐어코딩] Java에서 NullPointerException 방지하는 안전한 코딩 전략 (2) | 2025.04.09 |
---|---|
[시큐어코딩]Java에서 CSRF(크로스사이트요청위조) 취약점 완벽 대응 가이드 (0) | 2025.04.09 |
[시큐어코딩]Java에서 서버사이드 요청 위조(SSRF) 완벽 대응 가이드 (0) | 2025.04.08 |
[시큐어코딩]Java에서 파일업로드 취약점, 완벽 대응 가이드!! (1) | 2025.04.07 |
[시큐어코딩]Java에서 SQL Injection 대응 완벽 가이드 (0) | 2025.04.04 |