크로스사이트 스크립팅 (XSS)

신뢰할 수 없는 값을 출력 위치에 맞게 인코딩해 브라우저의 스크립트 실행을 막으세요.

설명

XSS는 웹 애플리케이션의 부적절한 입력 중립화로 인해 사용자 웹 브라우저에서 악의적인 스크립트가 실행될 수 있는 취약점입니다.

잠재적 영향

  • 보호 메커니즘 우회 (우회 공격 가능): 공격자가 악성 스크립트를 통해 사용자 개인 데이터를 탈취하거나 애플리케이션 보호 제한을 우회할 수 있습니다.
  • 애플리케이션 데이터 읽기: 페이지의 민감한 데이터나 스크립트가 접근할 수 있는 쿠키가 유출될 수 있습니다. HttpOnly 쿠키도 피해자의 권한으로 수행되는 동작 자체를 막지는 못합니다.
  • 승인되지 않은 코드 실행 (시스템 손상 가능): 공격자가 브라우저 컨텍스트에서 임의의 코드를 실행해 피해를 유발할 수 있습니다.

해결 방법

  • 출력 시점에 HTML 텍스트, 속성, JavaScript 등 실제 컨텍스트에 맞게 인코딩하세요. HTML 텍스트용 이스케이프가 JavaScript나 URL 검증을 대신하지는 않습니다. 가능하면 자동 이스케이프 템플릿을 사용하세요.
  • 추가로 콘텐츠 보안 정책(CSP)을 설정하여 브라우저가 외부 스크립트 실행을 제한하도록 하여 추가 방어 로직을 적용할 수 있습니다.
  • Spring Security를 추가하는 것만으로 사용자 입력이 자동 인코딩되지는 않습니다. HTML 입력을 허용해야 한다면 검토된 허용 목록 정책으로 정화하세요.

예시

Spring 컨트롤러의 응답이 HTML로 렌더링되는 경우를 가정합니다. HtmlUtils는 org.springframework.web.util.HtmlUtils이며, 아래 인코딩은 HTML 텍스트 위치에 적용합니다.

변경 전

java
// 위험 코드 예문
@RequestMapping("/welcome")
@ResponseBody
public String welcomeMessage(@RequestParam String username) {
    // 사용자 입력을 바로 HTML로 반영
    return "<h1>Welcome, " + username + "!</h1>";
}

변경 후

java
// 안전 코드 예문
@RequestMapping("/welcome")
@ResponseBody
public String welcomeMessage(@RequestParam String username) {
    // 사용자 입력을 HTML의 특수기호로 변환
    String safeUsername = HtmlUtils.htmlEscape(username);
    return "<h1>Welcome, " + safeUsername + "!</h1>";
}

설명:

  • 변경 전: 이 코드에서는 사용자 입력값 username을 HTML에 직접 삽입합니다. 악의적인 스크립트가 포함된 입력값이 전달되면, 해당 스크립트가 브라우저에서 실행될 위험이 있습니다.
  • 변경 후: 이 코드에서는 HtmlUtils.htmlEscape 메서드를 사용하여 사용자 입력을 HTML 텍스트로 인코딩합니다. 이 위치에서는 입력의 마크업이 실행되지 않고 텍스트로 표시됩니다.

관련 CVE

참조