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

Cross-Site Scripting (XSS)

설명

이 취약점은 Go의 html/template 패키지에서 제공하는 template.URL()을 사용할 때, 사용자 입력이 들어간 문자열을 escape(이스케이프) 하지 않고 그대로 넘겨서 발생합니다. template.URL()은 "이미 안전한 URL"이라고 가정하고 추가적인 필터링을 하지 않기 때문에, 공격자가 만든 JavaScript 코드나 악성 HTML이 그대로 브라우저에서 실행될 수 있습니다.

공격자는 URL 파라미터, 폼 입력값 등에 <script>, 이벤트 핸들러(onclick 등) 또는 악성 링크를 넣어 서버가 이를 template.URL()로 감싸서 응답하도록 유도할 수 있습니다. 그러면 피해자의 브라우저에서 공격 코드가 실행되어 세션 탈취, 쿠키 탈취, 피싱 페이지 띄우기 등 다양한 공격으로 이어질 수 있습니다.

잠재적 영향

  • 민감 정보 탈취: 공격 스크립트가 브라우저에서 실행되며 쿠키, 세션 토큰, LocalStorage 등 민감 정보를 훔칠 수 있습니다.

  • 사용자 계정 탈취: 세션 탈취를 통해 다른 사용자의 계정으로 로그인된 것처럼 행동할 수 있습니다.

  • 악성 페이지/피싱 유도: 화면에 가짜 로그인 폼이나 결제 페이지를 띄워 사용자가 민감 정보를 입력하도록 속일 수 있습니다.

  • 브라우저 기반 권한 오남용: 사용자 권한으로 API 호출, 게시글 작성, 설정 변경 등 예상치 못한 동작을 수행하게 만들 수 있습니다.

해결 방법

  • template.URL() 사용 최소화: 정말로 "개발자가 안전성을 보장하는 고정 URL"에만 사용하고, 사용자 입력이 섞인 값에는 사용하지 않습니다.

  • html/template의 자동 escaping 활용: 템플릿 파일(.tmpl, .html)을 사용하고, 데이터는 그대로 템플릿에 전달하여 html/template의 기본 escaping 기능을 사용합니다.

  • 사용자 입력 검증(Validation): URL에 들어갈 값(예: id, page 등)은 화이트리스트 방식으로 검증합니다. 예: 숫자만, 특정 패턴만 허용.

  • encoding/escaping: 불가피하게 문자열을 합쳐야 할 경우, 사용자 입력 부분은 template.HTMLEscapeString, url.QueryEscape 등 적절한 escaping 함수를 적용합니다.

  • 신뢰 경계 구분: DB, HTTP 요청, 쿠키 등 "외부에서 들어온 값"은 모두 잠재적으로 악의적이라고 생각하고, template.URL() 같은 신뢰 기반 API에 바로 넘기지 않습니다.

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

취약한 코드

안전한 코드

설명:

  • 취약한 코드: 비준수 코드에서는 사용자 입력값(redirect)을 검증하거나 escape 하지 않고 문자열로 더한 후, template.URL()에 그대로 전달합니다.

  • template.URL()은 "이 값은 이미 개발자가 안전성을 검증한 URL"이라고 가정하므로, 추가적인 HTML/JavaScript escaping을 수행하지 않습니다.

  • 공격자가 redirect 파라미터에 javascript:alert(document.cookie) 같은 값을 넣으면, 생성되는 <a> 태그의 href 속성에 이 값이 그대로 들어가 브라우저에서 실행될 수 있습니다.

  • URL에 HTML 태그 또는 이벤트 핸들러(onclick 등)를 포함시키면, 링크를 클릭하는 순간 XSS가 발생할 수 있습니다.

즉, 사용자 제어 입력을 template.URL()에 직접 넣는 것은 XSS로 바로 이어질 수 있는 위험한 패턴입니다.

  • 안전한 코드: 준수 코드에서는 다음과 같은 방식으로 취약점을 제거합니다.

  1. 사용자 입력 검증(Validation)

    • redirect 값이 비어 있으면 기본값(/home)을 사용합니다.

    • 내부 경로(/로 시작하는 값)만 허용하여, javascript:, data: 같은 위험한 scheme 이나 외부 도메인을 차단합니다.

  2. 적절한 escaping 적용

    • redirect 값을 쿼리스트링에 사용할 수 있도록 url.QueryEscape로 인코딩하여, 특수문자가 URL 구조를 깨뜨리거나 HTML로 해석되지 않도록 합니다.

  3. html/template 자동 escaping 활용

    • HTML을 문자열로 직접 합치지 않고, html/template에 템플릿을 정의한 후 데이터만 전달합니다.

    • html/template는 기본적으로 XSS 방어를 위한 escaping을 수행하므로, 변수를 출력할 때 <, >, " 등 위험 문자가 적절히 치환됩니다.

이렇게 함으로써 사용자 입력에 악성 스크립트가 포함되어 있어도 브라우저에서 코드로 실행되지 않고, 단순한 데이터로 처리되도록 만들어 XSS 위험을 크게 줄입니다.

참조

Last updated