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

8.1 KiB

Shadow DOM

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Informations de base

Shadow DOM fait partie de la suite de fonctionnalités Web Components, qui vise à permettre aux développeurs JS de créer des éléments personnalisés réutilisables avec leur fonctionnalité encapsulée loin du reste du code du site web.

Essentiellement, vous pouvez utiliser le Shadow DOM pour isoler le HTML et le CSS de votre composant du reste de la page web. Par exemple, si vous créez des identifiants d'éléments dans un Shadow DOM, ils ne seront pas en conflit avec les identifiants d'éléments dans le DOM parent. Tous les sélecteurs CSS que vous utilisez dans votre Shadow DOM s'appliqueront uniquement dans le Shadow DOM et non dans le DOM parent, et tous les sélecteurs que vous utilisez dans le parent ne pénétreront pas dans le Shadow DOM.

// creating a shadow DOM
let $element = document.createElement("div");
$shadowDomRef = $element.attachShadow({ mode: "open" }); // open or closed

Normalement, lorsque vous attachez un shadow DOM "ouvert" à un élément, vous pouvez obtenir une référence au shadow DOM avec $element.shadowRoot. Cependant, si le shadow DOM est attaché en mode "fermé", vous ne pouvez pas obtenir de référence de cette manière. Même après avoir lu toute la documentation des développeurs que j'ai pu trouver, je ne suis toujours pas tout à fait clair sur le but du mode fermé. Selon Google:

Il existe une autre variante de shadow DOM appelée mode "fermé". Lorsque vous créez un arbre de shadow fermé, le JavaScript externe ne pourra pas accéder au DOM interne de votre composant. C'est similaire au fonctionnement des éléments natifs tels que <video>. JavaScript ne peut pas accéder au shadow DOM de <video> car le navigateur l'implémente en utilisant un shadow root en mode fermé.

Cependant, ils précisent également:

Les shadow roots fermés ne sont pas très utiles. Certains développeurs considéreront le mode fermé comme une fonctionnalité de sécurité artificielle. Mais soyons clairs, ce n'est pas une fonctionnalité de sécurité.

Accéder au Shadow DOM

window.find() et les sélections de texte

La fonction window.find("texte_recherché") pénètre à l'intérieur d'un shadow DOM. Cette fonction a essentiellement la même fonctionnalité que ctrl-F sur une page web.

Il est possible d'appeler document.execCommand("SelectAll") pour étendre la sélection autant que possible, puis d'appeler window.getSelection() pour retourner le contenu du texte sélectionné à l'intérieur du shadow DOM.

Dans firefox, vous pouvez utiliser getSelection() qui renvoie un objet Selection, où anchorElement est une référence à un élément dans le shadow DOM. Ainsi, nous pouvons exfiltrer le contenu du shadow DOM de la manière suivante:

getSelection().anchorNode.parentNode.parentNode.parentNode.innerHTML

Mais cela ne fonctionne pas dans Chromium.

contenteditable ou injection CSS

Une façon dont nous pourrions interagir avec le shadow DOM est si nous avons une injection HTML ou JS à l'intérieur de celui-ci. Il existe des situations intéressantes où vous pouvez obtenir une injection dans un shadow DOM où vous ne pourriez pas le faire sur une page normale avec crossorigin.

Un exemple est si vous avez des éléments avec l'attribut contenteditable. Il s'agit d'un attribut HTML obsolète et peu utilisé qui déclare que le contenu de cet élément peut être modifié par l'utilisateur. Nous pouvons utiliser des sélections ainsi que l'API document.execCommand pour interagir avec un élément contenteditable et obtenir une injection HTML !

find('selection within contenteditable');

document.execCommand('insertHTML',false,'<svg/onload=console.log(this.parentElement.outerHTML)>')

Peut-être encore plus intéressant, contenteditable peut être déclaré sur n'importe quel élément dans chromium en appliquant une propriété CSS obsolète : -webkit-user-modify:read-write

Cela nous permet de élever une injection CSS/style en une injection HTML, en ajoutant la propriété CSS à un élément, puis en utilisant la commande insertHTML.

CTF

Consultez cette solution où cette technique a été utilisée comme défi CTF : https://github.com/Super-Guesser/ctf/blob/master/2022/dicectf/shadow.md

Références

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥