mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-25 22:20:43 +00:00
355 lines
23 KiB
Markdown
355 lines
23 KiB
Markdown
# 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 %}
|