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

8.9 KiB
Raw Blame History

Shadow DOM

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

基本情報

Shadow DOMは、Web Componentsの機能スイートの一部であり、JS開発者が再利用可能なカスタム要素を作成し、その機能をウェブサイトの他のコードから隔離することを目的としています。

基本的に、Shadow DOMを使用すると、コンポーネントのHTMLとCSSをウェブページの他の部分から分離することができます。たとえば、Shadow DOMで要素のIDを作成する場合、それらは親DOM内の要素のIDと競合しません。Shadow DOMで使用するCSSセレクタは、Shadow DOM内にのみ適用され、親DOMには適用されず、親で使用するセレクタはShadow DOM内には浸透しません。

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

通常、要素に**「オープン」シャドウ DOMをアタッチすると、$element.shadowRootを使用してシャドウ DOMへの参照を取得できます。ただし、シャドウ DOMが「クローズド」**モードでアタッチされている場合、この方法ではそれに対する参照を取得することはできません。開発者ドキュメントをすべて読んだ後でも、私はクローズドモードの目的について少し曖昧なままです。Googleによると

「クローズド」モードと呼ばれる別のシャドウ DOMのバリエーションがあります。クローズドシャドウツリーを作成すると、外部のJavaScriptはコンポーネントの内部DOMにアクセスできなくなります。これは、<video>のようなネイティブ要素の動作と似ています。ブラウザはクローズドモードのシャドウルートを使用して<video>を実装しているため、JavaScriptは<video>のシャドウ DOMにアクセスできません。

ただし、彼らはまた次のように述べています:

クローズドシャドウルートはあまり役に立ちません。一部の開発者は、クローズドモードを人工的なセキュリティ機能と見なすかもしれません。しかし、はっきり言って、それはセキュリティ機能ではありません

シャドウ DOMへのアクセス

window.find() とテキスト選択

関数**window.find("search_text")はシャドウ DOM内に侵入**します。この関数は、ウェブページ上のctrl-Fと同じ機能を持っています。

document.execCommand("SelectAll")を呼び出して選択範囲を可能な限り拡大し、その後**window.getSelection()を呼び出してシャドウ DOM内の選択されたテキストの内容を返す**ことができます。

Firefoxでは、getSelection()を使用して、Selectionオブジェクトを取得できます。anchorElementシャドウ DOM内の要素への参照です。したがって、シャドウ DOMの内容を以下のように外部に漏洩させることができます

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

しかし、これはChromiumでは機能しません。

contenteditableまたはCSSインジェクション

シャドウDOMとのやり取りを行う方法の一つは、それ自体の内部にHTMLまたはJSインジェクションがある場合です。通常のクロスオリジンページではできないようなシャドウDOM内でのインジェクションを取得できる興味深い状況がいくつかあります。

例えば、contenteditable属性を持つ要素がある場合です。これは非推奨であまり使用されていないHTML属性で、その要素のコンテンツをユーザーが編集可能にすることを宣言します。選択と**document.execCommand** APIを使用して、contenteditable要素とのやり取りを行い、HTMLインジェクションを取得することができます

find('selection within contenteditable');

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

おそらくさらに興味深いことに、**contenteditableは、廃止予定のCSSプロパティ-webkit-user-modify:read-write**を適用することで、Chromiumの任意の要素に宣言することができます。

これにより、CSS/styleのインジェクションをHTMLのインジェクションに昇格させることができます。要素にCSSプロパティを追加し、insertHTMLコマンドを利用することで実現します。

CTF

このテクニックがCTFの課題として使用された例は、次のリンクで確認できます: https://github.com/Super-Guesser/ctf/blob/master/2022/dicectf/shadow.md

参考文献

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