Insecure Password Reset Tokens
A password reset token is the secret a web application issues (usually by email or SMS) to prove that the person requesting a password change controls the account’s recovery channel. Because the reset flow is an alternate authentication path, its security must be at least as strong as the primary login — and it is a frequent weak point that yields full account takeover. OWASP classifies flaws here under A07:2021 – Identification and Authentication Failures.
Failure modes
Predictable token generation
Tokens built from known or guessable inputs — timestamps, usernames, email addresses, or simple hashes of them — let an attacker synthesize a valid token for an arbitrary account without accessing the recovery channel. OWASP WSTG is explicit: tokens must come from a CSPRNG with at least 128 bits of entropy, and must never be derived from known values such as md5($email) or a GUID backed by a non-random PRNG. Time-based tokens are a special case: if two reset requests are processed in the same second, they may receive identical tokens, so an attacker who triggers a victim reset and a self reset in parallel can reuse their own token against the victim.
Token leakage through the application
Even a well-generated token is useless to defend if the application discloses it in an API response. Excessive-data-exposure flaws (OWASP API3) in user-object endpoints can return the reset token alongside other sensitive fields — email, admin flags, password hashes — letting any authenticated (or unauthenticated) caller read a freshly-issued token for any user and complete the reset themselves. This chains naturally with user-ID enumeration (sequential integers) for full-account-takeover of every account on the platform, including administrators.
Missing validation and lifecycle controls
- Token not checked at all — the reset endpoint trusts a hidden
usernamefield, so submitting a new password for any account works regardless of the token (PortSwigger “broken logic” lab). - Token not invalidated after use — a used link becomes a persistent backdoor.
- No expiry — tokens that live forever extend the attack window indefinitely.
- No rate limiting / lockout — short tokens (6-digit SMS codes, ~20 bits) become brute-forceable.
- Host-header poisoning — if the reset link’s domain is built from the request’s
Hostheader, an attacker can poison the emailed link so the token is delivered to a server they control (see http and PortSwigger’s password-reset-poisoning material). Refererleakage — third-party content on the reset page can carry the token off-site in theRefererheader.
Exploitation pattern
A typical chain observed in real applications and cyber ranges:
- Enumerate user IDs on an endpoint that returns full user objects (a broken object-level authorization / IDOR flaw).
- Note that the response includes
password_reset_token(or the endpoint is unauthenticated and leaks users + salts + hashes). - Request a password reset for the target’s email.
- Re-query the endpoint to read the freshly minted token — or, when the token is time-derived (
$EMAIL-$DATE-$HOUR), synthesize it from theDateresponse header. - Submit the token with a new password; log in as the victim.
Remediation
- Generate tokens with a CSPRNG, ≥128 bits, unique per user and per reset attempt; never derive them from email, username, or timestamp.
- Return no more data than the page needs from user-object endpoints — never reset tokens, password hashes, salts, or admin flags; scope responses to the currently authenticated user.
- Invalidate tokens on first use and expire them quickly (minutes, not days); store only a hash of the token server-side.
- Rate-limit and CAPTCHA the reset request and token submission endpoints.
- Build reset links from a fixed, configured domain — never from the
Hostheader. - Require re-authentication before changing the account’s primary identifier (email/phone), so a hijacked session can’t redirect the recovery channel.
Sources
- OWASP WSTG — Testing for Weak Password Change or Reset Functionalities
- PortSwigger Web Security Academy — Password Reset Poisoning
- PortSwigger Web Security Academy — Lab: Password Reset Broken Logic
Related: xss-attacks, http, burp-suite