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

Cross-Site Scripting (XSS)

설명

Go 웹 애플리케이션에서 text/template 패키지는 HTML 이스케이프(escape)를 자동으로 해주지 않습니다. 이 상태에서 사용자 입력이나 외부 데이터(Todo 제목, 댓글, 프로필 정보 등)를 그대로 HTML에 렌더링하면, 데이터 안에 포함된 <script>...</script> 같은 자바스크립트 코드가 그대로 브라우저에서 실행될 수 있습니다. 공격자는 저장된 데이터나 파라미터에 악성 스크립트를 넣어 다른 사용자의 브라우저에서 실행되도록 만들어 세션 탈취, 페이지 변조, 피싱 등 다양한 공격을 수행할 수 있습니다.

잠재적 영향

  • 세션 탈취 및 계정 탈취 (세션 하이재킹): 공격자가 피해자의 브라우저에서 실행된 스크립트를 통해 쿠키, 토큰 등을 탈취하여 계정을 가로챌 수 있습니다.

  • 악성 스크립트 실행 (브라우저 내 코드 실행): 피해자 브라우저에서 임의의 자바스크립트가 실행되어 키로깅, 내부 API 호출, 브라우저 내 데이터 접근 등이 가능합니다.

  • 페이지 변조 및 피싱 (UI 위조): 화면 내용을 조작해 가짜 로그인 폼, 결제 창 등을 띄워 사용자에게 민감 정보를 입력하도록 속일 수 있습니다.

  • 데이터 조작 (클라이언트 측 데이터 위변조): DOM이나 화면상의 데이터가 임의로 변경되어 잘못된 정보 표시, 추가 요청 전송 등의 문제가 발생할 수 있습니다.

해결 방법

  • text/template 대신 html/template 사용: HTML을 렌더링하는 경우 항상 html/template 패키지를 사용합니다. 이 패키지는 기본적으로 HTML 이스케이프를 수행해 XSS를 예방합니다.

  • 신뢰할 수 없는 데이터는 모두 escape: 사용자 입력, DB/파일에서 읽어온 값 등은 HTML, JavaScript, URL, CSS 등 컨텍스트에 맞게 적절히 이스케이프해야 합니다. Go에서는 html/template가 대부분의 HTML 컨텍스트를 안전하게 처리합니다.

  • 템플릿 내에서 template.JS 등 raw 출력 최소화: 정말 불가피하게 raw JS를 출력해야 한다면, 데이터가 완전히 신뢰 가능하고 검증된 경우에만 사용합니다.

  • Content Security Policy(CSP) 적용: HTTP 응답 헤더에 적절한 CSP를 설정해 인라인 스크립트 실행, 외부 스크립트 로드 등을 제한하면 XSS 성공 시 피해를 줄일 수 있습니다.

  • 입력 검증 및 출력 인코딩 병행: 입력 단계에서 위험한 패턴을 1차적으로 필터링하고, 출력 시점에 컨텍스트 기반 인코딩(escaping)을 적용합니다.

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

취약한 코드

안전한 코드

설명:

  • 취약한 코드: text/template 패키지는 HTML에 특화된 이스케이프 기능이 없습니다. 위 취약 코드에서는 {{.Content}}에 사용자가 입력한 값이 그대로 들어가며, 예를 들어 content=<script>alert('xss')</script> 와 같이 요청을 보내면 이 스크립트가 브라우저에서 그대로 실행됩니다. 즉, 템플릿이 HTML 문서를 생성하면서 신뢰할 수 없는 입력을 적절히 중화(neutralize)하지 않아 XSS 공격이 가능합니다.

  • 안전한 코드: html/template 패키지는 HTML 컨텍스트에 맞게 <, >, ", & 등의 문자를 자동으로 이스케이프합니다. 동일한 템플릿이라도 {{.Content}}<script>alert('xss')</script>가 들어오면, 실제 응답에는 &lt;script&gt;alert('xss')&lt;/script&gt; 형태로 출력되어 브라우저가 태그가 아닌 단순 텍스트로 처리합니다. 따라서 사용자 입력에 악성 스크립트가 포함되어 있어도 실행되지 않아 XSS 취약점이 예방됩니다.

참조

Last updated