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

7.8 KiB

Shadow DOM

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

Informações Básicas

Shadow DOM faz parte do conjunto de recursos Web Components, que tem como objetivo permitir que desenvolvedores JS criem elementos personalizados reutilizáveis com sua funcionalidade encapsulada longe do restante do código do site.

Essencialmente, você pode usar o Shadow DOM para isolar o HTML e o CSS do seu componente do restante da página da web. Por exemplo, se você criar IDs de elementos em um shadow DOM, eles não entrarão em conflito com IDs de elementos no DOM pai. Quaisquer seletores CSS que você utilizar no seu shadow DOM serão aplicados apenas dentro do shadow DOM e não ao DOM pai, e quaisquer seletores que você utilizar no pai não penetrarão no shadow DOM.

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

Normalmente, quando você anexa um shadow DOM "aberto" a um elemento, você pode obter uma referência ao shadow DOM com $element.shadowRoot. No entanto, se o shadow DOM estiver anexado em modo "fechado", você não pode obter uma referência dessa maneira. Mesmo depois de ler toda a documentação do desenvolvedor que pude encontrar, ainda estou um pouco confuso sobre o propósito do modo fechado. De acordo com o Google:

Existe outra variação do shadow DOM chamada modo "fechado". Quando você cria uma árvore de sombra fechada, o JavaScript externo não poderá acessar o DOM interno do seu componente. Isso é semelhante ao funcionamento de elementos nativos como <video>. O JavaScript não pode acessar o shadow DOM de <video> porque o navegador o implementa usando uma raiz de sombra em modo fechado.

No entanto, eles também afirmam:

As raízes de sombra fechadas não são muito úteis. Alguns desenvolvedores veem o modo fechado como um recurso de segurança artificial. Mas vamos ser claros, isso não é um recurso de segurança.

Acessando o Shadow DOM

window.find() e seleções de texto

A função window.find("texto_de_pesquisa") penetra dentro de um shadow DOM. Essa função tem efetivamente a mesma funcionalidade que ctrl-F em uma página da web.

É possível chamar document.execCommand("SelectAll") para expandir a seleção o máximo possível e, em seguida, chamar window.getSelection() para retornar o conteúdo do texto selecionado dentro do shadow DOM.

No firefox, você pode usar getSelection(), que retorna um objeto Selection, onde anchorElement é uma referência a um elemento no shadow DOM. Portanto, podemos exfiltrar o conteúdo do shadow DOM da seguinte maneira:

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

Mas isso não funciona no Chromium.

contenteditable ou injeção de CSS

Uma maneira pela qual podemos interagir com o shadow DOM é se tivermos uma injeção de HTML ou JS dentro dele. Existem algumas situações interessantes em que você pode obter uma injeção dentro de um shadow DOM onde não seria possível em uma página normal com crossorigin.

Um exemplo disso é se você tiver quaisquer elementos com o atributo contenteditable. Este é um atributo HTML obsoleto e pouco utilizado que declara que o conteúdo desse elemento pode ser editado pelo usuário. Podemos usar seleções juntamente com a API document.execCommand para interagir com um elemento contenteditable e obter uma injeção de HTML!

find('selection within contenteditable');

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

Talvez ainda mais interessante, contenteditable pode ser declarado em qualquer elemento no chromium aplicando uma propriedade CSS obsoleta: -webkit-user-modify:read-write

Isso nos permite elevar uma injeção de CSS/style para uma injeção de HTML, adicionando a propriedade CSS a um elemento e, em seguida, utilizando o comando insertHTML.

CTF

Verifique este writeup onde essa técnica foi usada como um desafio CTF: https://github.com/Super-Guesser/ctf/blob/master/2022/dicectf/shadow.md

Referências

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