# DOM XSS

{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/files/Xcgr3q6BP5MpWT3hTn6d" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/files/Xcgr3q6BP5MpWT3hTn6d" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/files/aQnEyHWQGyok3qCc92qt" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/files/aQnEyHWQGyok3qCc92qt" 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**](#open-redirect)                                    | [**Javascript Injection**](#javascript-injection)                         | [**DOM-data manipulation**](#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**](#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**](#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**](#link-manipulation)                               | `someDOMElement.innerHTML`                          | `jQuery.parseHTML()`                                         |
| `jQuery.globalEval()`                                                  | `someDOMElement.href`                                                     | `someDOMElement.outerHTML`                          | `$.parseHTML()`                                              |
| `$.globalEval()`                                                       | `someDOMElement.src`                                                      | `someDOMElement.insertAdjacentHTML`                 | [**Client-side JSON injection**](#client-side-sql-injection) |
| **\`\`**[**HTML5-storage manipulation**](#html-5-storage-manipulation) | `someDOMElement.action`                                                   | `someDOMElement.onevent`                            | `JSON.parse()`                                               |
| `sessionStorage.setItem()`                                             | [**XPath injection**](#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**](#cookie-manipulation)      |
| `requestFileSystem()`                                                  | **\`\`**[**Document-domain manipulation**](#document-domain-manipulation) | `document.implementation.createHTMLDocument()`      | `document.cookie`                                            |
| `RegExp()`                                                             | `document.domain`                                                         | `history.pushState()`                               | [**WebSocket-URL poisoning**](#websocket-url-poisoning)      |
| [**Client-Side SQl injection**](#client-side-sql-injection)            | [**Web-message manipulation**](#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:

```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>

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>

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>

**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>

**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:

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

```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>

**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>

**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>

**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>

**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>

**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>

**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>

**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>

**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="/pages/gNyniLZrJHgFKujcY7R2" %}
[Dom Clobbering](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-clobbering.md)
{% endcontent-ref %}

{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/files/Xcgr3q6BP5MpWT3hTn6d" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/files/Xcgr3q6BP5MpWT3hTn6d" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/files/aQnEyHWQGyok3qCc92qt" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/files/aQnEyHWQGyok3qCc92qt" 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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://angelica.gitbook.io/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
