티스토리 뷰

 

1. 개요

 

사용자 브라우저에 검증되지 않은 외부 입력값을 허용하여 악의적인 스크립트가 실행 가능한 보안약점

2. 보안대책

 

- 문자열 치환 함수 사용: 문자열 치환 함수를 사용하여 & < > " ' /( ) 등을 & &lt; &gt; &quot; &#x27; &#x2F; &#x28; &#x29;로 치환

- 알려진 보안 라이브러리 사용: JSTL 또는 잘 알려진 크로스 사이트 스크립트 방지 라이브러리(Lucy-XSS-Filter, OWASP ESAPI) 사용

- 정규식 사용: 입력값에 대해 정규식을 이용하여 정확하게 허용되는 패턴의 데이터만 입력되도록 한다.
- XSS 필터 사용: 서버로 들어오는 모든 요청에 대해 XSS 필터를 적용하여 안전한 값만 전달되어 사용되도록 한다.
- 출력값 인코딩, XSS필터 적용: 출력값에 대해 XSSFilter를 적용하여 안전하지 않은 입력값(< > ‘ “ &)에 대해 HTML 인코딩을 적용하여 출력되도록 한다.

3. 코드예제

※ 아래 예제들은 KISA의 소프트웨어 개발보안 가이드, SW 보안약점 진단가이드의 예제를 옮겨놓았습니다.

 

[안전하지 않은 코드 - JAVA]

<% String keyword = request.getParameter("keyword"); %>
//외부 입력값에 대하여 검증 없이 화면에 출력될 경우 공격스크립트가 포함된 URL을 생성 할 수 있어 안전하지 않다.(Reflected XSS)
검색어 : <%=keyword%>
//게시판 등의 입력form으로 외부값이 DB에 저장되고, 이를 검증 없이 화면에 출력될 경우, 공격스크립트가 실행되어 안전하지 않다.(Stored XSS)
검색결과 : $ {m.content}
<script type="text/javascript">
//외부 입력값에 대하여 검증 없이 브라우저에서 실행되는 경우 서버를 거치지 않는 공격스크립트가 포함된 URL을 생성 할 수 있어 안전하지 않다. (DOM 기반 XSS)
document.write("keyword:" + <%=keyword%>);
</script>

 

[안전한 코드 - JAVA]

<% String keyword = request.getParameter("keyword"); %>
// 방법1. 입력값에 대하여 스크립트 공격가능성이 있는 문자열을 치환한다.
keyword = keyword.replaceAll("&", "&amp;");
keyword = keyword.replaceAll("<", "&lt;");
keyword = keyword.replaceAll(">", "&gt;");
keyword = keyword.replaceAll("₩"", "&quot;"");//" 추가
keyword = keyword.replaceAll("'", "&#x27;");
keyword = keyword.replaceAll("/"", "&#x2F;"");//" 추가
keyword = keyword.replaceAll("(", "&#x28;");
keyword = keyword.replaceAll(")", "&#x29;");
검색어 : <%=keyword%>

//방법2. JSP에서 출력값에 JSTL c:out 을 사용하여 처리한다.
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
검색결과 : <c:out value="$ {m.content}"/>
<script type="text/javascript">

//방법3. 잘 만들어진 외부 라이브러리를 활용(NAVER Lucy-XSS-Filter, OWASP ESAPI,OWASP Java-Encoder-Project)
document.write("keyword:"+
	<%=Encoder.encodeForJS(Encoder.encodeForHTML(keyword))%>);
</script>

 

[안전하지 않은 코드 - C#]

string usrInput = Request.QueryString["ID"];
// 외부 입력 값이 검증 없이 화면에 출력 됩니다.
string str = "ID : " + usrinput;
Request.Write(str);

 

[안전한 코드 - C#]

- Antixss 패키지를 이용하여 필터링

string usrInput = Request.QueryString["ID"];
string str = "ID : " + usrinput;
//AntiXss 패키지 등을 이용하여 외부 입력값을 필터링 합니다.
var sanitizedStr = Sanitizer.GetSafeHtmlFragment(str);
quest.Write(sanitizedStr);

 

[안전하지 않은 코드 - C]

int XSS(int argc, char* argv[]) {
unsigned int i = 0;
char data[1024];
…
// cgiFromString으로 받아온 사용자 입력값이 검증 없이 화면에 출력됩니다.
giFromString(“user input”, data, sizeof(data));
printf(cgiOut, “Print user input = %s<br/>”, data);
fprintf(cgiOut, “</body></html>₩n”);
return 0;
}

 

[안전한 코드 - C]

- data에 꺽쇠문자 검사 코드 추가

cgiFromString(“user input”, data, sizeof(data));
// data에 위험한 문자열을 검사하는 코드를 추가한다.
if(strchr(p, ‘<’)) return;
if(strchr(p, ‘>’)) return;
…
fprintf(cgiOut, “Print user input = %s<br/>”, data);
fprintf(cgiOut, “</body></html>₩n”);