크로스사이트 스크립트

IT 위키

XSS : Cross-Site Scripting

개요[편집 | 원본 편집]

웹 페이지에 악의적인 스크립트를 포함시켜 사용자 측에서 실행되게 유도하는 공격
  • 일반적으로 서버가 아닌 클라이언트에 대한 공격이다.

예를 들어, 검증되지 않은 외부 입력이 동적 웹페이지 생성에 사용될 경우, 전송된 동적 웹페이지를 열람하는 접속자의 권한으로 부적절한 스크립트가 수행되어 정보유출 등의 공격을 유발할 수 있다.

보안 대책[편집 | 원본 편집]

  • 외부입력값에 스크립트가 삽입되지 못하도록 문자변환 함수 또는 메서드를 사용하여 < > & “ 등을 < > & " 로 치환
  • HTML태그를 허용하는 게시판에서는 허용되는 HTML 태그들을 화이트리스트로 만들어 해당 태그만 지원하도록 한다.

종류[편집 | 원본 편집]

저장 XSS[편집 | 원본 편집]

웹 애플리케이션 취약점이 있는 웹 서버에 악성 스크립트를 저장해 놓는 방법

저장 XSS 공격.png

  • 공격 절차
    1. 게시판, 프로필, 댓글 등에 악성 스크립트를 삽입
    2. 사용자가 사이트를 방문하여 저장되어 있는 페이지에 정보를 요청할 때(게시판 글 읽기 등)
    3. 서버는 악성 스크립트를 사용자에게 전달하여 사용자 브라우저에서 스크립트가 실행되면서 공격

반사 XSS[편집 | 원본 편집]

웹 애플리케이션의 지정된 변수를 그대로 출력할 때 발생하는 취약점을 이용

반사 XSS 공격.png

  • ex) http://www.server.com/search/?q=<script>alert(document.cookie)</script>&x=0&y=0
    • 결과) <script>alert(document.cookie)</script>에 대한 검색결과입니다!
    • 스크립트가 실행된다.
  • 공격 절차
    1. 취약점이 있는 A사이트를 발견
    2. 민감한 정보를 획득할 수 있는 공격용 악성 URL을 생성
    3. 공격자는 이 URL을 이메일, SMS 등에 포함하여 배포하고 클릭 유도
    4. 피해자가 URL을 클릭하면, 바로 공격 스크립트가 피해자로 반사되어 A 사이트에 관련된 민감한 정보(ID/패스워드, 세션 정보)를 공격자에게 전송


코드 예제[편집 | 원본 편집]

  • 안전하지 않은 코드 : Java 예제
파라미터(id)에 <script>alert(document.cookie);</script>와 같은 스크립트 코드가 입력되고, 이 값을 그대로 출력에 사용하는 경우, 공격자는 공격코드를 이용하여 피해자의 쿠키정보를 빼돌릴 수 있다.
<% String customerID = request.getParameter(id); %>
요청한 사용자: <%=customerID%>
처리결과: ${m.content}
  • 안전한 코드 : Java 예제
서버의 처리 결과를 사용자 화면에 출력하는 경우, 문자열 치환 함수를 이용하여 출력값을 HTML 인코딩하거나, JSTL을 이용하여 출력 또는 잘 만들어진 외부 XSSFilter 라이브러리를 활용하여 출력하는 것이 안전하다.
// 방법1. 서블릿에서 출력값에 HTML인코딩
String cleanData = input.replaceAll(<, &lt).replaceAll(>, &gt);
out.println(cleanData);

// 방법2. JSP에서 출력값에 JSTL HTML 인코딩
<textarea name=content>${ fn:escapeXml(model.content) }</textarea>

// 방법3. JSP에서 출력값에 JSTL Core 출력 포맷을 사용하여 텍스트로 처리
<textarea name=content><c:out value=${model.content}/></textarea>

// 방법4. 잘 만들어진 외부 XSSFilter 라이브러리를 활용하여 출력값에 필터링
XssFilter filter = XssFilter.getInstance(lucy-xss-superset.xml);
out.append(filter.doFilter(data));
  • 안전하지 않은 코드 : C# 예제
파라미터(ID) 값에 서버로 전송하는 스크립트 코드가 입력되고, 이 값이 검증 없이 그대로 사용되면 부적절한 스크립트가 수행되어 정보유출 등의 공격을 유발할 수 있다.
public void Execute()
{
  String userid = Request.QueryString[ID];
  String query = Select * From Products Where ProductID =  + userid;
  Request.Write(query);
}
  • 안전한 코드 : C# 예제
외부 입력 문자열에서 replace() 메서드를 사용하여 <, >, &, “, ‘, / 같이 스크립트 생성에 사용되는 문자열을 <, >, &, ", ', / 등으로 변경하면, 파라미터 userid에 악성스크립트가 포함되더라도 스크립트가 실행되지 않는다.
public void Execute()
{
  String userid = Request.QueryString[ID];
  if (userid != null && !””.Equals(userid))
  {
    userid = userid.Replace(<, &lt;);
    userid = userid.Replace(>, &gt;);
    userid = userid.Replace(&, %amp;);
    userid = userid.Replace(“””, &#quot;);
    userid = userid.Replace(“’”, &#x27;);
    userid = userid.Replace(/, &#x2F;);
  }
  String query = Select * From Products Where ProductID =  + usrinput;
  Request.Write(query);
}

출처[편집 | 원본 편집]