October 23, 2026
Offline Password Cracking
Stealing someone else’s session cookie through a stored XSS, then reversing it on a machine they’ve never touched

By Kaustubh Asthana
6 min read
Every lab in this series so far has attacked a login mechanism directly, guessing passwords, racing two-factor codes, forging a cookie by rebuilding its format from scratch. This one takes a different route entirely. Instead of attacking the login form, I attacked a comment box, used it to steal a cookie belonging to a user who was never anywhere near my own browser session, and only then turned to a password cracker to finish the job completely offline, away from the application and its rate limits altogether.
The Target
The lab's blog has a comment section on every post, and the goal is to end up logged in as carlos and delete his account. Carlos never logs in through anything I can see or intercept. The only way in is through whatever his browser does on its own when it visits a page I control content on, which in this case is the comment section.
Confirming the Comment Field Actually Executes Script
Before building anything elaborate, I needed to know the comment field would run injected script at all. I opened one of the blog posts and had a look at the existing comments first, just ordinary visitor remarks with nothing unusual about them.
Then I posted a comment with nothing in it but a script tag wrapping a simple alert call, printing the number one.
The site redirected to a confirmation page after submitting.
Navigating back to the post triggered a browser alert box showing the number one, which meant the comment field stores whatever gets submitted and renders it without encoding it first. That's a stored cross-site scripting vulnerability, and unlike a reflected one, it doesn't need me to trick anyone into clicking a crafted link, the payload just sits there in the page waiting for the next visitor.
Understanding the Cookie Before Attacking It
I already had a rough idea of what the stay-logged-in cookie looked like from an earlier lab in this series, but I wanted to confirm it on this target before relying on it. I pulled up a request I'd made in my own session, logged in as wiener, and checked the cookie Burp had captured.
Same structure as before, username, then a colon, then the MD5 hash of the password. I ran that hash through CrackStation as a sanity check before trusting the whole approach, and it came back correctly as peter, wiener's actual password.
That confirmed two things. The cookie format on this lab matched what I expected, and a plain MD5 hash with no salt is exactly the kind of thing a public rainbow table lookup cracks instantly, no brute forcing required on my end at all
Setting Up Somewhere to Catch the Cookie
An attacker-controlled exploit server is the piece that makes this whole technique work, and it's worth being precise about what it actually does here. It isn't hosting the malicious script, the comment field is doing that job directly. What the exploit server provides is a destination outside the vulnerable application that carlos's browser can actually reach, and a log of every request that destination receives. I configured it to serve a basic JavaScript response just to have something valid sitting behind the endpoint.
Writing the Real Payload
This is where document.location and document.cookie do the actual work, and it's worth being specific about what each one is doing rather than treating the payload as a black box.
document.cookie is a property any script running on a page can read, and reading it returns every cookie the current browser has stored for that site that isn't marked HttpOnly, as one semicolon-separated string. Script injected through a stored XSS runs inside whatever browser loads the page, with that browser's own cookies, not the attacker's. That's the entire point of stealing a cookie this way rather than any other, the script executes as carlos, in carlos's browser, with carlos's session, the moment carlos's browser renders the comment I posted.
document.location is the property that holds the page's current URL, and setting it to a new value navigates the browser there immediately, the same as typing an address into the bar. So a payload that sets document.location to my exploit server's URL, with document.cookie appended straight onto the end, does two things in sequence the instant it runs. It reads out whatever cookies the visiting browser is holding, then forces that same browser to make a request to a server I control, carrying those cookies along as part of the URL it requests.
I posted that as the comment.
Catching the Cookie
This is the part that actually answers how I ended up with carlos's cookie while I'd been logged in as wiener this entire time, I didn't steal it from my own session at all. The lab's simulated visitor, logged in as carlos with stay logged in enabled, loaded the blog post containing my comment. Their browser ran the script, read their own cookies, and sent a request to my exploit server carrying them along. My own login state never factored into the theft, the victim's browser did all the work using the victim's own session.
I checked the exploit server's log afterward.
Carlos's stay-logged-in value was sitting right there in plain text in the log line, exactly as his browser had sent it.
Decoding and Cracking
I dropped that value into Burp's Decoder and ran it through a base64 decode.
That gave me carlos's username paired with the MD5 hash of his password, same format I'd already confirmed on my own account. Straight to CrackStation with it.
Finishing the Job
With a real username and a real plaintext password, logging in was just filling out the form.
The lab's objective was to delete his account, so I went to the account page and did exactly that.
Why This Matters
The interesting thing about this lab is how little of the actual password-cracking work happens inside the vulnerable application at all. The XSS gets you a hash, and from the moment that hash leaves the application's server, everything else, the decoding, the lookup, the final login, happens entirely on infrastructure the application has no visibility into and no ability to rate-limit, log, or block. That's what offline cracking means here, it's not about speed, it's about moving the attack somewhere the target can't see it happening.
It's also a reminder that a stay-logged-in cookie built from a reversible hash is a liability the moment anything on the site can read cookies and make an outbound request, which in practice means the moment any stored XSS exists anywhere on the domain. The authentication mechanism itself can be solid and still get undone by a completely unrelated feature, a comment box, that was never designed with session security in mind.
akeaways From This Lab
- A stored XSS payload executes in the victim's browser, with the victim's session, regardless of what session the attacker who planted it happens to be using at the time.
- document.cookie reads whatever cookies the current page can see, and document.location redirects the browser, so combining them turns a single script tag into a cookie exfiltration channel with no further infrastructure needed beyond somewhere to receive the request.
- The exploit server's job in this attack wasn't hosting the payload, it was being a reachable destination outside the application with a log the attacker can actually read afterward.
- An MD5 hash with no salt is not meaningfully different from a plaintext password once it's been seen by a public rainbow table lookup, which makes the hashing algorithm, not just the cookie's encoding, part of what actually needs fixing here.