6.9 KiB
Shadow DOM
Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!
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!
- Consigue el merchandising oficial de PEASS & HackTricks
- Descubre La Familia PEASS, nuestra colección de NFTs exclusivos
- Únete al 💬 grupo de Discord o al grupo de telegram o sigue a Twitter 🐦 @carlospolopm.
- Comparte tus trucos de hacking enviando PRs a los repositorios de GitHub de HackTricks y HackTricks Cloud.
Información Básica
Shadow DOM es parte del conjunto de características de 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.
// 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:
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
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, donde anchorElement
es una referencia a un elemento en el shadow DOM. Entonces, podemos exfiltrar contenidos del shadow DOM de la siguiente manera:
getSelection().anchorNode.parentNode.parentNode.parentNode.innerHTML
Pero esto no funciona en Chromium.
contenteditable o inyección de CSS
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!
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
Referencias
Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!
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!
- Consigue el merchandising oficial de PEASS & HackTricks
- Descubre La Familia PEASS, nuestra colección de NFTs exclusivos
- Únete al 💬 grupo de Discord o al grupo de telegram o sigue a Twitter 🐦 @carlospolopm.
- Comparte tus trucos de hacking enviando PRs a los repositorios de github HackTricks y HackTricks Cloud.