DOM XSS

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

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.

You can find a more updated list of sources and sinks in https://github.com/wisec/domxsswiki/wiki

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:

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

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()

FileReader.readAsFile()

someDOMElement.backgroundImage

constructor()

XMLHttpRequest.setRequestHeader()

FileReader.root.getFile()

someDOMElement.cssText

init()

XMLHttpRequest.open()

FileReader.root.getFile()

someDOMElement.codebase

index()

XMLHttpRequest.send()

someDOMElement.innerHTML

jQuery.parseHTML()

jQuery.globalEval()

someDOMElement.href

someDOMElement.outerHTML

$.parseHTML()

$.globalEval()

someDOMElement.src

someDOMElement.insertAdjacentHTML

someDOMElement.action

someDOMElement.onevent

JSON.parse()

sessionStorage.setItem()

document.write()

jQuery.parseJSON()

localStorage.setItem()

document.evaluate()

document.writeln()

$.parseJSON()

**[**`Denial of Service`**](dom-xss.md#denial-of-service)**

someDOMElement.evaluate()

document.title

requestFileSystem()

document.implementation.createHTMLDocument()

document.cookie

RegExp()

document.domain

history.pushState()

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

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()

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.

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

Dom Clobbering
Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Last updated