mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
302 lines
22 KiB
Markdown
302 lines
22 KiB
Markdown
# DOM XSS
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|
|
|
|
## Vulnerabilidades DOM
|
|
|
|
Las vulnerabilidades DOM ocurren cuando los datos de **fuentes** controladas por atacantes (como `location.search`, `document.referrer` o `document.cookie`) se transfieren de manera insegura a **sumideros**. Los sumideros son funciones u objetos (por ejemplo, `eval()`, `document.body.innerHTML`) que pueden ejecutar o renderizar contenido dañino si se les proporciona datos maliciosos.
|
|
|
|
- **Fuentes** son entradas que pueden ser manipuladas por atacantes, incluyendo URLs, cookies y mensajes web.
|
|
- **Sumideros** son puntos finales potencialmente peligrosos donde los datos maliciosos pueden llevar a efectos adversos, como la ejecución de scripts.
|
|
|
|
El riesgo surge cuando los datos fluyen de una fuente a un sumidero sin la validación o saneamiento adecuados, lo que permite ataques como XSS.
|
|
|
|
> [!TIP]
|
|
> **Puedes encontrar una lista más actualizada de fuentes y sumideros en** [**https://github.com/wisec/domxsswiki/wiki**](https://github.com/wisec/domxsswiki/wiki)
|
|
|
|
**Fuentes comunes:**
|
|
```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()` | \`\` | \`\` |
|
|
|
|
El **`innerHTML`** sink no acepta elementos `script` en ningún navegador moderno, ni se activarán los eventos `svg onload`. Esto significa que necesitarás usar elementos alternativos como `img` o `iframe`.
|
|
|
|
Este tipo de XSS es probablemente el **más difícil de encontrar**, ya que necesitas mirar dentro del código JS, ver si está **usando** algún objeto cuyo **valor controlas**, y en ese caso, ver si hay **alguna forma de abusar** de él para ejecutar JS arbitrario.
|
|
|
|
## Tools to find them
|
|
|
|
- [https://github.com/mozilla/eslint-plugin-no-unsanitized](https://github.com/mozilla/eslint-plugin-no-unsanitized)
|
|
- Extensión de navegador para verificar todos los datos que llegan a un sink potencial: [https://github.com/kevin-mizu/domloggerpp](https://github.com/kevin-mizu/domloggerpp)
|
|
|
|
## Examples
|
|
|
|
### Open Redirect
|
|
|
|
De: [https://portswigger.net/web-security/dom-based/open-redirection](https://portswigger.net/web-security/dom-based/open-redirection)
|
|
|
|
Las **vulnerabilidades de redirección abierta en el DOM** ocurren cuando un script escribe datos, que un atacante puede controlar, en un sink capaz de iniciar navegación entre dominios.
|
|
|
|
Es crucial entender que ejecutar código arbitrario, como **`javascript:alert(1)`**, es posible si tienes control sobre el inicio de la URL donde ocurre la redirección.
|
|
|
|
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()
|
|
```
|
|
### Manipulación de cookies
|
|
|
|
From: [https://portswigger.net/web-security/dom-based/cookie-manipulation](https://portswigger.net/web-security/dom-based/cookie-manipulation)
|
|
|
|
Las vulnerabilidades de manipulación de cookies basadas en DOM ocurren cuando un script incorpora datos, que pueden ser controlados por un atacante, en el valor de una cookie. Esta vulnerabilidad puede llevar a un comportamiento inesperado de la página web si la cookie se utiliza dentro del sitio. Además, puede ser explotada para llevar a cabo un ataque de fijación de sesión si la cookie está involucrada en el seguimiento de sesiones de usuario. El sumidero principal asociado con esta vulnerabilidad es:
|
|
|
|
Sinks:
|
|
```javascript
|
|
document.cookie
|
|
```
|
|
### Inyección de JavaScript
|
|
|
|
From: [https://portswigger.net/web-security/dom-based/javascript-injection](https://portswigger.net/web-security/dom-based/javascript-injection)
|
|
|
|
Las vulnerabilidades de inyección de JavaScript basadas en DOM se crean cuando un script ejecuta datos, que pueden ser controlados por un atacante, como código JavaScript.
|
|
|
|
Sinks:
|
|
```javascript
|
|
eval()
|
|
Function() constructor
|
|
setTimeout()
|
|
setInterval()
|
|
setImmediate()
|
|
execCommand()
|
|
execScript()
|
|
msSetImmediate()
|
|
range.createContextualFragment()
|
|
crypto.generateCRMFRequest()
|
|
```
|
|
### Manipulación del dominio del documento
|
|
|
|
From: [https://portswigger.net/web-security/dom-based/document-domain-manipulation](https://portswigger.net/web-security/dom-based/document-domain-manipulation)
|
|
|
|
**Las vulnerabilidades de manipulación del dominio del documento** ocurren cuando un script establece la propiedad `document.domain` utilizando datos que un atacante puede controlar.
|
|
|
|
La propiedad `document.domain` juega un **papel clave** en la **aplicación** de la **política de mismo origen** por parte de los navegadores. Cuando dos páginas de diferentes orígenes establecen su `document.domain` al **mismo valor**, pueden interactuar sin restricciones. Aunque los navegadores imponen ciertos **límites** a los valores asignables a `document.domain`, impidiendo la asignación de valores completamente no relacionados con el origen real de la página, existen excepciones. Típicamente, los navegadores permiten el uso de **dominios** **hijos** o **padres**.
|
|
|
|
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** ocurre cuando un script utiliza **datos controlables como la URL objetivo** para una conexión WebSocket.
|
|
|
|
Sinks:
|
|
|
|
El constructor `WebSocket` puede llevar a vulnerabilidades de WebSocket-URL poisoning.
|
|
|
|
### Link manipulation
|
|
|
|
From: [https://portswigger.net/web-security/dom-based/link-manipulation](https://portswigger.net/web-security/dom-based/link-manipulation)
|
|
|
|
**Las vulnerabilidades de manipulación de enlaces basadas en DOM** surgen cuando un script escribe **datos controlables por el atacante en un objetivo de navegación** dentro de la página actual, como un enlace clicable o la URL de envío de un formulario.
|
|
|
|
Sinks:
|
|
```javascript
|
|
someDOMElement.href
|
|
someDOMElement.src
|
|
someDOMElement.action
|
|
```
|
|
### Manipulación de solicitudes Ajax
|
|
|
|
From: [https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation](https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation)
|
|
|
|
**Las vulnerabilidades de manipulación de solicitudes Ajax** surgen cuando un script escribe **datos controlables por el atacante en una solicitud Ajax** que se emite utilizando un objeto `XmlHttpRequest`.
|
|
|
|
Sinks:
|
|
```javascript
|
|
XMLHttpRequest.setRequestHeader()
|
|
XMLHttpRequest.open()
|
|
XMLHttpRequest.send()
|
|
jQuery.globalEval()
|
|
$.globalEval()
|
|
```
|
|
### Manipulación de rutas de archivos locales
|
|
|
|
From: [https://portswigger.net/web-security/dom-based/local-file-path-manipulation](https://portswigger.net/web-security/dom-based/local-file-path-manipulation)
|
|
|
|
**Las vulnerabilidades de manipulación de rutas de archivos locales** surgen cuando un script pasa **datos controlables por el atacante a una API de manejo de archivos** como el parámetro `filename`. Esta vulnerabilidad puede ser explotada por un atacante para construir una URL que, si es visitada por otro usuario, podría llevar a que **el navegador del usuario abra o escriba un archivo local arbitrario**.
|
|
|
|
Sinks:
|
|
```javascript
|
|
FileReader.readAsArrayBuffer()
|
|
FileReader.readAsBinaryString()
|
|
FileReader.readAsDataURL()
|
|
FileReader.readAsText()
|
|
FileReader.readAsFile()
|
|
FileReader.root.getFile()
|
|
FileReader.root.getFile()
|
|
```
|
|
### Inyección SQL del lado del cliente
|
|
|
|
De: [https://portswigger.net/web-security/dom-based/client-side-sql-injection](https://portswigger.net/web-security/dom-based/client-side-sql-injection)
|
|
|
|
**Las vulnerabilidades de inyección SQL del lado del cliente** ocurren cuando un script incorpora **datos controlables por el atacante en una consulta SQL del lado del cliente de manera insegura**.
|
|
|
|
Sinks:
|
|
```javascript
|
|
executeSql()
|
|
```
|
|
### Manipulación de almacenamiento HTML5
|
|
|
|
De: [https://portswigger.net/web-security/dom-based/html5-storage-manipulation](https://portswigger.net/web-security/dom-based/html5-storage-manipulation)
|
|
|
|
**Las vulnerabilidades de manipulación de almacenamiento HTML5** surgen cuando un script **almacena datos controlables por el atacante en el almacenamiento HTML5 del navegador web** (`localStorage` o `sessionStorage`). Aunque esta acción no es inherentemente una vulnerabilidad de seguridad, se vuelve problemática si la aplicación **lee los datos almacenados y los procesa de manera insegura**. Esto podría permitir a un atacante aprovechar el mecanismo de almacenamiento para llevar a cabo otros ataques basados en DOM, como scripting entre sitios e inyección de JavaScript.
|
|
|
|
Sinks:
|
|
```javascript
|
|
sessionStorage.setItem()
|
|
localStorage.setItem()
|
|
```
|
|
### Inyección XPath
|
|
|
|
De: [https://portswigger.net/web-security/dom-based/client-side-xpath-injection](https://portswigger.net/web-security/dom-based/client-side-xpath-injection)
|
|
|
|
**Las vulnerabilidades de inyección XPath basadas en DOM** ocurren cuando un script incorpora **datos controlables por el atacante en una consulta XPath**.
|
|
|
|
Sinks:
|
|
```javascript
|
|
document.evaluate()
|
|
someDOMElement.evaluate()
|
|
```
|
|
### Inyección de JSON del lado del cliente
|
|
|
|
De: [https://portswigger.net/web-security/dom-based/client-side-json-injection](https://portswigger.net/web-security/dom-based/client-side-json-injection)
|
|
|
|
**Las vulnerabilidades de inyección de JSON basadas en DOM** ocurren cuando un script incorpora **datos controlables por el atacante en una cadena que se analiza como una estructura de datos JSON y luego es procesada por la aplicación**.
|
|
|
|
Sinks:
|
|
```javascript
|
|
JSON.parse()
|
|
jQuery.parseJSON()
|
|
$.parseJSON()
|
|
```
|
|
### Manipulación de mensajes web
|
|
|
|
De: [https://portswigger.net/web-security/dom-based/web-message-manipulation](https://portswigger.net/web-security/dom-based/web-message-manipulation)
|
|
|
|
**Las vulnerabilidades de mensajes web** surgen cuando un script envía **datos controlables por el atacante como un mensaje web a otro documento** dentro del navegador. Un **ejemplo** de manipulación de mensajes web vulnerable se puede encontrar en [la Academia de Seguridad Web de PortSwigger](https://portswigger.net/web-security/dom-based/controlling-the-web-message-source).
|
|
|
|
Sinks:
|
|
|
|
El método `postMessage()` para enviar mensajes web puede llevar a vulnerabilidades si el listener de eventos para recibir mensajes maneja los datos entrantes de manera insegura.
|
|
|
|
### Manipulación de datos DOM
|
|
|
|
De: [https://portswigger.net/web-security/dom-based/dom-data-manipulation](https://portswigger.net/web-security/dom-based/dom-data-manipulation)
|
|
|
|
**Las vulnerabilidades de manipulación de datos DOM** surgen cuando un script escribe **datos controlables por el atacante en un campo dentro del DOM** que se utiliza dentro de la UI visible o la lógica del lado del cliente. Esta vulnerabilidad puede ser explotada por un atacante para construir una URL que, si es visitada por otro usuario, puede alterar la apariencia o el comportamiento de la UI del lado del cliente.
|
|
|
|
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)
|
|
|
|
**Las vulnerabilidades de denegación de servicio basadas en DOM** ocurren cuando un script pasa **datos controlables por el atacante de manera insegura a una API problemática de la plataforma**. Esto incluye APIs que, al ser invocadas, pueden llevar a que la computadora del usuario consuma **cantidades excesivas de CPU o espacio en disco**. Tales vulnerabilidades pueden tener efectos secundarios significativos, como que el navegador restrinja la funcionalidad del sitio web al rechazar intentos de almacenar datos en `localStorage` o termine scripts ocupados.
|
|
|
|
Sinks:
|
|
```javascript
|
|
requestFileSystem()
|
|
RegExp()
|
|
```
|
|
## Dom Clobbering
|
|
|
|
|
|
{{#ref}}
|
|
dom-clobbering.md
|
|
{{#endref}}
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|