
Contents
- The ATO Attack Surface
- Credential-Based Attack Vectors
- Session Management Flaws
- Password Reset & Recovery Chains
- Multi-Factor Authentication Bypasses
- OAuth 2.0 / SSO Vulnerabilities
- Token & JWT Attacks
- Business Logic Flaws Leading to ATO
- Reporting ATO Findings Effectively
- Triage, Severity & Impact Framing
1 · The ATO attack surface
Account Takeover (ATO) is consistently among the top payout categories on major bug bounty platforms. Unlike many vulnerability classes that require specific technology stacks, ATO findings span every layer of the application: from HTTP headers and JavaScript logic to back-end API endpoints and third-party identity providers.
In a bug bounty context, an ATO is defined as any technique allowing one user to fully or partially control another user’s account accessing private data, performing privileged actions, or permanently locking out the legitimate owner without possessing the victim’s credentials.

2 · Credential-based attack vectors
2.1 · Username enumeration
Enumeration is the gateway to every credential attack. It transforms a brute-force problem from O(users × passwords) to O(passwords) against known accounts. Look beyond obvious HTTP 200/404 differentials:
- Timing oracles — a login endpoint that hashes the password only when the user exists will respond measurably faster for invalid usernames (no bcrypt round). Measure with 100+ requests and statistical analysis.
- Error message differences — “Incorrect password” vs. “No account found” leaks user existence even when styled identically. Check JSON error codes, not just UI text.
- Registration flow — submitting a taken email often returns a different response code, redirect, or CAPTCHA behavior.
- Password reset — “We’ve sent a reset link” shown universally is correct; anything that varies by address is enumerable.
- OAuth implicit enumeration — initiating an OAuth flow with a known email may produce a “link existing account” prompt vs. “create account.”
Tip: Always test enumeration over both the primary domain and any API subdomains (api., auth., accounts.). Back-end APIs often have weaker error normalization than the UI layer.
2.2 · Brute-force & rate-limit bypass
Modern applications impose rate limits, but bypass techniques are still frequently effective in bug bounty targets:
POST /login HTTP/1.1
X-Forwarded-For: 1.2.3.{{counter}} # IP rotation via header
X-Original-IP: 10.0.0.1
X-Remote-IP: 10.0.0.1
True-Client-IP: 10.0.0.1
- Header rotation — many reverse proxies trust X-Forwarded-For; cycling its value resets per-IP counters.
- Username normalization bypass — user@example.com, User@Example.COM, user+tag@example.com may all authenticate as the same account but consume separate rate-limit buckets.
- Password spray via slow loop — one attempt per 30 seconds across thousands of accounts evades most time-window lockouts.
- Cluster-node inconsistency — in horizontally scaled systems, rate-limit state is sometimes per-node. Rapid IP cycling across a round-robin LB can split counters.
2.3 · Credential stuffing hooks
While credential stuffing itself is an operational attack, bug bounty programs care whether the application facilitates it by lacking CAPTCHA, device fingerprinting, or anomalous-login detection. Documenting the absence of these controls as a risk amplifier strengthens the severity argument for adjacent findings.
3 · Session management flaws
3.1 · Session fixation
If the application assigns a session token before authentication and does not rotate it upon login, an attacker who can set a victim’s cookie (via XSS, subdomain takeover, or network position) can pre-authenticate a session and gain access after the victim logs in.
GET /login HTTP/1.1
→ Set-Cookie: session=ATTACKER_KNOWN_VALUE
# Victim authenticates with this session
# Attacker's session is now authenticated — no credential theft needed
3.2 · Insufficient session invalidation
- Tokens remain valid after logout (server-side state not cleared)
- Tokens remain valid after password change — critical for post-compromise remediation bypass
- Tokens remain valid after email change or 2FA enrollment
- Concurrent sessions never expire or are not listed/revocable
- “Log out all devices” functionality is cosmetic only
High impact: Demonstrating that a token captured before a password reset continues to authenticate is typically rated P1/Critical on most programs — it negates the primary account recovery mechanism.
3.3 · Session token entropy & predictability
Legacy or custom session implementations sometimes use weak token generation. Collect a large sample (500–1000 tokens) and run them through entropy analysis tools (BURP Sequencer, Dieharder). A FIPS 140-2 non-conformant token generator is reportable even before exploitation is proven.

4 · Password reset & recovery chains
Password reset flows are among the richest sources of ATO findings because they are complex, stateful, and frequently custom-built. Test each stage independently and as a chain.
4.1 · Token predictability & reuse
- Reset tokens that encode timestamp + user ID (base64, not signed) are trivially forgeable.
- Tokens that do not expire or are valid indefinitely after use.
- Tokens that remain valid after a new reset is requested — allows replay of an intercepted older link.
- Sequential or patterned tokens — generate tokens for attacker-owned accounts, infer pattern.
4.2 · Host header injection in reset emails
If the reset link domain is dynamically constructed from the Host header, an attacker who can intercept or forge the request can redirect the link to an attacker-controlled host:
POST /password/reset HTTP/1.1
Host: attacker.com
...
email=victim@target.com
# Email received by victim contains:
# https://attacker.com/reset?token=SECRET_TOKEN
Test by intercepting the reset request in Burp and modifying Host, X-Forwarded-Host, and X-Host independently.
4.3 · Token leakage in Referer / analytics
Reset links embedded with tokens in the URL path or query string may be forwarded in the Referer header when the victim clicks any link on the reset page, or logged by third-party analytics scripts loaded on the reset confirmation page. Check the page's JS includes before dismissing URL-based tokens.
4.4 · Account takeover via email change + reset
A subtle but critical logic chain: if email change does not require re-authentication and does not invalidate existing sessions, an attacker who gains temporary access (e.g., via XSS) can silently change the email address, then use the password reset flow to fully take over the account — while the victim is still logged in with no indication anything changed.
5 · Multi-factor authentication bypasses
5.1 · MFA step skip
After successful primary authentication, the server issues a pre-MFA session cookie and expects the client to complete the second factor. Many implementations only verify MFA when the client actually submits the code — they do not enforce that MFA was required before issuing the full session. Test by:
1. POST /login → 200 OK + pre-MFA cookie
2. Skip /mfa/verify entirely
3. GET /dashboard → check if full access granted with pre-MFA cookie
5.2 · TOTP code reuse
TOTP codes are valid for 30 seconds. A used code must be invalidated server-side until the window expires. If the server only validates the mathematical correctness of the TOTP and does not track used codes, the same code can be replayed within its validity window — relevant in MITM scenarios.
5.3 · Backup code exhaustion & fallback abuse
- Backup codes with no rate limit can be brute-forced (typically 8-digit numeric = 10⁸, feasible if no lockout).
- SMS fallback with no rate limit on the send endpoint allows both number enumeration and toll fraud.
- Fallback to security questions that are trivially answerable from public social profiles.
- “Can’t access your authenticator?” flows that drop MFA entirely after email verification — reduces to single-factor security.
5.4 · Response manipulation
On single-page applications, the MFA verification response is sometimes a JSON flag read by client-side JavaScript. Intercepting the response and changing {"mfa_verified": false} to true may bypass the check entirely if session elevation is managed client-side.
Note: Response manipulation findings are frequently disputed on programs that require “no client-side trust assumption.” Document explicitly that the server issued a privileged session token as a result — that makes the impact server-authoritative.
6 · OAuth 2.0 / SSO vulnerabilities
6.1 · State parameter missing or not validated
The state parameter serves as a CSRF token for the OAuth flow. If absent or not validated, an attacker can initiate an authorization flow and trick a victim into completing it, binding the attacker's authorization code to the victim's session (OAuth CSRF → ATO).
Attacker: GET /auth/oauth/start → redirect_uri=...&state=ATTACKER_STATE
Attacker: copies the authorization URL before code exchange
Victim: visits the attacker's URL, authenticates with their IDP
IDP: redirects to callback with code tied to victim's identity
Attacker: uses code to authenticate as victim
6.2 · Redirect URI validation bypass
The OAuth callback URL must be exact-matched against registered values. Weak validation allows code theft:
- Prefix match only: https://target.com.evil.com/cb
- Path traversal: https://target.com/callback/../open-redirect
- Fragment injection: https://target.com/callback#@evil.com
- Registered wildcard subdomains: attacker controls https://any.target.com/ via subdomain takeover
- Registered path accepts query params: code leaked via open redirect on same path
6.3 · Account linking / pre-hijacking
If a target application allows linking a social login to an existing email account, and does not verify ownership of that email before linking, an attacker can:
- Register an account with the victim’s email address (if email verification is not required immediately).
- Link their own OAuth identity (attacker’s Google/GitHub) to this unverified account.
- When the victim later registers or logs in via OAuth with their real provider identity, the application merges the accounts — granting the attacker access.
6.4 · Token leakage via referrer in implicit flow
Applications still using the implicit flow (response_type=token) return the access token in the URL fragment. If the post-login page loads third-party resources, some browsers send a Referer header including the fragment — leaking the token to those origins.
7 · Token & JWT attacks
7.1 · Algorithm confusion (alg:none / RS256→HS256)
The classic JWT attack vectors remain valid when applications accept the alg field from the token header without enforcing a fixed algorithm server-side:
# alg:none — no signature required
{"alg":"none","typ":"JWT"}.{"sub":"admin","role":"superuser"}.
# RS256 → HS256 confusion
# If server uses RS256 public key as HMAC secret when alg is HS256,
# sign with the public key (which is often publicly accessible) → valid sig
7.2 · Weak secret brute-force
HMAC-signed JWTs using weak or default secrets (secret, password, application name) can be cracked offline with hashcat mode 16500 or jwt-cracker. Once the secret is known, arbitrary payloads can be signed.
7.3 · JWT claim injection via nested objects
Parsers that flatten nested JSON or use insecure path-based claim extraction can be confused by injecting claims in unexpected positions:
{"alg":"HS256"}.{
"sub": "user123",
"role": "user",
"admin": {"$ne": null}, // MongoDB operator injection if claims passed to query
"iat": 1234567890
}7.4 · Kid header injection
The kid (key ID) header tells the server which key to use for verification. If the server uses kid as a file path or database query without sanitization, SQL injection or path traversal can direct verification to an attacker-controlled key value.
8 · Business logic flaws leading to ATO
8.1 · Insecure direct object reference on account actions
Endpoints that accept a user ID or account identifier as a parameter without re-validating authorization against the session are classic IDOR-to-ATO pathways:
POST /api/account/update-email
{"user_id": "12345", "email": "attacker@evil.com"}
# Does the server verify session belongs to user 12345?
8.2 · Race conditions in authentication state
Concurrent requests during a login or verification flow can exploit non-atomic state transitions. For example, sending two simultaneous MFA verification requests with different codes may cause both to succeed if the server checks against a shared state variable without locking:
- Use Burp’s “Send in parallel” or Turbo Intruder for precise timing.
- Target operations that check-then-act on shared state: token validation, OTP verification, login attempt counters.
- Race windows as small as 10–50ms can be sufficient.
8.3 · Trust boundary violations in microservices
In microservice architectures, internal services often skip authentication because they assume all inbound traffic is internal. If any user-facing surface forwards attacker-controlled data to an internal service endpoint (via SSRF, header injection, or parameter passing), the attacker may authenticate as any user by supplying an arbitrary user identifier.
9 · Reporting ATO findings effectively
A technically brilliant ATO finding can be downgraded or closed as “informational” due to poor reporting. In bug bounty, the report is the product — it must be as rigorous as the research.
9.1 · Report structure for ATO
- Title — precise: “Pre-authentication CSRF in OAuth flow enables ATO without victim credentials.” Not: “OAuth vulnerability.”
- Summary — 3–4 sentences: what the bug is, how it’s exploited, what the attacker gains, minimal prerequisite.
- Steps to reproduce — exact HTTP requests, preferably as raw Burp exports. Every step numbered. Reproducible by a triage engineer who has never seen the application.
- Proof of concept — a video or at minimum annotated screenshots showing the attacker accessing victim account data. Without PoC, many programs will request one before triaging.
- Impact — answer: what can the attacker do, to whom, with what effort, at what scale? Is it one account or every account?
- Suggested remediation — actionable, specific, not generic.
9.2 · Demonstrating impact without harming accounts
Use only accounts you own or have explicit written permission to test. For ATO demonstrations, create two accounts (attacker + victim), execute the attack, and capture evidence of the attacker session accessing victim-only resources (e.g., victim’s profile data, private messages, or billing info). Never test on real user accounts — doing so can get your program membership revoked and raises potential legal liability.
10 · Triage, severity & impact framing

10.1 · Chaining findings to escalate severity
Individual low/medium findings frequently chain to critical ATO. Common chains worth documenting:
- Subdomain takeover + broad cookie domain → attacker-controlled subdomain reads session cookie → full ATO
- Open redirect + OAuth → redirect authorization code to attacker server → ATO without victim credentials
- XSS + missing HttpOnly + long-lived token → persistent session theft even after browser close
- Username enumeration + no rate limit + weak password policy → targeted brute-force at scale
- CSRF on email-change + missing re-auth → silently change email → use password reset → full ATO
Program perspective: Chains are more persuasive to triage when each link is independently verified with a request/response pair. Show that A enables B and B enables C — don’t assume the reviewer will make those connections themselves.
This article is intended for authorized security research and bug bounty testing only. All techniques described should be tested exclusively on accounts and targets where you have explicit written authorization. Responsible disclosure via the program’s defined channel is required before publishing any finding.