Account Recovery & Verification

Chapter 9
Account Recovery & Verification
Secure password reset, email verification — the #1 takeover vector

Every chapter so far has secured the front door. This chapter secures the side door — account recovery — and it's the one attackers love most, because a recovery flow is a deliberate way to gain access without the original credential. Get it wrong and all your strong passwords, MFA, and session hardening are bypassed. This is the chapter the CSRF course's "change email → password reset → takeover" chain has been pointing at all along.

Account recovery is, by design, an authentication bypass — so it must be as strong as login
A password-reset flow exists precisely to let someone in who doesn't have the password. That makes it an alternate authentication path — and attackers attack the weakest path, not the strongest (Chapter 6). If your login uses passkeys and MFA but your reset flow emails a link, an attacker simply ignores the front door and attacks the email-based reset. Recovery is consistently the #1 account-takeover vector. Treat it with the same (or greater) rigor as login: it deserves rate limiting, anti-enumeration, secure tokens, and re-verification — not a quick "email them a link."

The Secure Password-Reset Flow

The correct shape uses a secure, single-use, expiring token delivered out-of-band (email), never a security question or a guessable code:

User requests a reset for an email. Respond with a generic message regardless of whether the account exists (anti-enumeration).
If the account exists, generate a high-entropy random token (CSPRNG), store only its hash with a short expiry and the user ID.
Email a link containing the token: /reset?token=… — sent only to the registered address.
User clicks; the server hashes the presented token and looks it up — valid, unexpired, unused?
User sets a new password; the server invalidates the token (single-use), invalidates existing sessions, and notifies the user.

Reset-Token Design — The Details That Matter

PropertyWhy
High entropy (CSPRNG)unguessable / unbrute-forceable — it's a temporary credential
Stored hasheda DB leak mustn't reveal usable reset tokens (treat like a password)
Short expirylimits the window a leaked link is useful (e.g. 15–60 min)
Single-useinvalidate on use (and on a new request) so it can't be replayed
Bound to one accounttoken maps to a specific user; can't be redirected
Three classic reset-flow bugs
(1) Predictable tokens — sequential IDs, timestamps, or Math.random() let an attacker forge a valid reset link for any account (same lesson as session IDs, Chapter 4). Use a CSPRNG. (2) Tokens that don't expire / aren't single-use — a reset link that works forever is a permanent backdoor sitting in an inbox; one that's reusable can be replayed. Expire and invalidate. (3) Host-header / link poisoning — if the reset link's domain is built from the request's Host header, an attacker can request a reset for a victim, spoof the Host so the emailed link points at the attacker's site, and capture the token when the victim clicks. Build reset URLs from a trusted, configured base URL — never from the incoming request's host.

Don't Use Security Questions

"What's your mother's maiden name?" / "First pet?" are knowledge factors (Chapter 1) that are often public or guessable — found on social media, in public records, or simply common (a handful of pet names cover most answers). They're a weak recovery method that has enabled many real takeovers. Avoid them; if a legacy system has them, treat them as one weak signal among several, never as the sole gate.

Email Verification

Verifying a new user actually controls the email they signed up with uses the same token mechanism, and matters for several reasons: it confirms the address is reachable (so recovery works), prevents signups under someone else's email, and reduces spam/abuse accounts. The flow mirrors reset: generate a high-entropy token, store it hashed with an expiry, email a single-use verification link, and mark the address verified when clicked. Keep responses generic (don't reveal "this email is already registered" to a stranger — that's enumeration, Chapter 3).

Re-Verification & Notifications for Sensitive Changes

Recovery security extends to changing the recovery channels themselves — the exact step the CSRF takeover chain exploited:

  • Re-authenticate for sensitive changes — require the current password (or an MFA challenge) before changing email, password, or MFA settings. A forged or session-riding request then can't succeed (CSRF/XSS courses).
  • Notify on every security change — email the user (at the old address too, for an email change) when the password, email, or MFA is changed, so an unauthorized change is at least visible and reversible.
  • Invalidate sessions on password reset — after a reset, kill all existing sessions, so an attacker who had a session is logged out by the legitimate recovery.
  • Cool-down / delayed change for email — some systems delay or allow a grace-period reversal of an email change, blunting silent takeover.
This closes the CSRF course's account-takeover chain
Recall the chain: a forged change-email request → attacker controls the recovery address → triggers a password reset → seizes the account. This chapter is the defence, end to end: re-authentication on the change-email step stops the forged request from succeeding; notification to the old address surfaces it if it somehow does; generic responses + rate limiting stop the attacker probing accounts; and session invalidation on reset ejects them. The recovery flow isn't an afterthought bolted onto auth — it is auth, and it's where the previous three courses' attacks converge. Secure it last in the course, but never last in priority.

Hands-On Exercises

Exercise 1

Explain why account recovery is effectively an authentication bypass and must be as strong as login. Then design a secure password-reset flow and list the five required token properties (entropy, hashing, expiry, single-use, account-binding) with the reason for each.

📄 View solution
Exercise 2

Identify and fix the bug in each reset implementation: (a) the token is the user's ID times a timestamp; (b) the reset link never expires and works repeatedly; (c) the reset URL's domain comes from the request Host header. Explain the attack each enables.

📄 View solution
Exercise 3

Walk through the CSRF course's "change email → password reset → takeover" chain, then list the recovery-side defences from this chapter that break it at each step (re-authentication, old-address notification, generic responses + rate limiting, session invalidation). Explain why each step is closed.

📄 View solution

Chapter 9 Quick Reference

  • Recovery is an authentication bypass by design — attackers hit the weakest path, so secure it as strongly as login (the #1 ATO vector)
  • Reset flow: generic response → CSPRNG token (store hashed, short expiry) → emailed single-use link → set new password → invalidate token + sessions + notify
  • Token properties: high-entropy · hashed at rest · short expiry · single-use · bound to one account
  • Classic bugs: predictable tokens · non-expiring/reusable tokens · Host-header link poisoning (build URLs from a trusted base, not the request host)
  • Avoid security questions — public/guessable knowledge factors
  • Email verification uses the same token mechanism; keep responses generic (anti-enumeration)
  • Sensitive changes: re-authenticate, notify (old address too on email change), invalidate sessions on reset, optional change cool-down
  • This closes the CSRF takeover chain — recovery is where the prior courses' attacks converge; it IS auth, not an afterthought
  • Next chapter: testing, pitfalls & a hardening checklist — the course finale