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 / Cross-Site Scripting
Typical Severity High
OWASP A03:2021 – Injection
CWE CWE-79 – Improper Neutralization of Input During Web Page Generation
Also known as Persistent XSS, Second-Order XSS, Type-2 XSS
Affected systems Web applications that store and later render user-supplied content (forums, comment systems, CMS platforms, profile pages, chat applications, admin dashboards)
Standards & References OWASP Top 10 A03:2021, CWE-79, W3C Content Security Policy Level 3

Overview

Stored Cross-Site Scripting (Stored XSS) occurs when a web application accepts user-controlled input, persists it to a back-end data store (database, log file, message queue, etc.) without adequate sanitisation, and later renders that data in an HTTP response without proper output encoding. Unlike Reflected XSS—where the malicious payload is embedded in a URL and executed in a single round trip—Stored XSS payloads are durable: every user whose browser renders the affected page executes the injected script, often without any interaction beyond visiting the page.

Stored XSS is classified under CWE-79 (Improper Neutralization of Input During Web Page Generation) and maps to OWASP Top 10 A03:2021 – Injection. Because the attack is self-propagating and does not require tricking a victim into clicking a crafted link, it is generally considered more severe than Reflected XSS.

How it works

The attack life cycle has three distinct phases:

  1. Injection: The attacker submits a payload—typically a <script> tag, an event-handler attribute, or an encoded variant—through any input surface the application accepts (comment fields, user profiles, product reviews, file names, HTTP headers stored in logs, etc.).
  2. Persistence: The application stores the unsanitised payload in a data store. From this point the payload is latent and ready to execute for any future visitor.
  3. Execution: When a legitimate user (or administrator) requests the page containing the stored data, the server includes the payload in the HTML response. The browser, unable to distinguish the injected script from legitimate application code, executes it in the context of the origin.

Key technical characteristics:

  • Execution occurs in the victim's browser under the application's origin, granting the script access to cookies (including session tokens), localStorage, sessionStorage, and the DOM.
  • Payloads can exfiltrate session cookies to an attacker-controlled server, perform actions on behalf of the victim (CSRF-equivalent), redirect users to phishing pages, or serve drive-by downloads.
  • Polyglot payloads and encoding tricks (HTML entities, Unicode escapes, base64, SVG vectors, CSS expressions) are commonly used to bypass naive input filters.
  • Second-order (or second-stage) XSS is a variant where stored data is retrieved and unsafely interpolated into a later, different page or context—often a maintenance or admin interface—making it harder to discover during standard testing.
  • The HttpOnly cookie flag prevents JavaScript from reading cookies directly, but does not prevent all classes of session hijacking achievable through XSS (e.g., forging authenticated requests).

Business impact

Because Stored XSS executes automatically for every affected visitor, the blast radius scales with the traffic to the compromised page. Documented consequences include:

  • Account takeover: Session tokens captured via document.cookie exfiltration allow attackers to impersonate victims without knowing their passwords.
  • Credential harvesting: Injected scripts can overwrite login forms or inject fake authentication dialogs to harvest plaintext credentials.
  • Privilege escalation: If an administrator views an infected page, the attacker gains administrative-level access, potentially compromising the entire application.
  • Malware distribution: Scripts can silently redirect users to exploit kits or trigger drive-by downloads.
  • Regulatory exposure: Unauthorised access to personal data can trigger breach notifications and fines under GDPR, HIPAA, PCI DSS, and similar frameworks.
  • Reputational damage: Publicly known XSS incidents erode user trust, particularly for e-commerce, banking, and healthcare platforms.
  • Data integrity compromise: Scripts can alter on-screen content, leading users to make decisions based on falsified information (e.g., manipulating financial figures).

How to fix it

Defence requires controls at multiple layers. No single measure is sufficient on its own.

  1. Context-aware output encoding: Encode all user-supplied data at the point of rendering, not at the point of storage. Use the appropriate encoding for the output context: HTML entity encoding for HTML body/attributes, JavaScript string escaping for inline scripts, URL encoding for href/src attributes, and CSS escaping for style contexts. Libraries such as OWASP Java Encoder, Microsoft AntiXSS, or framework-native templating engines (React's JSX, Angular's interpolation, Django's auto-escaping) apply this automatically when used correctly.
  2. Input validation and sanitisation: Reject or sanitise input that does not conform to expected formats. For fields that must accept rich text (HTML), use a well-maintained allowlist-based HTML sanitisation library (e.g., DOMPurify for client-side, bleach for Python, HtmlSanitizer for .NET). Blocklist approaches are insufficient against encoding bypass techniques.
  3. Content Security Policy (CSP): Deploy a strict CSP header (Content-Security-Policy) that disallows inline scripts ('unsafe-inline') and restricts script sources to trusted origins. A policy using nonces or hashes for legitimate inline scripts provides the strongest protection. CSP is a defence-in-depth control and should not replace server-side fixes.
  4. HttpOnly and Secure cookie flags: Set HttpOnly on all session cookies to prevent JavaScript access. Set Secure to enforce HTTPS-only transmission.
  5. Subresource Integrity (SRI): For externally loaded scripts, use SRI hashes to detect tampering.
  6. Trusted Types API: In modern browsers, enforce the Trusted Types API (require-trusted-types-for 'script') to block DOM injection sinks from accepting raw strings.
  7. Security code review and DAST: Include XSS test cases in static analysis (SAST) pipelines and perform dynamic application security testing (DAST) against all input surfaces. Sensagraph automatically detects Stored XSS vulnerabilities during continuous scanning.
  8. Web Application Firewall (WAF): A WAF can provide a secondary layer of detection and blocking for known XSS patterns, but should not be the primary control.

References

Frequently asked questions

In Reflected XSS the malicious payload is included in the HTTP request (e.g., a URL parameter) and immediately reflected back in the response—it is not stored. In Stored XSS the payload is written to a persistent data store and served to all subsequent visitors who load the affected page, making it significantly more dangerous as no victim interaction with a crafted link is required.

HttpOnly prevents JavaScript from reading cookie values via document.cookie, which mitigates session-token theft through that specific vector. However, it does not prevent XSS payloads from performing authenticated actions (forging requests), manipulating the DOM, harvesting keystrokes, or redirecting users. It is a useful defence-in-depth measure but not a fix for the underlying vulnerability.

A well-configured CSP can block or significantly limit the damage from XSS payloads by preventing inline script execution and restricting the origins from which scripts can be loaded. However, CSP does not eliminate the vulnerability itself—misconfigurations, use of 'unsafe-inline', or overly permissive source lists can render it ineffective. CSP should be treated as defence-in-depth, alongside proper server-side output encoding and input sanitisation.

Common injection points include comment and forum post fields, user profile fields (names, bios, website URLs), product reviews, file upload names, chat messages, support ticket descriptions, and any field whose value is later rendered in an HTML page. Admin interfaces and log viewers are high-value targets because compromising an administrator's session can yield full application control.

Sanitising at storage is better than nothing but is not sufficient on its own, for two reasons. First, data may be displayed in multiple contexts (HTML, JSON, JavaScript, email) each requiring different encoding. Encoding at storage for one context can break other consumers or be insufficient for others. Second, context-aware output encoding at the point of rendering is the most reliable defence because it is closest to the point of harm. The OWASP recommendation is to encode at output, in the correct context, rather than relying solely on input sanitisation.