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
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
- HTML entity smuggling that survives many regex filters
- Tag confusion via svg animate onbegin handlers
- JavaScript URL inside SVG xlink:href anchors
- Unicode normalization tricks where escaped sequences bypass keyword denylists
- 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
- Prefer textContent and createElement over innerHTML
- Adopt Trusted Types with require-trusted-types-for in CSP
- Sanitize on output with DOMPurify, never on input
- Lock CSP to strict-dynamic with nonces and drop unsafe-inline
- Validate postMessage origin against an allowlist before parsing
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.