# DOM XSS

{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)

<details>

<summary>Support HackTricks</summary>

* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.

</details>
{% endhint %}

## 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**](https://github.com/wisec/domxsswiki/wiki)
{% endhint %}

**Common sources:**

```javascript
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**](dom-xss.md#open-redirect)                                    | [**Javascript Injection**](dom-xss.md#javascript-injection)                         | [**DOM-data manipulation**](dom-xss.md#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**](dom-xss.md#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**](dom-xss.md#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**](dom-xss.md#link-manipulation)                               | `someDOMElement.innerHTML`                                    | `jQuery.parseHTML()`                                                   |
| `jQuery.globalEval()`                                                            | `someDOMElement.href`                                                               | `someDOMElement.outerHTML`                                    | `$.parseHTML()`                                                        |
| `$.globalEval()`                                                                 | `someDOMElement.src`                                                                | `someDOMElement.insertAdjacentHTML`                           | [**Client-side JSON injection**](dom-xss.md#client-side-sql-injection) |
| **\`\`**[**HTML5-storage manipulation**](dom-xss.md#html-5-storage-manipulation) | `someDOMElement.action`                                                             | `someDOMElement.onevent`                                      | `JSON.parse()`                                                         |
| `sessionStorage.setItem()`                                                       | [**XPath injection**](dom-xss.md#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**](dom-xss.md#cookie-manipulation)      |
| `requestFileSystem()`                                                            | **\`\`**[**Document-domain manipulation**](dom-xss.md#document-domain-manipulation) | `document.implementation.createHTMLDocument()`                | `document.cookie`                                                      |
| `RegExp()`                                                                       | `document.domain`                                                                   | `history.pushState()`                                         | [**WebSocket-URL poisoning**](dom-xss.md#websocket-url-poisoning)      |
| [**Client-Side SQl injection**](dom-xss.md#client-side-sql-injection)            | [**Web-message manipulation**](dom-xss.md#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](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](https://github.com/kevin-mizu/domloggerpp)

## Examples

### Open Redirect

From: [https://portswigger.net/web-security/dom-based/open-redirection](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:

```javascript
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](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:

```javascript
document.cookie
```

### JavaScript Injection

From: [https://portswigger.net/web-security/dom-based/javascript-injection](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:

```javascript
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](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:

```javascript
document.domain
```

### WebSocket-URL poisoning

From: [https://portswigger.net/web-security/dom-based/websocket-url-poisoning](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](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:

```javascript
someDOMElement.href
someDOMElement.src
someDOMElement.action
```

### Ajax request manipulation

From: [https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation](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:

```javascript
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](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:

```javascript
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](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:

```javascript
executeSql()
```

### HTML5-storage manipulation

From: [https://portswigger.net/web-security/dom-based/html5-storage-manipulation](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:

```javascript
sessionStorage.setItem()
localStorage.setItem()
```

### XPath injection

From: [https://portswigger.net/web-security/dom-based/client-side-xpath-injection](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:

```javascript
document.evaluate()
someDOMElement.evaluate()
```

### Client-side JSON injection

From: [https://portswigger.net/web-security/dom-based/client-side-json-injection](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:

```javascript
JSON.parse()
jQuery.parseJSON()
$.parseJSON()
```

### Web-message manipulation

From: [https://portswigger.net/web-security/dom-based/web-message-manipulation](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](https://portswigger.net/web-security/dom-based/controlling-the-web-message-source).

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](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:

```javascript
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](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:

```javascript
requestFileSystem()
RegExp()
```

## Dom Clobbering

{% content-ref url="dom-clobbering.md" %}
[dom-clobbering.md](dom-clobbering.md)
{% endcontent-ref %}

{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)

<details>

<summary>Support HackTricks</summary>

* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.

</details>
{% endhint %}