Account Takeover (ATO)
debt(d7/e7/b7/t7)
Closest to 'only careful code review or runtime testing' (d7). While semgrep is listed as a tool and can catch specific patterns like md5-based tokens or missing session_regenerate_id, the detection_hints explicitly state automated detection is 'no'. ATO vulnerabilities span multiple flows (login, password reset, session management, OAuth) and most of the common_mistakes (missing session invalidation after password change, no rate limiting, trusting client-supplied user IDs) require careful manual code review or penetration testing to identify comprehensively. A single semgrep rule catches only a narrow slice.
Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix says 'audit the full authentication flow' covering password reset tokens, session regeneration, and rate limiting on all auth endpoints. The common_mistakes span login, password reset, session management, and OTP endpoints — these are distinct subsystems. Fixing all ATO vectors requires changes across multiple files and components (session handling, token generation, rate limiting middleware, email-change flows). This is not a single-line fix but a cross-cutting security hardening effort.
Closest to 'strong gravitational pull' (b7). ATO defences touch authentication, session management, password reset, OAuth, and rate limiting — these are cross-cutting concerns that shape how every auth-related feature is built. Every new feature involving user identity (email change, 2FA enrollment, API key management) must consider ATO. The tags (authentication, session, owasp-top10) confirm this is load-bearing across the system. It doesn't quite reach b9 because it's scoped to auth flows rather than defining the entire system architecture.
Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7). The misconception field is explicit: developers believe ATO 'always requires stealing a password,' when in reality attackers frequently use password reset flaws, session fixation, or OAuth misconfigurations — no password needed. This is a serious cognitive trap because a competent developer focused on password security (strong hashing, breach detection) will believe they've addressed ATO while leaving session fixation, weak reset tokens, and missing session invalidation completely unguarded. The mental model of 'protect the password = protect the account' is intuitive but dangerously incomplete.
Also Known As
TL;DR
Explanation
Account takeover aggregates multiple attack vectors: credential stuffing (testing breached username/password pairs at scale), password spraying (common passwords against many accounts), phishing (fake login pages), session hijacking (stolen cookies), and broken password-reset flows (predictable tokens, user-enumeration, host-header injection in reset emails). Defences form layers: bcrypt/argon2 password hashing, rate limiting login and reset endpoints, multi-factor authentication, breach-password detection (HaveIBeenPwned API), login anomaly detection (new device/IP), secure HttpOnly+SameSite session cookies, and short-lived password-reset tokens bound to the requesting IP stored as a hash.
Diagram
flowchart TD
subgraph Attack Vectors
CRED[Credential Stuffing<br/>leaked passwords]
PHISH[Phishing<br/>fake login page]
SIM[SIM Swap<br/>bypass SMS 2FA]
SESS[Session Hijack<br/>steal cookie]
RESET[Password Reset<br/>weak flow]
end
subgraph Defences
MFA[Strong 2FA<br/>TOTP not SMS]
RATE[Velocity checks<br/>per account]
NOTIF[Login notification<br/>email on new device]
CSESS[Concurrent session<br/>detection]
RECOV[Secure recovery flow<br/>identity verification]
end
CRED --> MFA
SIM --> MFA
PHISH --> NOTIF
SESS --> CSESS
RESET --> RECOV
style MFA fill:#238636,color:#fff
style RATE fill:#238636,color:#fff
style NOTIF fill:#238636,color:#fff
Watch Out
Common Misconception
Why It Matters
Common Mistakes
- Not invalidating all existing sessions after a password change.
- Weak or predictable password-reset tokens that expire too slowly.
- No rate-limiting on login, reset, or OTP endpoints.
- Trusting client-supplied user IDs in session data rather than reading from the server-side session.
Avoid When
- Do not implement security theatre (e.g. re-CAPTCHA only) without layered controls — bots solve CAPTCHAs routinely.
- Avoid storing session tokens in localStorage — XSS can exfiltrate them; use HttpOnly cookies instead.
When To Use
- Apply ATO defences on any account that controls money, data, or downstream user trust (admin accounts, payment accounts, OAuth providers).
- Use this threat model when reviewing login, password-reset, session management, and email-change flows.
Code Examples
// No re-auth required — attacker with stolen session can change email
public function updateEmail(Request $req): Response {
auth()->user()->update(['email' => $req->email]);
return response()->json(['ok' => true]);
}
public function updateEmail(Request $req): Response {
// Require current password for sensitive account changes
if (!password_verify($req->current_password, auth()->user()->password)) {
return response()->json(['error' => 'Password incorrect'], 403);
}
$newEmail = $req->validate(['email' => 'required|email|unique:users'])['email'];
// Send verification to NEW address before applying
$token = bin2hex(random_bytes(32));
Cache::put('email_change:' . $token, ['user_id' => auth()->id(), 'new_email' => $newEmail], now()->addHour());
Mail::to($newEmail)->send(new VerifyEmailChange($token));
return response()->json(['message' => 'Check your new email to confirm the change']);
}