PortSwigger-Writeups

Lab: Reflected XSS with event handlers and href attributes blocked

Difficulty: Exper

Vulnerability: Reflected XSS via SVG Attribute Smuggling

Lab Link: https://portswigger.net/web-security/cross-site-scripting/contexts/lab-event-handlers-and-href-attributes-blocked

1. The Goal

The objective of this lab was to execute a Cross-Site Scripting (XSS) attack in a search function protected by a comprehensive blocklist WAF.

The WAF blocked all standard event handlers (onclick, onload, onmouseover) and the href attribute, making standard exploitation impossible. My goal was to construct a malicious link vectore that bypasses these filters and executes alert() when clicked.

2. Reconnaissance (Fuzzing)

I started by testing standard tags and attributes. The application blocked almost everything, returning 400 Bad Request for payloads containing href= or on[event]=.

To find a foothold, I fuzzed for allowed HTML tags using Burp intruder. I identified a specific set of allowed tags related to SVG (Scalable Vectore Graphics):

c1 c2 c3 c4 c5

3. Vulnerability Analysis (The “Attribute Smuggling” Concept)

Since I could use the and tags, I recognised a potential SMIL injection vulnerability (Synchronised Multimedia Integration Language).

The tag is designed to animate the attributes of a parent element. Crucially, it can target any including functional ones like href.

The Bypass Logic

The WAF is a static text analyser. It blocks the string href=. However, the tag doesn't use href=. It blocks the string href=. However, the tag doesn't use href=. It uses attributeName="href".

This discrepancy allows me to “smuggle” the forbidden attribute past the WAF. I don’t send the attribute directly; I send an “animation instruction” that forces the browser to create the attribute after the page loads.

4. The Exploit Strategy

I constructed a payload using three nested componenets:

  1. : Acts as the container to enable SVG-specific behavior.
  2. : Creates a clickable link. I defined it “naked” (without an href) to bypass the WAF.

  3. : Placed inside the link. It instructs the browser to immediately "animate" (set) the href attribute of its parent to a malicious JavaScript URI.
5. The Payload

I crafted the following XML payload:

<svg>
    <a>
        <animate attributeName="href" values="javascript:alert(1)" />
        <text x="20" y="20">Click me</text>
    </a>
</svg>

Breakdown:

c7

6. Execution
  1. I injected the payload into the search bar.

  2. The WAF allowed the request because it did not see the forbidden href= string.

  3. The browser rendered the SVG.

  4. The tag executed immediately, dynamically adding href="javascript:alert(1)" to the link in the DOM.

  5. I clicked the “Click me” text, and the alert executed.