DOM-based vulnerabilities
๐ What is DOM?
DOM(Document Object Model)์ HTML, XML๊ณผ ๊ฐ์ ๋งํฌ์ ์ธ์ด๋ฅผ ๊ฐ์ฒด ๋ชจ๋ธ(ํธ๋ฆฌ ๋ ธ๋)๋ก ๋ณํํ์ฌ Javascript, Java์ ๊ฐ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์ ์ ๊ทผ ๊ฐ๋ฅํ๊ฒ ํ๋ฉฐ, ์น ๋ธ๋ผ์ฐ์ ์ ๋ ๋๋งํ ์ ์๋๋ก ํด์ฃผ๋ ์ธํฐํ์ด์ค ์ ๋๋ค.
์น ๋ธ๋ผ์ฐ์ ๋์ ์๋ฆฌ
1. ์ฌ์ฉ์๊ฐ ์นํ์ด์ง๋ฅผ ์์ฒญํ๋ฉด ์๋ฒ๋ HTML, CSS, JavaScript๋ฑ์ ๋ฌธ์๋ค์ ๋ธ๋ผ์ฐ์ ๋ก ์๋ตํ๋ค.
2. ์ด๋ ๋ ๋๋ง ์์ง์ ์๋ต๋ฐ์ ๋ฌธ์๋ค์ ํ์ฑํ ๋ค ํธ๋ฆฌ๋ฅผ ์์ฑํ๋ค. ํธ๋ฆฌ๋ฅผ ์์ฑํ๊ธฐ ์ํด ํ์ํ ๋ ๋ชจ๋ธ์ด ๋ฐ๋ก DOM(Document Object Model)๊ณผ CSSOM(Cascading Style Sheets Object Model)์ด๋ค. ๋ ๋๋ง ์์ง์ HTML๊ณผ CSS๋ฅผ ํ์ฑํ์ฌ ๊ฐ๊ฐ DOM tree์ CSSOM tree๋ฅผ ์์ฑํ๋ค.
3. ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ ๋๋ง ์์ง์ด ์๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ง์ ์ํด ํ์ฑ๋๋ค. ํ์ฑํ ๊ฒฐ๊ณผ๋ฅผ ๋
ธ๋ ํธ๋ฆฌ์ ์ ์ฉํ๋ค.
4. ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ ๋ ํธ๋ฆฌ๋ฅผ ์์ฑํ๋ค.
5. ์ด๋ ๊ฒ ์์ฑ๋ ๋ ๋ ํธ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์น ๋ธ๋ผ์ฐ์ ๋ ์ฌ์ฉ์์๊ฒ ํ์ํ ์ ๋ณด๋ฅผ ํ์ด์ง์ ๋ ๋๋งํ๋ค.
๋ ๋๋ง ์์ง์ด ๋ธ๋ผ์ฐ์ ์ ๋ ๋๋ง ํ๊ธฐ ์ํด ํ์ํ ์ด ๊ณผ์ ์ CRP(Critical Rendering Path)๋ผ๊ณ ํ๋ค.
๋ ๋๋ง ์์ง์ด HTML ๋ฌธ์๋ฅผ ํ์ฑํ๊ณ ํ๊ทธ๋ค์ DOM tree๋ก ๋ณํ์ํค๋ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
<html>
<head>
<title>Understanding the Critical Rendering Path</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>Understanding the Critical Rendering Path</h1>
</header>
<main>
<h2>Introduction</h2>
<p>Lorem ipsum dolor sit amet</p>
</main>
<footer>
<small>Copyright 2017</small>
</footer>
</body>
</html>
์์ ๊ฐ์ ํ๊ทธ ๊ตฌ์กฐ๋ฅผ ์๋์ ๊ฐ์ tree node๋ก ๋ณํ์ํจ๋ค.
DOM
์์ ๊ฐ์ ๊ตฌ์กฐ์ ํธ๋ฆฌ๋ ธ๋๋ฅผ DOM์ด๋ผ๊ณ ํ๋ค.
CSSOM
CSSOM๋ ๋ง์ฐฌ๊ฐ์ง๋ก ํธ๋ฆฌ๋ ธ๋๋ก ํํ๋๋ฉฐ, DOM, CSSOM, Javascript๋ฅผ ๋ชจ๋ ํฉ์น ๊ฒฐ๊ณผ๊ฐ ๋ฐ๋ก ๋ ๋ ํธ๋ฆฌ์ด๋ค.
๐ What is taint flow?
๋ง์ DOM ๊ธฐ๋ฐ ์ทจ์ฝ์ ์ ํด๋ผ์ด์ธํธ ์ธก ์ฝ๋๊ฐ ๊ณต๊ฒฉ์๊ฐ ์ ์ดํ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํ๋ ๋ฐฉ๋ฒ๊ณผ ๊ด๋ จ๋ ๋ฌธ์ ๋ก ์ญ์ถ์ ๋ ์ ์์ต๋๋ค.
์ด๋ฌํ ์ทจ์ฝ์ ์ ์
์ฉํ๊ฑฐ๋ ์ํํ๋ ค๋ฉด ๋จผ์ Source์ Sink ๊ฐ์ ํ๋ฆ์ ๋ํ ๊ธฐ๋ณธ์ฌํญ์ ์๊ณ ์์ด์ผ ํฉ๋๋ค.
Source
Source๋ ์ ์ฌ์ ์ผ๋ก ๊ณต๊ฒฉ์๊ฐ ์ ์ดํ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๋ JavaScript ์์ฑ์
๋๋ค.
Source์ ์๋ก๋ location.search ์ฟผ๋ฆฌ ๋ฌธ์์ด์์ ์
๋ ฅ์ ์ฝ๊ธฐ ๋๋ฌธ์ ๊ณต๊ฒฉ์ ์
์ฅ์์ ๋น๊ต์ ์ฝ๊ฒ ์ปจํธ๋กคํ ์ ์์ต๋๋ค.
๊ถ๊ทน์ ์ผ๋ก ๋ชจ๋ ์ฌ์ฐ์ ๊ณต๊ฒฉ์์ ์ ์ฌ์ ์ธ ์์ค์ ์ํด ์ปจํธ๋กค ๋ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ referring URL(eocument.referrer ๋ฌธ์์ด์ ๋
ธ์ถ),์ ์ ์ฟ ํค(document.cookie ๋ฌธ์์ด์ ๋
ธ์ถ), ์น ๋ฉ์์ง๊ฐ ํฌํจ๋ฉ๋๋ค.
Sinks
Sink๋ ์ ์ฌ์ ์ผ๋ก ์ํํ JavaScriptํจ์ ๋๋ DOM ๊ฐ์ฑ๋ก, ๊ณต๊ฒฉ์๊ฐ ์ปจํธ๋กคํ๋ ๋ฐ์ดํฐ๊ฐ ์ ๋ฌ๋ ๊ฒฝ์ฐ ์ํ์ง ์๋ ์ํฅ์ ๋ผ์น ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด eval() ํจ์๋ JavaScript๋ก ์ ๋ฌ๋๋ ์ธ์๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ๋๋ฌธ์ Sink์
๋๋ค.
HTML sink์ ์๋ก๋ ๊ณต๊ฒฉ์๊ฐ ์
์์ ์ธ HTML์ ์ฃผ์
ํ๊ณ JavScript๋ฅผ ์คํ์ํฌ ์ ์๋ document.body.innerHTML๊ฐ ์์ต๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก DOM ๊ธฐ๋ฐ ์ทจ์ฝ์ ์ ์น ์ฌ์ดํธ๊ฐ Source์์ Sink๋ก ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ ๋ ๋ฐ์ํ๋ฉฐ, Sink๋ ํด๋ผ๋ฆฌ์ธํธ ์ธ์ ์ ์ปจํ ์คํธ์์ ์์ ํ์ง ์์ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์์ค๋ location ๊ฐ์ฑ์ ํจ๊ป ์ก์ธ์ค๋๋ URL์ ๋๋ค.
goto = location.hash.slice(1)
if (goto.startsWith('https:')) {
location = goto;
}
Source๊ฐ ์์ ํ์ง ์์ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌ๋๊ธฐ ๋๋ฌธ์ ํด๋น ์ฝ๋๋ DOM ๊ธฐ๋ฐ Open Redirection์ ์ทจ์ฝํฉ๋๋ค.
ํด๋น ์ฝ๋๋ ์๋์ ๊ฐ์ด URL์ ๊ตฌ์ฑํ์ฌ ์ทจ์ฝ์ ์ ์
์ฉํ์ฌ ํผํด์๊ฐ ํด๋น URL์ ๋ฐฉ๋ฌธํ๋ฉด JavaScript๋ location ์์ฑ ๊ฐ์ https://www.evil-user.net ์ผ๋ก ์ค์ ํ์ฌ ํผํด์๋ฅผ ๋ฆฌ๋ค์ด๋ ์
ํฉ๋๋ค.
https://www.innocent-website.com/example#https://www.evil-user.net
-
Common sources
taint-flow์ ์ทจ์ฝ์ ์ ์ฌ์ฉํ ์ ์๋ ์ผ๋ฐ์ ์ธ ์์ค์ ๋๋ค.
document.URL
document.documentURI
document.URLUnencoded
document.baseURI
location
document.cookie
document.referrer
window.name
history.pushState
history.replaceState
localStorage
sessionStorage
IndexedDB (mozIndexedDB, webkitIndexedDB, msIndexedDB)
Database
๋ค์๊ณผ ๊ฐ์ ์ข ๋ฅ์ ๋ฐ์ดํฐ๋ taint-flow ์ทจ์ฝ์ ์ ์ ์ฉํ๋ ์์ค๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
Reflected DOM XSS
JSON ์๋ต ํ์ด์ง
ํด๋น js์คํฌ๋ฆฝํธ ํ์ผ์ ์ฐพ์ ์์ค์ฝ๋ ๋ถ์ ๊ฒฐ๊ณผ eval์ ์ฌ์ฉํ๋๊ฒ์ ํ์ธ
eval ํจ์ ์ฌ์ฉ
๋ฐฑ์ฌ๋์๋ฅผ ์ฝ์ ์ ์ฌ์ดํธ์์ ํํฐ๋ง ์ฒ๋ฆฌํ์ง ์๋๋ค๋๊ฒ์ ํ์ธ ํ \"-alert(1)}// ๊ณต๊ฒฉ๊ตฌ๋ฌธ์ ์ ๋ ฅํ์ฌ XSS ๋ฐ์
//ํ์ด๋ก๋ ์
๋ ฅ์ ์
๋ ฅ๋์ด ๋ค์ด๊ฐ์ง๋๊ฐ
{"results":[],
"searchTerm":"\\"-alert(1)}//" }
XSS ๋ฐ์
Stored DOM XSS
ํด๋น ์น์ฌ์ดํธ๋ XSS๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด JavaScript replace()๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ ๊บพ์ ๊ดํธ๋ฅผ ์ธ์ฝ๋ฉํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ฒซ๋ฒ์งธ ์ธ์๊ฐ ๋ฌธ์์ด์ธ ๊ฒฝ์ฐ ํจ์๋ ์ฒซ๋ฒ์งธ ํญ๋ชฉ๋ง ๋์ฒดํฉ๋๋ค. ์ฃผ์ ์์ ๋ถ๋ถ์ ์ถ๊ฐ ๊บพ์ ๊ดํธ ์ธํธ๋ฅผ ํฌํจํ์ฌ ์ทจ์ฝ์ ์ ์ฐํํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊บพ์ ๊ดํธ๋ ์ธ์ฝ๋ฉ ๋์ง๋ง ์ดํ์ ๋ชจ๋ ๊บพ์ ๊ดํธ๋ ์ํฅ์ ๋น์ง ์์ผ๋ฏ๋ก ํํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฐํํ ์ ์์ต๋๋ค.
<><img src=1 onerror=alert(1)>
ํ์ด๋ก๋ ์
๋ ฅ
Stored XSS
-
Lead to DOM-based vulnerabilities sinks
DOM-based vulnerability | Example sink |
---|---|
DOM XSS | document.write() |
Open redirection | window.location |
Cookie manipulation | document.cookie |
JavaScript injection | eval() |
Document-domain manipulation | document.domain |
WebSocket-URL poisoning | WebSocket() |
Link manipulation | element.src |
Web message manipulation | postMessage() |
Ajax request-header manipulation | setRequestHeader() |
Local file-path manipulation | FileReader.readAsText() |
Client-side SQL injection | ExecuteSql() |
HTML5-storage manipulation | sessionStorage.setItem() |
Client-side XPath injection | document.evaluate() |
Client-side JSON injection | JSON.parse() |
DOM-data manipulation | element.setAttribute() |
Denial of service | RegExp() |
๐ How to Prevent ?
DOM ๊ธฐ๋ฐ ๊ณต๊ฒฉ์ ์ํ์ ์์ ํ ์ ๊ฑฐํ๊ธฐ ์ํด ์ทจํ ์ ์๋ ๋จ์ผ ์กฐ์น๋ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ผ๋ฐ์ ์ผ๋ก DOM ๊ธฐ๋ฐ ์ทจ์ฝ์ ์ ํผํ๋ ๊ฐ์ฅ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ ์ ๋ขฐ ํ ์ ์๋ ์์ค์ ๋ฐ์ดํฐ๊ฐ Sink๋ก ์ ์ก๋๋ ๊ฐ์ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๊ฒ ์
๋๋ค.
์ ํ๋ฆฌ์ผ์ด์
์ ์ํ๋ ๊ธฐ๋ฅ์ด ์ด๋ฌํ ๋์์ ํผํ ์ ์์ ๊ฒฝ์ฐ ํด๋ผ์ด์ธํธ ์ธก ์ฝ๋ ๋ด์์ ๋ฐฉ์ด๊ฐ ๊ตฌํ๋์ด์ผ ํฉ๋๋ค. ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์์ ํ๋ค๊ณ ์๋ ค์ง ์ฝํ
์ธ ๋ง ํ์ฉํ๋ฉด์ ํ์ดํธ๋ฆฌ์คํธ ๊ธฐ๋ฐ์ผ๋ก ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ฆํ ์ ์์ต๋๋ค. ๋ค๋ฅธ ๊ฒฝ์ฐ์๋ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๊ฑฐ๋ ์ธ์ฝ๋ฉ ํด์ผํฉ๋๋ค.
๋ณต์กํ ์์
์ผ ์ ์์ง๋ง ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ ์ปจํ
์คํธ์ ๋ฐ๋ผ JavaScript escaping, HTML ์ธ์ฝ๋ฉ, URL ์ธ์ฝ๋ฉ ๋ฑ์ ์กฐํฉ์ด ํฌํจ๋ ์ ์์ต๋๋ค.