DOM Exploitation Unleashed: Mastering Client-Side XSS with documentwrite and innerHTML + Video

Listen to this Post

Featured Image

Introduction:

DOM-based Cross-Site Scripting (XSS) represents a client-side vulnerability where malicious JavaScript executes because user-controlled input flows from a source (like location.search) directly into a DOM sink (such as `document.write` or innerHTML) without proper sanitization. Unlike reflected or stored XSS, the attack payload never leaves the victim’s browser, making it stealthy and often overlooked by server-side filters. This article walks through hands-on exploitation of DOM XSS using real-world lab scenarios, Burp Suite, and browser developer tools, then provides actionable mitigation steps.

Learning Objectives:

  • Identify DOM-based XSS by tracing tainted data from `location.search` to unsafe sinks (document.write, innerHTML).
  • Craft and execute exploit payloads that bypass client-side protections using browser console and Burp Suite.
  • Implement secure coding practices and Content Security Policy (CSP) rules to prevent DOM XSS.

You Should Know:

  1. DOM XSS vs. Reflected/Stored XSS – A Conceptual Breakdown
    DOM-based XSS differs fundamentally from other XSS types because the malicious script is injected into the DOM dynamically on the client side, without the server ever seeing the payload.

Step‑by‑step comparison:

  • Reflected XSS: Malicious input is echoed by the server in an HTTP response (e.g., error message).
  • Stored XSS: Payload is saved on the server (database, comments) and served to all users.
  • DOM XSS: The client-side JavaScript reads a URL parameter (location.search) and writes it to the DOM using an unsafe sink. No server reflection occurs.
    Testing for DOM XSS: Open browser console, execute console.log(location.search), modify the URL fragment and watch how scripts behave. Use `document.write` or `innerHTML` assignments as breakpoints in DevTools.

2. Exploiting `document.write` Sink with `location.search`

When an application uses `document.write` to insert URL parameters directly into the page, an attacker can inject arbitrary HTML/JavaScript.

Step‑by‑step guide:

  1. Identify a script that reads from `location.search` (e.g., var user = new URLSearchParams(location.search).get('q')).
  2. Confirm unsafe sink: document.write("<div>" + user + "</div>").
  3. Construct payload: https://victim.com/page?q=<script>alert('XSS')</script>.
  4. Since `document.write` executes script tags, the alert fires.

Linux/Windows commands (curl test):

curl -s "http://testlab.com/vuln?q=<script>alert(1)</script>" | grep -i "alert"

Browser console verification:

var params = new URLSearchParams(location.search);
document.write(params.get('q'));

If the page shows `` as plain text or executes it, the sink is vulnerable.

  1. Abusing `innerHTML` Sink – No <script>? No Problem
    Unlike document.write, `innerHTML` does not execute `