Understanding DOM-Based Attacks
DOM-based attacks exploit vulnerabilities in client-side JavaScript code that improperly handles user input when manipulating the Document Object Model (DOM). Unlike traditional attacks that involve server-side processing, these attacks execute entirely in the browser when untrusted data flows from a source to a sink without proper validation or sanitization.
Key Concepts
Understanding DOM-based attacks requires familiarity with two critical components:
- Source: The entry point where untrusted data originates from user input (e.g.,
location.hash,document.URL,document.referrer) - Sink: The dangerous JavaScript function or property where the data is used to modify the DOM (e.g.,
eval(),innerHTML,location)
The vulnerability occurs when data flows from source to sink without adequate validation, allowing attackers to inject malicious payloads.
DOM-Based Open Redirection
DOM-based open redirection is a common attack vector that exploits how web applications handle URL fragments (the portion after #) to control navigation. When applications use hash values to determine redirects without proper validation, attackers can redirect users to malicious sites.
Vulnerable Code Example
goto = location.hash.slice(1)
if (goto.startsWith('https:')) {
location = goto;
}
Vulnerability Analysis:
| Component | Value | Issue |
|---|---|---|
| Source | location.hash.slice(1) | Extracts user-controlled URL fragment |
| Sink | location = goto | Directly assigns to location without sanitization |
| Validation | goto.startsWith('https:') | Insufficient - only checks protocol prefix |
Exploitation Scenario
An attacker can craft a malicious URL that passes the weak validation:
https://realwebsite.com/#https://attacker.com
Attack Flow:
- User clicks the malicious link
- JavaScript extracts
https://attacker.comfrom the hash - Code validates that it starts with
https: - Browser redirects to attacker's domain
- User believes they're still on the legitimate site
Mitigation Strategies
Input Validation
- Implement whitelist-based validation for allowed redirect destinations
- Validate against a list of approved domains rather than just checking protocols
- Use regular expressions to ensure URLs match expected patterns
// Better approach
const allowedDomains = ['realwebsite.com', 'trusted-partner.com'];
const goto = location.hash.slice(1);
try {
const url = new URL(goto);
if (allowedDomains.includes(url.hostname)) {
location = goto;
}
} catch (e) {
// Invalid URL - do nothing
}
Security Best Practices
- Avoid dangerous sinks: Minimize use of
eval(),innerHTML, and directlocationassignments - Use safe APIs: Prefer
textContentoverinnerHTML,setAttribute()over direct property assignment - Content Security Policy (CSP): Implement CSP headers to restrict script execution
- Encode output: Always encode data before inserting into the DOM
Regular Security Audits
- Conduct code reviews focusing on data flow from sources to sinks
- Use static analysis tools to automatically detect potential DOM-based vulnerabilities
- Perform penetration testing to identify exploitable weaknesses
- Monitor security advisories for third-party libraries
Learn More
To deepen your understanding of DOM-based vulnerabilities:
- OWASP DOM-based XSS Prevention Cheat Sheet: Comprehensive guide on preventing DOM-based attacks
- PortSwigger Web Security Academy: Interactive labs for practicing DOM-based vulnerability exploitation and mitigation
- MDN Web Security Documentation: Best practices for secure JavaScript development
- Browser Developer Tools: Use browser consoles to trace data flow and identify sources and sinks in your code