DOM-Based XSS: The Client-Side Scripting You Didn’t Expect
Understanding and defending against the stealthiest XSS variant
What is DOM-Based XSS?
DOM-Based Cross-Site Scripting (XSS) is a client-side vulnerability where the attack payload is executed as a result of modifying the DOM (Document Object Model) environment in the victim’s browser. Unlike traditional XSS, the malicious payload never touches the server.
Contains crafted parameters that affect DOM
JavaScript writes attacker-controlled data to DOM
In the context of the vulnerable page
Key Differences from Other XSS Types
Type | Payload Location | Server Involvement |
---|---|---|
Reflected XSS | Server response | Payload reflected from server |
Stored XSS | Server database | Payload served from server |
DOM-Based XSS | Client-side only | No server involvement |
How DOM-Based XSS Works
Vulnerable Code Example
// URL: https://example.com/page.html#default=<script>alert(1)</script> const hash = window.location.hash.substring(1); document.getElementById('message').innerHTML = hash;
Common Sources of DOM-Based XSS
document.URL
/window.location
propertiesdocument.referrer
window.name
localStorage
/sessionStorage
- HTML5 postMessage data
Finding DOM-Based XSS Vulnerabilities
1. Manual Testing Approach
- Identify DOM sinks (functions that write to DOM)
- Trace back to sources (user-controllable input)
- Test if sources flow to sinks without proper sanitization
2. Common Dangerous Sinks
element.innerHTML document.write() eval() setTimeout() location.href Function()
3. Testing Payloads
#test=<img src=x onerror=alert(1)> #default='-alert(1)-' #redirect=javascript:alert(document.domain)
Advanced DOM-Based XSS Techniques
1. AngularJS Sandbox Escapes
{{constructor.constructor('alert(1)')()}}
2. jQuery Selector Injection
#selector=<img src=x onerror=alert(1)>
3. PostMessage Exploitation
// Malicious page window.opener.postMessage('<script>alert(1)</script>', '*'); // Vulnerable page window.addEventListener('message', function(e) { document.getElementById('content').innerHTML = e.data; });
Tools for Detection
Tool | Purpose | Usage |
---|---|---|
DOM Invader (Burp) | Built-in DOM XSS detection | Enable in Burp Browser |
DOMinator Pro | Browser extension | Passive scanning |
OWASP ZAP | DOM XSS active scan | Use DOM XSS scan rule |
Manual Testing | Browser DevTools | Trace data flow |
Prevention and Mitigation
1. Safe DOM Manipulation
// UNSAFE element.innerHTML = userInput; // SAFE element.textContent = userInput; document.createTextNode(userInput);
2. Context-Aware Encoding
- HTML Context: Use
innerText
ortextContent
- Attribute Context: Escape quotes and special chars
- URL Context: Encode with
encodeURIComponent()
3. Content Security Policy (CSP)
Content-Security-Policy: script-src 'self'; object-src 'none';
Real-World Examples
Case 1: jQuery Selector Injection
A popular website used $(location.hash)
allowing XSS through crafted hash fragments.
Case 2: AngularJS Client-Side Template
Single Page App evaluated user input as Angular expressions leading to RCE.
Case 3: PostMessage XSS
Chat widget trusted messages from any origin and injected them into DOM.
Conclusion
DOM-Based XSS is particularly dangerous because:
- It bypasses server-side protections
- Traditional scanners often miss it
- The attack happens entirely client-side