Test Your Knowledge
Learn Cross-Site Scripting (XSS)
This educational playground demonstrates how XSS attacks work and why proper output encoding is essential. Compare vulnerable vs secure rendering side-by-side.
Educational Purpose Only - This playground runs safely in your browser with script execution disabled for demonstration. No actual XSS attacks are performed. Use this knowledge responsibly.
Vulnerable (innerHTML)
User input rendered directly as HTML
Secure (textContent)
User input properly escaped
Try These XSS Payloads
Basic Script Injection
Event Handler Injection
HTML Injection
Filter Bypass Techniques
// Vulnerable code (DON'T DO THIS) element.innerHTML = userInput; // Secure code (DO THIS) element.textContent = userInput; // OR use proper encoding library
Types of XSS
1. Reflected XSS
Payload is reflected off the web server in error messages, search results, or any response that includes user input.
// URL: https://example.com/search?q=
// Vulnerable server code:
app.get('/search', (req, res) => {
res.send(`Results for: ${req.query.q}`); // VULNERABLE
});
// Attack: Send victim a malicious link
2. Stored XSS
Payload is permanently stored on target server (database, comment field, forum post).
// Attacker posts comment:
// Every user who views the page executes the script
// Most dangerous type - affects all users
3. DOM-based XSS
Payload is executed as a result of modifying the DOM environment in the victim's browser.
// URL: https://example.com/page#
// Vulnerable JavaScript:
document.getElementById('content').innerHTML = location.hash.slice(1);
// Server never sees the payload - it's all client-side
XSS Prevention
Output Encoding by Context
| Context | Encoding Required | Example |
|---|---|---|
| HTML Body | HTML Entity Encoding | < becomes < |
| HTML Attribute | Attribute Encoding | " becomes " |
| JavaScript | JavaScript Encoding | ' becomes \x27 |
| URL Parameter | URL Encoding | < becomes %3C |
| CSS | CSS Encoding | ( becomes \28 |
Secure Code Examples
Vulnerable
// JavaScript
element.innerHTML = userInput;
// React (dangerous)
<div dangerouslySetInnerHTML={{__html: userInput}} />
// PHP
echo $_GET['name'];
// Python/Jinja2
{{ user_input | safe }}
Secure
// JavaScript
element.textContent = userInput;
// React (auto-escapes)
<div>{userInput}</div>
// PHP
echo htmlspecialchars($_GET['name'], ENT_QUOTES);
// Python/Jinja2
{{ user_input }} // auto-escaped
Content Security Policy (CSP)
// HTTP Header - Defense in depth
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
// Prevents inline scripts even if XSS vulnerability exists
// Blocks: <script>alert(1)</script>
// Blocks: <img onerror="alert(1)">
// HTML meta tag alternative
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
XSS Prevention Checklist
- Encode output based on context (HTML, JS, URL, CSS)
- Use safe APIs - textContent instead of innerHTML
- Use frameworks that auto-escape (React, Angular, Vue)
- Implement CSP headers as defense-in-depth
- Validate input - whitelist allowed characters
- Use HTTPOnly cookies to protect session tokens
- Sanitize HTML with DOMPurify if rich text needed
- Avoid dangerous sinks - eval(), document.write()
Related Resources
FixTheVuln Store
Studying for CompTIA PenTest+? Get the Study Planner
Fillable PDF study planners with domain trackers, weekly schedules, and progress tracking. Available in Standard, ADHD-Friendly, Dark Mode, and 4-Format Bundle.
CompTIA PenTest+ Planner60+ certifications available — from $5.99