hacktricks/pentesting-web/xss-cross-site-scripting/shadow-dom.md

84 lines
6.9 KiB
Markdown
Raw Normal View History

# Shadow DOM
<details>
<summary><strong>Aprende hacking en AWS de cero a héroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Otras formas de apoyar a HackTricks:
* Si quieres ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF**, consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Consigue el [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sigue** a **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de GitHub de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## Información Básica
Shadow DOM es parte del conjunto de características de [Web Components](https://developer.mozilla.org/en-US/docs/Web/Web\_Components), que tiene como objetivo permitir a los desarrolladores de JS crear elementos personalizados reutilizables con su funcionalidad encapsulada lejos del resto del código del sitio web.
Esencialmente, puedes usar Shadow DOM para **aislar el HTML y CSS de tu componente del resto de la página web**. Por ejemplo, si creas identificadores de elementos en un shadow DOM, estos **no entrarán en conflicto con los identificadores de elementos en el DOM padre**. Cualquier selector de CSS que utilices en tu shadow DOM solo se aplicará dentro del shadow DOM y no al DOM padre, y cualquier selector que utilices en el padre no penetrará dentro del shadow DOM.
```js
// creating a shadow DOM
let $element = document.createElement("div");
$shadowDomRef = $element.attachShadow({ mode: "open" }); // open or closed
```
Normalmente, cuando adjuntas un **"open" shadow DOM a un elemento**, puedes obtener una referencia al shadow DOM con **`$element.shadowRoot`**. Sin embargo, si el shadow DOM se adjunta en modo **"closed"**, **no puedes obtener una referencia** de esta manera. Incluso después de leer toda la documentación para desarrolladores que pude encontrar, todavía no tengo del todo claro el propósito del modo cerrado. [Según Google](https://developers.google.com/web/fundamentals/web-components/shadowdom):
> Hay otra variante de shadow DOM llamada modo "closed". Cuando creas un árbol shadow **closed**, **el JavaScript externo no podrá acceder al DOM interno de tu componente**. Esto es similar a cómo funcionan elementos nativos como `<video>`. JavaScript no puede acceder al shadow DOM de `<video>` porque el navegador lo implementa usando una raíz shadow en modo cerrado.
Sin embargo, también afirman:
> Las raíces shadow cerradas no son muy útiles. Algunos desarrolladores verán el modo cerrado como una **característica de seguridad artificial**. Pero seamos claros, **no** es una característica de seguridad.
## Accediendo al Shadow DOM
### window.find() y selecciones de texto <a href="#introducing-windowfind-and-text-selections" id="introducing-windowfind-and-text-selections"></a>
La función **`window.find("search_text")` penetra dentro de un shadow DOM**. Esta función efectivamente tiene la misma funcionalidad que ctrl-F en una página web.
Es posible llamar a **`document.execCommand("SelectAll")`** para expandir la selección **tanto como sea posible** y luego llamar a **`window.getSelection()`** para **devolver el contenido** del texto seleccionado dentro del shadow DOM.
En **firefox** puedes usar `getSelection()`, que devuelve un objeto [Selection](https://developer.mozilla.org/en-US/docs/Web/API/Selection), donde `anchorElement` es una **referencia a un elemento en el shadow DOM**. Entonces, podemos exfiltrar contenidos del shadow DOM de la siguiente manera:
```js
getSelection().anchorNode.parentNode.parentNode.parentNode.innerHTML
```
Pero esto no funciona en Chromium.
### contenteditable o inyección de CSS <a href="#contenteditable-or-css-injection" id="contenteditable-or-css-injection"></a>
Una forma en que podríamos interactuar con el shadow DOM es si tenemos una **inyección de HTML o JS dentro de él**. Hay algunas situaciones interesantes donde puedes obtener una inyección dentro de un shadow DOM donde no podrías en una página crossorigin normal.
Un ejemplo es si tienes cualquier **elemento con el atributo `contenteditable`**. Este es un atributo HTML obsoleto y poco utilizado que declara que el **contenido de ese elemento puede ser editado por el usuario**. ¡Podemos usar selecciones junto con la API **`document.execCommand`** para interactuar con un elemento contenteditable y obtener una inyección de HTML!
```js
find('selection within contenteditable');
document.execCommand('insertHTML',false,'<svg/onload=console.log(this.parentElement.outerHTML)>')
```
Quizás aún más interesante, **`contenteditable`** puede ser declarado en cualquier elemento en chromium aplicando una **propiedad CSS obsoleta: `-webkit-user-modify:read-write`**
Esto nos permite **elevar una inyección de CSS/estilo a una inyección de HTML**, añadiendo la propiedad CSS a un elemento y luego utilizando el comando `insertHTML`.
## CTF
Revisa este informe donde esta técnica fue utilizada como un desafío de CTF: [https://github.com/Super-Guesser/ctf/blob/master/2022/dicectf/shadow.md](https://github.com/Super-Guesser/ctf/blob/master/2022/dicectf/shadow.md)
## Referencias
* [https://blog.ankursundara.com/shadow-dom/](https://blog.ankursundara.com/shadow-dom/)
<details>
<summary><strong>Aprende hacking en AWS de cero a héroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Otras formas de apoyar a HackTricks:
* Si quieres ver a tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF** revisa los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Consigue el [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sigue** a **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Comparte tus trucos de hacking enviando PRs a los repositorios de github** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>