The Script That Shouldn't Run
A malicious payload hidden in plain sight. One line of code that bypasses every defense. Welcome to Cross-Site Scripting.
Injection via Trusted Context
Cross-Site Scripting (XSS) is an injection attack where malicious scripts execute in a victim's browser within the context of a trusted site. The fundamental problem: browsers can't distinguish attacker code from legitimate code.
When a script executes in your site's context, it inherits all permissions: access to cookiesHTTP cookies store session tokens and authentication data. XSS gives attackers full access., session tokensAuthentication tokens that prove user identity to the server., and the entire DOMDocument Object Model — the tree structure representing the HTML page in memory..
The attack violates the trust boundary: user input flows through your application and back to the browser without proper encoding. The browser executes it as if you wrote it.
Three Attack Vectors
XSS manifests in three distinct forms, each with different persistence and detection characteristics. Understanding the taxonomy is critical for defense.
How Browsers Execute the Attack
The stored XSS lifecycle demonstrates the critical failure point: when the server reflects untrusted data back into HTML without encoding, the browser has no way to distinguish malicious code from legitimate scripts.
At step 5, the browser parses the HTML and encounters the <script> tag. Because it arrived from the trusted origin (your domain), it executes with full privileges.
The same-origin policy (SOP) can't protect here. The malicious script is same-origin — it's embedded in your HTML response. SOP only restricts cross-origin access, not code that originates from your domain.
Accessible to Attacker
- ✓
document.cookie— session tokens - ✓
localStorage/sessionStorage - ✓ DOM manipulation — full page rewrite
- ✓
XMLHttpRequest/fetch— API calls - ✓ Event listeners — keylogging
Defense: Validate Input, Encode Output
The OWASP XSS Prevention Cheat Sheet defines the gold standard: never insert untrusted data except in allowed locations, and always encode for the context where data appears.
Encoding transforms special characters into their HTML entity equivalents. < becomes <, > becomes >. The browser renders the literal characters instead of parsing them as code.
Context-Specific Encoding
htmlspecialchars($data, ENT_QUOTES)
attr($data)
json_encode($data, JSON_HEX_TAG)
urlencode($data)
CSS.escape($data)
innerHTML with untrusted data.
Additional Defenses
- Content Security Policy (CSP): Restrict script sources. Use
script-src 'self'to block inline scripts. - HTTPOnly cookies: Prevents JavaScript access to session cookies. Set
Set-Cookie: HttpOnly. - X-XSS-Protection header: Enable browser XSS filters (legacy, superseded by CSP).
- Input validation: Whitelist allowed characters. Reject unexpected input early.
- Disable HTTP TRACE: Prevents XST (Cross-Site Tracing) attacks that steal headers.
Real-World Impact
XSS enables a cascade of attacks, from session hijacking to content defacement with financial consequences.
Session Hijacking
Attacker steals session cookies and gains full account access. No password required. Complete account takeover.
document.cookie → attacker.com
Credential Theft
Inject fake login forms over real page. Capture credentials as users type. Keylogging via event listeners.
addEventListener('keydown', ...)
Content Defacement
Rewrite HTML to modify press releases, product information, or pharmaceutical dosage instructions. Stock price impacts documented.
document.body.innerHTML = ...
Trojan Delivery
Serve malware via trusted domain. Browser extensions, ransomware droppers. User trusts the origin.
<iframe src="malware.exe">
Case Study: Pharmaceutical Site XSS
A stored XSS vulnerability in a drug information portal allowed attackers to modify dosage recommendations. The defacement remained live for hours, potentially causing patient harm. The company's stock dropped 3% on disclosure day.
Finding XSS in Your Code
Automated tools catch obvious cases, but manual code review and systematic testing remain essential.
Manual Code Review
Search for all locations where HTTP request data appears in HTML output. Focus on reflection points.
# Find dangerous patterns
grep -r "echo \$_GET" .
grep -r "echo \$_POST" .
grep -r ".innerHTML = " .
grep -r "document.write" .
Every instance is a potential injection point. Verify encoding is applied.
Automated Scanning
Tools can crawl your app and inject test payloads. Useful for broad coverage, but limited by JavaScript rendering and authentication.
- OWASP ZAP: Open-source web app scanner
- Burp Suite: Commercial, proxy-based testing
- Nessus / Nikto: Network scanners with XSS checks
Tools only scratch the surface. Complex XSS requires manual verification.
Testing Methodology
- Identify input points: Every form field, URL parameter, HTTP header that could be reflected.
- Submit test payloads: Start simple (
<script>alert(1)</script>), then escalate (<img src=x onerror=alert(1)>). - Check reflection: View source. Is your payload in the HTML? Is it encoded?
- Test context variations: HTML content, attributes, JavaScript strings, event handlers.
- Bypass attempts: Try encoding variations (
<ScRiPt>, URL encoding, Unicode normalization). - Test all roles: Anonymous, authenticated, admin. Privileges affect what data is reflected.
Common Payloads
<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
'><script>alert(1)</script>
"><script>alert(1)</script>
javascript:alert(1)
<iframe src="javascript:alert(1)">
Golden Rule
If you find one XSS vulnerability, assume there are more. Vulnerable code patterns repeat. Audit the entire codebase systematically.
Next Steps
XSS is preventable. Proper output encoding eliminates the vulnerability. This is an implementation issue, not an inherent web flaw.
Action Items
- Audit your codebase for unencoded output:
grep -r "echo \$_" - Implement context-aware encoding:
htmlspecialchars(),json_encode() - Add CSP headers:
Content-Security-Policy: script-src 'self' - Set HTTPOnly on session cookies:
Set-Cookie: HttpOnly; Secure - Integrate automated scanning in CI/CD: OWASP ZAP, Burp Suite
- Train developers on OWASP Top 10 and secure coding practices
You Now Understand XSS
From injection vectors to defense strategies, you've mapped the complete XSS landscape.