Cross-site Scripting (Reflected)

  • CAPEC 19
  • CWE 79
  • WASC 8
  • OWASP 2017-A7

Cross-Site Scripting (XSS) is a client-side injection vulnerability that enables attackers to inject malicious scripts into web pages viewed by other users. When an application includes untrusted data in a web page without proper validation or escaping, an attacker can cause the victim’s browser to execute attacker-controlled JavaScript (or other client-side code), resulting in session hijacking, user impersonation, content manipulation, or the theft of sensitive data such as cookies, tokens and credentials.

There are three primary XSS types:

  • Stored (persistent) XSS — malicious payloads are stored on the server (e.g., in a database, forum post, or comment) and are served to other users when they view the infected resource. This is often the most damaging because it can affect many users automatically.
  • Reflected (non-persistent) XSS — the payload is included in a request (e.g., query parameter, form submission) and immediately reflected in the response. The attacker typically convinces a victim to follow a crafted link or submit a specially formed form.
  • DOM-based XSS — the vulnerability occurs entirely in the client-side DOM: untrusted data is read by client-side code (e.g., location.hash, document.write, innerHTML) and used to modify the DOM in an unsafe way, without the server altering the content.

Why XSS happens:

  • Failure to properly validate, filter, or encode untrusted input before placing it into a web page.
  • Unsafe use of APIs that inject content into the DOM (e.g., innerHTML, document.write, eval).
  • Treating user data as HTML or script rather than data — no separation of content and executable context.
  • Inconsistent or missing output-encoding for different contexts (HTML body, attribute, JavaScript, URL, CSS).
  • Overly permissive content allow-lists for rich text editors or improper sanitizers.

Common consequences:

  • Account takeover through theft of session cookies or tokens.
  • Actions performed on behalf of users (CSRF-like effects) using stolen credentials.
  • Phishing and social engineering by altering page content or UI elements.
  • Exfiltration of data accessible in the browser (localStorage, DOM, page content).
  • Drive-by distribution of malware or propagation of further attacks.

Detection and indicators:

  • Presence of unescaped <script>, on* attributes, or use of innerHTML/outerHTML with user data.
  • Automated scanners can detect many XSS patterns, but DOM-based issues often require manual review and browser instrumentation.
  • Abnormal outbound connections from the client (to attacker-controlled domains) or unexpected script execution in user sessions.
  • Code review focusing on output encoding, templating, and client-side DOM manipulation points.
Remediation

Mitigating XSS requires treating any untrusted input as data and applying context-aware output encoding, combined with appropriate input handling and secure UI practices.

  1. Context-Aware Output Encoding
    Encode output according to the context where it will appear:

    • HTML body: escape <, >, &, " and '.
    • HTML attribute: additionally escape quotes and use proper quoting of attributes.
    • JavaScript context: use JS string encoding or safely serialize data (e.g., JSON) and avoid injecting raw strings into script blocks.
    • URL context: use percent-encoding for unsafe characters.
    • CSS context: use CSS string escaping methods. Use well-tested encoding libraries (framework-provided or community-vetted) rather than hand-rolled escaping.
  2. Use Safe Templating and Framework Features
    Prefer frameworks and templating engines that automatically escape output by default (e.g., React's JSX, Angular, Razor). Avoid constructs that bypass escaping (e.g., dangerouslySetInnerHTML, ng-bind-html without sanitizer).

  3. Validate and Sanitize Input (When Appropriate)
    Validate inputs for expected type, length and format. For rich text inputs, apply strict sanitization using a robust HTML sanitizer that allows only a minimal, well-audited set of tags and attributes. Keep sanitizer libraries up to date.

  4. Avoid Dangerous DOM APIs
    On the client side, avoid APIs that directly interpret strings as HTML or code (e.g., innerHTML, outerHTML, document.write, eval, setTimeout() with string arguments). Prefer text-setting APIs like textContent, setAttribute, or DOM methods that create elements and set properties safely.

  5. Use Content Security Policy (CSP)
    Implement a strong CSP to reduce the impact of XSS by restricting script sources, disallowing unsafe-inline scripts, and enabling script-src nonces or hashes. CSP is a powerful mitigation but should not replace escaping and input handling.

  6. HTTP-only and Secure Cookies
    Mark session cookies HttpOnly so they are not accessible to JavaScript, reducing the impact of session-stealing XSS attacks. Also use Secure and appropriate SameSite attributes.

  7. Principle of Least Privilege in UI
    Minimize sensitive data exposed in the browser, and avoid placing secrets or privileged tokens in client-side storage accessible to scripts.

  8. Safe Rich Text Handling
    When allowing user-supplied HTML (e.g., WYSIWYG), sanitize and canonicalize on the server side, strip event handlers (on*), disallow dangerous protocols (e.g., javascript:), and normalize attributes. Consider storing only sanitized HTML or a safe subset (or a structured representation like Markdown rendered server-side with safe renderer).

  9. Testing and Code Review
    Include XSS scenarios in unit tests, integration tests, and security test plans. Use automated scanners, manual penetration testing, and DOM-focused testing tools to catch client-side vulnerabilities.

  10. User Education and Monitoring
    Educate developers about XSS risks and secure patterns. Monitor client-side errors and suspicious activity that may indicate XSS exploitation attempts.

References