Varol Cagdas Tok

Personal notes and articles.

DOM-Based XSS

DOM-based XSS occurs when client-side JavaScript reads attacker-controlled data and writes it to the DOM in a way the browser executes as script. The server response may be entirely free of the payload. The vulnerability is in JavaScript running in the browser, not in the server-side code.


Sources

A source is a JavaScript property that contains attacker-controlled data. Common sources:


Sinks

A sink is a JavaScript function or property that, when given attacker-controlled data, causes script execution. Common dangerous sinks:


A Concrete Case

A single-page application reads the fragment to populate a greeting:

const name = location.hash.slice(1);
document.getElementById('greeting').innerHTML = 'Hello, ' + name;

A URL with fragment #<img src=x onerror=alert(1)> causes the script to assign that string to innerHTML. The browser parses an <img> element with an onerror handler and fires the handler when the image fails to load. The entire flow is client-side. The server logs a request with no indication of the payload.


Why DOM-Based XSS Is Harder to Find

Server-side code review and HTTP-level scanning tools can find reflected and stored XSS by tracing request parameters through server templates. DOM-based XSS requires analyzing JavaScript execution paths: which sources flow into which sinks, and whether any sanitization occurs in between. This requires either static analysis of JavaScript or dynamic analysis through a browser. Automated scanners miss many DOM XSS cases because they do not execute JavaScript or do not trace data flow through it.

Code search for dangerous sinks (innerHTML, eval, document.write) is a starting point. Each sink should be reviewed to determine what data reaches it and whether that data can be controlled from a URL or other external source.