
// TL;DR
On a HackerOne Challenge (H1C) private site, the forgot-password flow leaked far more than it should have. Triggering a password reset returned the account’s own sensitive details in the HTTP response — and because the request was tied to an attacker-supplied email with no authorization check, swapping in another user’s email returned their data: personal information plus the account password as a SHA-256 hash. The hash could be cracked offline to recover the plaintext — but it didn’t even need cracking, because the login flow itself sent the password to the server as a SHA-256 hash. So you could take a victim’s leaked hash, intercept your own login in Burp, swap your hash for theirs, and log straight into their account. A clean example of why you should always look closely at forgot-password functionality — and at what the login request actually sends.
The finding
The bug lived in the forgot-password page. When I entered my own email and triggered a reset, the site returned my account’s information in the response itself — more than a reset flow has any reason to expose.
That alone is a leak. But the real issue was authorization. Intercepting the request in Burp and sending it to Repeater, I changed the email value from my own to another registered user’s email and resent it. The response came back with that user’s sensitive information — personal details such as their phone number, along with the account password stored as a SHA-256 hash.

Two things made the password exposure worse than a simple hash leak:
- The SHA-256 hash could be cracked offline to recover the plaintext password.
- But cracking wasn’t even necessary, because of how login worked on this site. The login form sent the password to the server already hashed as SHA-256 — the client computed the hash and submitted that as the credential. So the hash was effectively the password. Armed with a victim’s leaked hash, I could start logging in with my own account, intercept the login request in Burp, replace my password hash with the victim’s, forward it, and the server authenticated me as the victim.
That second point is the killer: the forgot-password page leaked the exact value the login endpoint accepts as proof of identity. So any registered user’s account could be taken over with nothing more than their email address — no cracking, no password, just a hash swap.
Why it’s serious
This is a high-severity finding because it collapses several protections at once:
- It’s mass-exploitable. The only input needed is a target’s email — no interaction from the victim, no session, no prior access.
- It discloses PII. Phone numbers and other personal details leaking in bulk is a privacy incident on its own.
- It discloses credentials. Exposing the password hash — crackable or directly replayable — means straightforward account takeover across the user base.
A forgot-password page is supposed to be a recovery mechanism. Here it became a lookup oracle for everyone’s personal data and credentials.

The three problems underneath
Stripped down, three independent mistakes stacked into a full account-takeover primitive:
- The response exposed data it never needed to. A reset flow should confirm an email was sent — nothing more. Returning account details (let alone a password hash) in the response is sensitive data leaking into a place it doesn’t belong.
- There was no authorization on whose data was returned. The email in the request was trusted as-is, so one user could request another user’s data. That’s an IDOR (insecure direct object reference) at the account level.
- The login treated a client-side hash as the credential. Because the browser hashed the password with SHA-256 and sent the hash as the thing the server checks, the hash was functionally equivalent to the plaintext password. Hashing on the client gives no security benefit here — whatever value the client submits is what an attacker can submit too. It turned the leaked hash from “something you’d have to crack” into “the login credential itself.”
Any one of these is a bug. The first two together leak credentials; the third makes those leaked credentials immediately usable. Stacked, they mean any account falls to just an email address.
Takeaways
- Always scrutinise the forgot-password flow. It touches accounts, identity, and recovery, and it’s frequently less hardened than the main login. Watch what comes back in the response, not just what renders on screen.
- Read the raw response, not the rendered page. The site may show you a tidy “check your email” message while the HTTP body quietly contains far more. Burp’s Repeater is where this kind of leak surfaces.
- Test authorization by swapping identifiers. Change the email/ID in a request to one you don’t own. If the response changes to someone else’s data, you’ve found an access-control bug.
- Inspect what the login request actually sends. If the client hashes the password and submits the hash, that hash is the real credential — client-side hashing adds no security, and any leak of it is a leak of the password. Chaining a data-exposure bug with a hash-as-credential login is a direct path to takeover.
- Credentials should never be reachable, in any form. A password that can be read back — plaintext or hash — is a design failure regardless of the algorithm.
Thanks for reading — go check those forgot-password pages. Happy hacking!
Leave a Reply