BIPI
BIPI

XSS Beyond the Basics: DOM, Mutation, mXSS, and Filter Bypasses

Cybersecurity

A pentester field guide to DOM XSS sinks, mutation XSS in sanitizers, and the WAF bypass payloads that still pop shells in 2024.

By Arjun Raghavan, Security & Systems Lead, BIPI · November 13, 2024 · 12 min read

#xss#pentesting#web-security#payloads#waf-bypass

Reflected and stored XSS are well documented, but the bugs that actually pay bounties in 2024 live deeper: DOM sinks reachable only through fragment routing, mutation XSS that survives DOMPurify, and filter bypasses that exploit parser quirks in Chromium and Safari.

Identifying DOM XSS Sinks

Start with a sink-first review. Grep the bundle for innerHTML, outerHTML, doc.write, insertAdjacentHTML, eval, setTimeout with string args, and jQuery $() with attacker-controlled input. Use Burp Suite DOM Invader to taint location.hash and postMessage data through the SPA router.

  • location.hash, location.search, location.pathname read into innerHTML
  • postMessage listeners without origin checks feeding eval or Function()
  • window.name persisted across navigations and rendered as HTML
  • JSON.parse output spread into a template literal that lands in a sink
  • Client-side template engines (Vue, Angular, Handlebars) compiling attacker strings

Mutation XSS Against Sanitizers

mXSS exploits the gap between sanitizer parsing and browser re-parsing. DOMPurify, sanitize-html, and Google Closure have all shipped bypasses where a payload using nested noscript and template tags mutates after sanitization when reinserted into the DOM.

Filter and WAF Bypass Payloads

  1. HTML entity smuggling that survives many regex filters
  2. Tag confusion via svg animate onbegin handlers
  3. JavaScript URL inside SVG xlink:href anchors
  4. Unicode normalization tricks where escaped sequences bypass keyword denylists
  5. Template literal abuse with setTimeout backtick syntax to dodge parenthesis filters

Exploiting CSP-Protected Apps

CSP is not a fix on its own. Hunt for script-src self with JSONP endpoints, AngularJS gadgets on the origin, or uploaded SVG files served same-origin. The classic JSONP callback trick still works against many fintech apps.

If the CSP allows unsafe-inline with a nonce but the nonce leaks via a dangling markup injection, the policy is decorative.

Postmessage and Cross-Window XSS

Audit every window.addEventListener message handler. Missing event.origin checks let an attacker iframe the target and post a payload that ends up in innerHTML. Test with a hosted PoC page that posts crafted JSON to the target.

Tooling Stack

  • Burp Suite Pro + DOM Invader for taint tracking
  • ffuf for parameter discovery on reflected sinks
  • PortSwigger XSS cheat sheet as your payload library
  • Chromium with disabled XSS auditor for local repro
  • Playwright scripts to automate stored XSS detonation

Remediation Patterns

  1. Prefer textContent and createElement over innerHTML
  2. Adopt Trusted Types with require-trusted-types-for in CSP
  3. Sanitize on output with DOMPurify, never on input
  4. Lock CSP to strict-dynamic with nonces and drop unsafe-inline
  5. Validate postMessage origin against an allowlist before parsing
63%
of web apps still expose at least one DOM sink
12
DOMPurify bypasses disclosed since 2020
4hr
median time to find DOM XSS with DOM Invader

BIPI red team engagements consistently surface DOM XSS in apps that passed automated scanners. The pattern holds: scanners hunt sources, attackers hunt sinks.

Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.