23 KiB
DOM XSS
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
DOM Vulnerabilities
DOM vulnerabilities occur when data from attacker-controlled sources (like location.search
, document.referrer
, or document.cookie
) is unsafely transferred to sinks. Sinks are functions or objects (e.g., eval()
, document.body.innerHTML
) that can execute or render harmful content if given malicious data.
- Sources are inputs that can be manipulated by attackers, including URLs, cookies, and web messages.
- Sinks are potentially dangerous endpoints where malicious data can lead to adverse effects, such as script execution.
The risk arises when data flows from a source to a sink without proper validation or sanitation, enabling attacks like XSS.
{% hint style="info" %} You can find a more updated list of sources and sinks in https://github.com/wisec/domxsswiki/wiki {% endhint %}
Common 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
Common 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 doesn't accept script
elements on any modern browser, nor will svg onload
events fire. This means you will need to use alternative elements like img
or iframe
.
This kind of XSS is probably the hardest to find, as you need to look inside the JS code, see if it's using any object whose value you control, and in that case, see if there is any way to abuse it to execute arbitrary JS.
Tools to find them
- https://github.com/mozilla/eslint-plugin-no-unsanitized
- Browser extension to check every data taht reaches a potential sink: https://github.com/kevin-mizu/domloggerpp
Examples
Open Redirect
From: https://portswigger.net/web-security/dom-based/open-redirection
Open redirect vulnerabilities in the DOM occur when a script writes data, which an attacker can control, into a sink capable of initiating navigation across domains.
It's crucial to understand that executing arbitrary code, such as javascript:alert(1)
, is possible if you have control over the start of the URL where the redirection occurs.
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 occur when a script incorporates data, which can be controlled by an attacker, into the value of a cookie. This vulnerability can lead to unexpected behavior of the webpage if the cookie is utilized within the site. Additionally, it can be exploited to carry out a session fixation attack if the cookie is involved in tracking user sessions. 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 vulnerabilities are created when a script runs data, which can be controlled by an attacker, as JavaScript code.
Sinks:
eval()
Function() constructor
setTimeout()
setInterval()
setImmediate()
execCommand()
execScript()
msSetImmediate()
range.createContextualFragment()
crypto.generateCRMFRequest()
Document-domain manipulation
From: https://portswigger.net/web-security/dom-based/document-domain-manipulation
Document-domain manipulation vulnerabilities occur when a script sets the document.domain
property using data that an attacker can control.
The document.domain
property plays a key role in the enforcement of the same-origin policy by browsers. When two pages from different origins set their document.domain
to the same value, they can interact without restrictions. Although browsers impose certain limits on the values assignable to document.domain
, preventing the assignment of completely unrelated values to the actual page origin, exceptions exist. Typically, browsers permit the use of child or parent domains.
Sinks:
document.domain
WebSocket-URL poisoning
From: https://portswigger.net/web-security/dom-based/websocket-url-poisoning
WebSocket-URL poisoning occurs when a script utilizes controllable data as the target URL for a WebSocket connection.
Sinks:
The WebSocket
constructor can lead to WebSocket-URL poisoning vulnerabilities.
Link manipulation
From: https://portswigger.net/web-security/dom-based/link-manipulation
DOM-based link-manipulation vulnerabilities arise when a script writes attacker-controllable data to a navigation target within the current page, such as a clickable link or the submission URL of a form.
Sinks:
someDOMElement.href
someDOMElement.src
someDOMElement.action
Ajax request manipulation
From: https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation
Ajax request manipulation vulnerabilities arise when a script writes attacker-controllable data into an Ajax request that is issued using an XmlHttpRequest
object.
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 arise when a script passes attacker-controllable data to a file-handling API as the filename
parameter. This vulnerability can be exploited by an attacker to construct a URL that, if visited by another user, could lead to the user's browser opening or writing an arbitrary local file.
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 occur when a script incorporates attacker-controllable data into a client-side SQL query in an unsafe way.
Sinks:
executeSql()
HTML5-storage manipulation
From: https://portswigger.net/web-security/dom-based/html5-storage-manipulation
HTML5-storage manipulation vulnerabilities arise when a script stores attacker-controllable data in the web browser's HTML5 storage (localStorage
or sessionStorage
). While this action is not inherently a security vulnerability, it becomes problematic if the application subsequently reads the stored data and processes it unsafely. This could allow an attacker to leverage the storage mechanism to conduct other DOM-based attacks, such as cross-site scripting and JavaScript injection.
Sinks:
sessionStorage.setItem()
localStorage.setItem()
XPath injection
From: https://portswigger.net/web-security/dom-based/client-side-xpath-injection
DOM-based XPath-injection vulnerabilities occur when a script incorporates attacker-controllable data into an 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 occur when a script incorporates attacker-controllable data into a string that is parsed as a JSON data structure and then processed by the application.
Sinks:
JSON.parse()
jQuery.parseJSON()
$.parseJSON()
Web-message manipulation
From: https://portswigger.net/web-security/dom-based/web-message-manipulation
Web-message vulnerabilities arise when a script sends attacker-controllable data as a web message to another document within the browser. An example of vulnerable Web-message manipulation can be found at PortSwigger's Web Security Academy.
Sinks:
The postMessage()
method for sending web messages can lead to vulnerabilities if the event listener for receiving messages handles the incoming data in an unsafe way.
DOM-data manipulation
From: https://portswigger.net/web-security/dom-based/dom-data-manipulation
DOM-data manipulation vulnerabilities arise when a script writes attacker-controllable data to a field within the DOM that is utilized within the visible UI or client-side logic. This vulnerability can be exploited by an attacker to construct a URL that, if visited by another user, can alter the appearance or behaviour of the client-side 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 occur when a script passes attacker-controllable data unsafely to a problematic platform API. This includes APIs that, when invoked, can lead the user's computer to consume excessive amounts of CPU or disk space. Such vulnerabilities can have significant side effects, such as the browser restricting the website's functionality by rejecting attempts to store data in localStorage
or terminating busy scripts.
Sinks:
requestFileSystem()
RegExp()
Dom Clobbering
{% content-ref url="dom-clobbering.md" %} dom-clobbering.md {% endcontent-ref %}
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.