PortSwigger-Writeups

Lab: Reflected XSS into HTML context with all tags blocked except custom ones

Difficulty: Practitioner

Vulnerability: Reflected XSS with WAF Evasion & Browser Logic Abuse

Lab Link: https://portswigger.net/web-security/cross-site-scripting/contexts/lab-html-context-with-all-standard-tags-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 strict WAF that blocks all standard HTML tags.

My goal was to inject a custom HTML tag, make it interactive using specific attributes, and force the victim’s browser to execute code automatically upon page load.

2. Reconnaissance (Fuzzing)

I started by testing standard XSS vectos (

b1 b2

Phase 1: Tag Enumeration

I hypothesized that the WAF might only block known HTML tags. To test this, I injected a non-existent custom tag:

b3

Phase 2: Event Enumeration

Since custom tags do not load external resources, standard events like onload or onerror do not fire. I needed an interaction event.

  1. I fuzzed the custom tag for attributes: <test §event§=1>

  2. I found that onfocus was allowed.

b4

3. The Exploit Chain

I had a working vector: <xss onfocus=alert(1)>.

However, a custom tag is just a text container. It cannot receive “focus” by default (unlike an input field), and I could not rely on the victim clicking it manually. I needed to chain three browser behaviour to weaponise this:

  1. tabindex=”1”: This attribute forces the browser to treat the custom tag as an interactive, focusable element (allowing it to receive focus).

  2. id=”x”: This gives the element a targetable identity.

  3. URL Fragment (#x): Appending #x to the URL forces the browser to automatically scroll to and focus on the element with id=”x” immediately upon page load.

The trigger logic: Load Page -> Browser reads #x -> Jumps to -> Element receives Focus -> onfocus fires -> Alert executes.

b5

4. The Delivery Strategy (iframe vs. Redirect)

I initially attempted to use an <iframe> to deliver the payload invisibly.

To bypass this security control, I switched to a Top-Level Navigation attack. I used window.location to redirect the victim’s entire tab to the malicious URL. This makes the lab the “Active Window,” allowing the focus event to fire automatically.

5. Tha Payload

I constructed the following JavaScript for the Exploit Server body:

<script>
location = '[https://YOUR-LAB-ID.web-security-academy.net/?search=%3Cxss+id%3Dx+onfocus%3Dalert%28document.cookie%29%20tabindex=1%3E#x](https://YOUR-LAB-ID.web-security-academy.net/?search=%3Cxss+id%3Dx+onfocus%3Dalert%28document.cookie%29%20tabindex=1%3E#x)';
</script>

Breakdown:

b6

6. Execution
  1. I pasted the script into the Exploit Server.

  2. I clicked “Deliver exploit to victim”.

  3. The victim visited my page, was immediately redirected to the lab, and the browser’s focus behaviour triggered the alert(document. cookie) popup.