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

Cross-site Scripting (XSS)

설명

크로스 사이트 스크립팅(XSS)은 사용자 입력 값이 HTML, JavaScript 등 웹 페이지로 출력될 때 적절한 escaping(이스케이프 처리) 없이 그대로 포함되어 발생하는 취약점입니다. 이 규칙은 Go의 html/template 패키지에서 template.JS()를 사용할 때, 포맷팅된 문자열이나 문자열 더하기(+)로 만든 값에 사용자 입력이 섞여 들어가는데도 escape 없이 그대로 JavaScript로 사용하는 패턴을 찾습니다. 공격자는 URL 파라미터, 폼 입력 등에 악의적인 스크립트를 넣어, 그 내용이 template.JS()를 통해 그대로 브라우저에서 실행되도록 만들 수 있습니다.

잠재적 영향

  • 스크립트 실행을 통한 세션 탈취: 공격자가 악성 JavaScript를 삽입해 사용자의 세션 쿠키, 토큰 등을 훔칠 수 있습니다.

  • 웹 페이지 변조: 악성 스크립트로 화면 내용을 바꾸거나 가짜 입력 폼을 만들어 사용자에게 추가 정보를 입력하도록 유도할 수 있습니다.

  • 기타 브라우저 기반 공격: 키로깅(입력 값 가로채기), CSRF 토큰 탈취, 브라우저 저장소(localStorage, sessionStorage) 접근 등 다양한 2차 공격이 가능합니다.

해결 방법

  • template.JS 사용 최소화: 정말로 신뢰할 수 있는 정적 JavaScript 코드에만 template.JS를 사용하고, 사용자 입력이 섞일 수 있는 경우에는 사용하지 않습니다.

  • 자동 escaping 활용: html/template의 기본 기능을 사용해 {{.}} 같은 placeholder에 값을 바인딩하면, HTML/JS 컨텍스트에 맞게 자동으로 escape되도록 템플릿을 설계합니다.

  • 사용자 입력 검증 및 정규화: URL 파라미터, 폼 값 등 사용자 입력은 화이트리스트 기반 검증(허용 문자/패턴만 허용)을 적용합니다.

  • JavaScript와 데이터 분리: JavaScript 코드 안에 문자열 더하기로 HTML을 직접 만드는 방식 대신, 템플릿에서 구조를 정의하고, 데이터는 안전하게 바인딩하는 방식으로 구성합니다.

  • Content Security Policy(CSP) 적용: 가능하다면 CSP 헤더를 설정해 inline script 실행을 제한하고, XSS 발생 시 피해 범위를 줄입니다.

취약한 코드 및 안전한 코드 예시

취약한 코드

안전한 코드

설명:

  • 취약한 코드: 위 취약 코드에서는

  • 사용자 입력(userID)을 검증 없이 그대로 사용하고,

  • 문자열 더하기로 JavaScript 코드 문자열을 만든 뒤,

  • template.JS로 감싸서 escape를 하지 않은 채 <script> 안에 넣습니다.

template.JS는 "이 문자열은 이미 안전한 JS 코드"라고 가정하고 아무런 escaping을 하지 않기 때문에, 공격자가 userID에 '</h1><script>alert(1)</script> 같은 값을 넣으면 그대로 브라우저에서 실행됩니다. 따라서 전형적인 XSS 취약점이 발생합니다.

  • 안전한 코드: 안전한 코드에서는

  • html/template의 템플릿을 사용해 HTML 구조를 정의하고,

  • 데이터(UserID)는 템플릿의 {{.UserID}} 자리에 바인딩하여 자동 escape를 맡깁니다.

  • JavaScript 코드 안에 직접 사용자 입력을 이어 붙이지 않고, data-* 속성 등 HTML 속성으로 데이터를 전달한 후 JS에서 DOM을 통해 읽습니다.

이 방식은 템플릿 엔진이 HTML/속성 컨텍스트에 맞춰 적절하게 특수문자를 escape하기 때문에, 공격자가 스크립트를 주입하려고 해도 그대로 텍스트로만 취급되어 실행되지 않습니다. 또한 template.JS를 사용하지 않아, "이미 안전한 JS"라고 잘못 가정하는 상황을 제거합니다.

참조

Last updated