XSS Attack Lab
Cross-Site Scripting (XSS) is a code injection vulnerability that allows attackers to execute malicious scripts in a victim's browser. Learn how XSS works, explore interactive simulations, and discover effective prevention techniques.
Understanding XSS
Cross-Site Scripting (XSS) is a web security vulnerability that enables attackers to inject client-side scripts into web pages viewed by other users. It exploits the trust between a user and a legitimate website, bypassing the Same-Origin Policy.
Reflected XSS
Payload is reflected off the web server. Delivered via phishing links or crafted URLs. Never stored on the server.
Stored XSS
Malicious script is permanently stored on the server (e.g., comments). Executed by every visitor. Most damaging type.
DOM-based XSS
Vulnerability exists entirely client-side. Payload modifies the DOM environment without reaching the server.
Reflected XSS Simulator
Type or select a payload below to see how reflected XSS works.
Rendered Output:
No input yet
Stored XSS Simulator
A guestbook where comments are rendered. When vulnerable, injected scripts execute.
Alice
Bob
Mallory
Prevention Techniques
Input Validation
Validate and sanitize all user input on both client and server sides. Use allowlists (whitelist) over blocklists. Restrict input to expected types, lengths, and patterns.
Output Encoding
Encode output based on context: HTML entity encoding for HTML body, URL encoding for URLs, JavaScript encoding for JS contexts. Libraries like OWASP Java Encoder or DOMPurify handle this.
Content Security Policy
Use CSP headers to restrict which scripts can execute. Disable inline scripts with script-src 'self'. Report violations via report-uri.
HTTPOnly Cookies
Set the HttpOnly flag on session cookies to prevent JavaScript access. Combine with Secure and SameSite=Strict/Lax attributes for defense in depth.
Sanitization Libraries
Use well-maintained libraries like DOMPurify, OWASP Java Encoder, or Bleach (Python). Avoid rolling your own sanitizer — edge cases with SVG, MathML, and obscure attributes are easy to miss.
Context-aware Escaping
Apply the correct escaping for each context: HTML body, HTML attributes, CSS, JavaScript strings, URLs. A single unescaped insertion point can open an XSS vector.
XSS Types Comparison
| Type | Description | Impact | Difficulty | Example |
|---|---|---|---|---|
| Reflected XSS | Payload is reflected off the web server in the response (e.g., search query, error message). Requires user to click a crafted link. | Medium | Easy | <script>alert('xss')</script> |
| Stored XSS | Payload is stored on the server (database, comments, forum) and served to every visitor. The most dangerous type. | Critical | Medium | <img src=x onerror=alert('stored')> |
| DOM-based XSS | Vulnerability exists entirely in client-side JavaScript. The payload never reaches the server; it modifies the DOM environment dynamically. | High | Hard | #<img src=x onerror=alert(1)> |
Code Examples
// React - dangerouslySetInnerHTML
<div dangerouslySetInnerHTML={{
__html: userInput
}} />
// jQuery - HTML injection
$("#output").html(userInput);
// Vanilla JS - innerHTML
document.getElementById(
"output"
).innerHTML = userInput;
// PHP - raw echo
echo $_GET['search'];
// SQL + Display
SELECT comment FROM posts;
// then display raw HTML// React - text content
<div>{escapeHtml(userInput)}</div>
// DOMPurify sanitization
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(input)
}} />
// Vanilla JS - textContent
document.getElementById(
"output"
).textContent = userInput;
// PHP - htmlspecialchars
echo htmlspecialchars(
$_GET['search'],
ENT_QUOTES, 'UTF-8'
);
// Python - Bleach
import bleach
bleach.clean(user_input)