Dom Clobbering
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.
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 :
Tableaux et Attributs
Il est également possible de surcharger un tableau et les attributs d'un objet :
Pour écraser un 3ème attribut (par exemple x.y.z), vous devez utiliser un form
:
Cibler plus d'attributs est plus compliqué mais toujours possible, en utilisant des iframes :
La balise style est utilisée pour donner suffisamment de temps à l'iframe pour se rendre. Sans cela, vous obtiendrez une alerte indéfinie.
Pour écraser des attributs plus profonds, vous pouvez utiliser des iframes avec un encodage html de cette manière :
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.
Écrasement de window.someObject
window.someObject
En JavaScript, il est courant de trouver :
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 :
Dans un code vulnérable tel que :
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.
É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 prend en charge les propriétés nommées. Les noms de propriétés pris en charge d'un objet 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 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 embed, form, iframe, img, et les éléments exposés object qui ont un attribut de contenu name non vide et sont dans un arbre de document avec le document comme leur racine; - La valeur de l'attribut de contenu id pour tous les éléments exposés object qui ont un attribut de contenu id non vide et sont dans un arbre de document avec le document comme leur racine; - La valeur de l'attribut id pour tous les éléments img qui ont à la fois un attribut de contenu id non vide et un attribut de contenu name non vide, et sont dans un arbre de document avec le document comme leur racine.
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
.
É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 :
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:
Les investigations sur SVG ont révélé qu'une balise <body>
peut également être utilisée de manière efficace :
Pour que la balise HTML fonctionne dans SVG dans des navigateurs comme Chrome et Firefox, une balise <foreignobject>
est nécessaire :
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()
):
Pour plus d'attributs de formulaire, consultez ce lien.
Références
Heyes, Gareth. JavaScript pour les hackers : Apprenez à penser comme un hacker.
Last updated