7.8 KiB
Shadow DOM
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿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!
- Descubre The PEASS Family, nuestra colección de NFTs exclusivos.
- Obtén el swag oficial de PEASS y HackTricks.
- Únete al 💬 grupo de Discord o al grupo de Telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de 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.
Básicamente, puedes usar el Shadow DOM para aislar el HTML y CSS de tu componente del resto de la página web. Por ejemplo, si creas IDs de elementos en un Shadow DOM, no entrarán en conflicto con los IDs de elementos en el DOM principal. Cualquier selector CSS que utilices en tu Shadow DOM solo se aplicará dentro del Shadow DOM y no al DOM principal, y cualquier selector que utilices en el DOM principal 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 shadow DOM "abierto" a un elemento, puedes obtener una referencia al shadow DOM con $element.shadowRoot
. Sin embargo, si el shadow DOM está adjunto en modo "cerrado", no puedes obtener una referencia de esta manera. Incluso después de leer toda la documentación para desarrolladores que pude encontrar, todavía tengo algunas dudas sobre el propósito del modo cerrado. Según Google:
Hay otro tipo de shadow DOM llamado modo "cerrado". Cuando creas un árbol de shadow cerrado, JavaScript externo no podrá acceder al DOM interno de tu componente. Esto es similar a cómo funcionan los elementos nativos como
<video>
. JavaScript no puede acceder al shadow DOM de<video>
porque el navegador lo implementa utilizando un shadow root en modo cerrado.
Sin embargo, también afirman:
Los shadow roots cerrados no son muy útiles. Algunos desarrolladores ven 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("texto_de_búsqueda")
penetra dentro de un shadow DOM. Esta función tiene efectivamente 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 obtener 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. Por lo tanto, podemos filtrar el contenido 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 la 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 en las que puedes obtener una inyección dentro de un shadow DOM donde no podrías en una página normal con crossorigin.
Un ejemplo es si tienes algún 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 declararse 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, agregando la propiedad CSS a un elemento y luego utilizando el comando insertHTML
.
CTF
Ver este writeup donde se utilizó esta técnica como un desafío CTF: https://github.com/Super-Guesser/ctf/blob/master/2022/dicectf/shadow.md
Referencias
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿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!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Obtén el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de Telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de hacktricks-cloud.