Secure Coding Guide | 크로스 사이트 스크립트 (XSS)

정의

크로스 사이트 스크립트(cross-site scripting)은 검증되지 않은 외부 입력 값을 응답의 일부로 사용하는 경우 사용자 브라우저에서 악의적인 스크립트가 실행될 수 있는 보안약점이다.

영향

쿠키 정보를 탈취하거나 피싱사이트,불법 광고 사이트 등의 악성 사이트로 이동할 수 있다.

방식

Reflected XSS

URL을 이용하여 스크립트를 피해자에게 직접 노출시켜 공격

Stored XSS

스크립트를 서버의 게시판 등 DB에 저장하여 클라이언트가 열람시 발생

조치 방법

검증되지 않은 값을 웹 브라우저에 보내는 경우(XSS_ATTRIBUTE)

안전하지 않은 jsp 코드 일부

<tr>
  <td colspan="2">${contents}</td>
</tr>

attribute로부터 얻어온 값에 대한 검증을 수행하지 않는다.

안전한 jsp 코드 일부

<tr>
     <td colspan="2"><c:out value="${contents}"/></td>
</tr>

JSTL의 <c:out> 태그를 사용하여 필터링을 수행한다.

javascipt에서 막는 방법

var escapeHtmlMap = {
    "&" : "&amp;",
    "<" : "&lt;",
    ">" : "&gt;",
    '"' : '&quot;',
    "'" : '&#39;',
    "/" : '&#x2F;'
};

String.prototype.escapeHTML = function() {
    return String(this).replace(/[&<>"'\/]/g, function(s) {
        return escapeHtmlMap[s];
    });
};

var text = "안녕하세요! <b>데브쿠아</b>입니다.";

text.escapeHTML();

참고 자료

공격에 이용되는 스크립트/태그

태그 기능
<SCRIPT> 스크립트 코드를 실행
<OBJECT> Active-X 컨트롤을 실행
<APPLET> 자바 애플릿 등을 실행
<EMBED> 객체 등을 포함 (예: 동영상, 음악)
<FORM> 태그를 사용해 기존폼을 수정하여 사용자의 민감한 정보를 빼돌릴 수 있음
<IMG> 이미지를 브라우저 상에서 로드 함
<IFRAME> 웹문서내에특정페이지를로드함

다양한 XSS 패턴 https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

잘못된 조치 방법

String param = request.getParameter("Param");
param = param.replaceAll("<script>", "");
param = param.replaceAll("</script>", "");
  • 필터링을 사용하였으나, 문장을 공백으로 변경하여 우회 공격이 가능하다.
  • 공격시 <sc<script>ript> 로 공격하면 <script>로 되어 스크립트 공격 가능하다.
<c:out value="${param}" escapeXml="false"></c:out>
  • JSTL 라이브러리 c:out을 사용하였으나 escapeXml 옵션을 false 로 한 경우 스크립트 공격에 취약하다.

올바른 조치 방법

String param = request.getParameter("param");
param = param.replaceAll("<", ""); 
param = param.replaceAll(">", "");
param = param.replaceAll("/", "");
param = param.replaceAll(";", "");
param = param.replaceAll(",", "");
param = param.replaceAll("!", "");
param = param.replaceAll("-", "");
  • 단어보단 문자열을 필터링한다.
  • ; , ! – XSS.DOM 방지를 위해 해당 문자열도 수행한다. ;alert()<!– 식으로도 공격한다.
String param = request.getParameter("param");
param = param.replaceAll("<script>", "<scr(X)ipt>");
param = param.replaceAll("</script>", "</scr(X)ipt");
  • 단어등의 문장을 필터링 하는 경우 공백이 아닌 의미없는 문자로 변경한다.
<c:out value="${param}"></c:out>
  • JSTL 라이브러리 c:out을 사용한다. (escapeXml 옵션 기본값 : true)