Skip to main content
4 min read Intermediate Web

How to Identify DOM-Based XSS?

Why is this a DOM-Based XSS?

DOM-based XSS occurs when the vulnerability is in the JavaScript code running in the browser, rather than in the server-side response. The malicious script is executed purely on the client side without the server modifying the page.

How This XSS is DOM-Based

FactorExplanation
SourceThe user-controlled input comes from location.search (query string in the URL).
Execution in BrowserThe JavaScript on the page reads location.search and inserts it into the DOM using document.write().
No Server InteractionThe attack does not require modifying server responses; it happens entirely in the user's browser.
Vulnerable Codejavascript document.write("Search: " + location.search);
Why This is DOM-BasedThe vulnerability exists inside the JavaScript code, not in the HTML or server response.

To determine if a website is vulnerable to DOM-based XSS, follow these steps:

1️⃣ Identify User-Controlled Input Sources

Look for JavaScript code that takes input from the URL, cookies, or other user-controllable locations. Common sources include:

SourceExample
location.searchdocument.write(location.search);
location.hashdocument.write(location.hash);
document.URLdocument.write(document.URL);
document.referrerdocument.write(document.referrer);
localStoragedocument.write(localStorage.getItem("data"));
sessionStoragedocument.write(sessionStorage.getItem("data"));
window.namedocument.write(window.name);

Check if the application reads user input from these sources.


2️⃣ Find Sinks (Execution Points)

A sink is where the user-controlled input is inserted into the page. If the input is inserted without sanitization, it can execute JavaScript. Dangerous sinks include:

SinkVulnerable Example
document.write()document.write(location.search);
innerHTMLelement.innerHTML = location.search;
outerHTMLelement.outerHTML = location.search;
eval()eval(location.search);
setTimeout()setTimeout(location.search, 0);
setInterval()setInterval(location.search, 0);
Function()new Function(location.search);
document.createElement()var script = document.createElement("script"); script.src = location.search; document.body.appendChild(script);

Check if user-controlled data reaches any of these sinks.


3️⃣ Test by Injecting a Simple Payload

If you find a possible input-source and sink combination, test by injecting a non-harmful script like:

https://example.com/search?query=<script>alert('XSS')</script>

If an alert box pops up, the site is vulnerable to DOM-based XSS.


4️⃣ Use Browser Developer Tools

  1. Inspect JavaScript Code:

    • Open DevTools (F12Sources tab).
    • Search (Ctrl + F) for location.search, innerHTML, or other sources/sinks.
  2. Monitor DOM Changes:

    • Open DevTools Console and run:
      Object.getOwnPropertyDescriptor(window, 'location')
    • If location is modified dynamically, it may be vulnerable.
  3. Use DOM XSS Scanner Extensions:

    • Chrome/Firefox "DOM XSS Scanner" extensions can help detect vulnerabilities.

5️⃣ Use Security Tools for Automated Testing

🔹 Burp Suite (DOM Invader)

  • Can automatically detect and test for DOM XSS.

🔹 OWASP ZAP

  • Has DOM XSS scanning in passive and active modes.

🔹 Google Chrome DevTools (DOM Breakpoints)

  • Set breakpoints on document.write, innerHTML, etc., to track execution.

Final Summary

StepAction
1️⃣ Find User InputLook for location.search, document.URL, localStorage, etc.
2️⃣ Identify SinksCheck if input is inserted via document.write(), innerHTML, eval(), etc.
3️⃣ Test PayloadsInject <script>alert('XSS')</script> and observe execution.
4️⃣ Use DevToolsCheck JavaScript execution and DOM changes.
5️⃣ Use Security ToolsTry Burp Suite, OWASP ZAP, and browser extensions.

Let's break down each component in your code to fully understand how it leads to DOM-based XSS.


Code Breakdown:

function doSearchQuery(query) {
document.getElementById('searchMessage').innerHTML = query;
}

var query = (new URLSearchParams(window.location.search)).get('search');

if (query) {
doSearchQuery(query);
}

1️⃣ window.location.search (User Input Source)

window.location.search
  • This retrieves everything after the ? in the URL.

  • Example: If the URL is:

    https://victim.com/page?search=hello

    Then:

    console.log(window.location.search); // Output: "?search=hello"
  • This means the attacker can control search by modifying the URL.


Summary Table

ComponentPurposeSecurity Issue
window.location.searchRetrieves user input from the URLAttacker can modify it
new URLSearchParams().get('search')Extracts search valueExtracted value can contain JavaScript
document.getElementById('searchMessage')Selects an HTML elementTarget where attacker injects code
innerHTMLInserts query into the pageExecutes JavaScript if input contains scripts
FixtextContent or sanitize inputPrevents execution of malicious code