Browse CTFs New CTF Sign in

2FA logic flaw

crypto_asymmetric Difficulty 1–5 30 min certifiable

Theory

Why This Matters

Multi-factor authentication is widely regarded as the single most impactful control for preventing account takeover, with Microsoft reporting it blocks more than 99.9% of automated credential attacks. Yet MFA is only as strong as the logic that enforces it. CVE-2023-34960 (Chamilo LMS), multiple Uber-related incidents, and the 2022 Twilio breach (which led to the Okta compromise) all involved MFA bypass via logic flaws rather than cryptographic weakness — attackers navigated directly to post-authentication endpoints, manipulated server responses, or exploited missing session binding between the authentication steps. These bypasses demonstrate that adding an MFA step does not automatically create a secure authentication flow.

Core Concept

A two-factor authentication (2FA) logic flaw exists when the server does not correctly enforce that all authentication factors have been successfully verified before granting access to a protected resource. Unlike a cryptographic attack on the OTP algorithm itself, a logic flaw exploits incorrect state machine implementation in the authentication flow.

The most common variant is OTP step skipping: after supplying valid credentials in step 1, the server issues a partially-authenticated session. If the server fails to verify that this session has completed step 2 before honouring requests to authenticated endpoints, an attacker who knows the URL of a post-authentication page can navigate there directly, bypassing the OTP challenge entirely. The server's mistake is granting a partially-privileged session token at the end of step 1 and relying on the client to proceed through step 2 — rather than treating the session as unauthenticated until all factors are complete.

Response manipulation is a related attack: the OTP challenge endpoint returns a 401 with {"status": "error", "message": "Invalid OTP"} for a wrong code and a 200 with {"status": "success", "redirect": "/dashboard"} for a correct one. If the client-side JavaScript is responsible for checking the status and redirecting, and the server accepts the session as authenticated upon receipt of the OTP endpoint request regardless of code validity, then intercepting the 401 and changing it to a 200 in Burp Suite's proxy causes the browser to treat the login as successful.

An OTP not tied to session vulnerability occurs when the server validates any currently-valid TOTP code against any account rather than the specific account whose session initiated the challenge. An attacker who controls one account can use their own valid OTP to complete another account's 2FA challenge.

TOTP brute-force against a 6-digit code is theoretically bounded by the one-million possible values, but with a 30-second window and a ±1 window tolerance the practical space is 3 codes at any moment. Without lockout on the OTP endpoint, an attacker can cycle all 1 000 000 values in minutes.

Technical Deep-Dive

Testing step-skipping with Burp Suite:

-- Step 1: Submit valid credentials
POST /login HTTP/1.1
Host: target.example.com
username=victim&password=correct_password

-- Response issues a partial session
HTTP/1.1 302 Found
Location: /login/otp
Set-Cookie: session=abc123partial; Path=/

-- Step 2: Skip OTP — navigate directly to authenticated endpoint
GET /dashboard HTTP/1.1
Host: target.example.com
Cookie: session=abc123partial

-- If server responds 200 with dashboard content, step-skip succeeded

Response manipulation in Burp Proxy (Intercept response):

-- Original server response to wrong OTP:
HTTP/1.1 401 Unauthorized
{"verified": false, "message": "Incorrect OTP"}

-- Attacker modifies in Burp before forwarding to browser:
HTTP/1.1 200 OK
{"verified": true, "message": "Login successful"}
-- If the browser now redirects to /dashboard and server honours the session,
-- the application delegated the authentication decision to the client

Brute-forcing a 6-digit TOTP without lockout:

import requests

url = "https://target.example.com/login/verify-otp"
cookies = {"session": "abc123partial"}

for code in range(0, 1000000):
    otp = f"{code:06d}"
    r = requests.post(url, data={"otp": otp}, cookies=cookies)
    if "dashboard" in r.text or r.status_code == 200:
        print(f"[+] Valid OTP: {otp}")
        break

Security Assessment Methodology

  1. Map the full authentication flow — Use Burp Suite to capture every request from initial login through post-authentication page access. Identify the cookies or tokens set at each step and note which endpoints are accessed.
  2. Test direct navigation (step skipping) — After step 1, copy the partially-authenticated session cookie into a fresh browser session with no prior step-1 history. Navigate directly to the post-authentication URL (e.g., /dashboard, /account). If the server serves the authenticated content, the OTP step is not enforced server-side.
  3. Test response manipulation — In Burp Proxy, enable response interception. Submit an intentionally wrong OTP. When the server sends back a failure response, modify the status code and body to match a success response, then forward. Check whether the browser gains access.
  4. Test cross-account OTP reuse — Log in with account A up to the OTP step. Get a valid OTP from your own authenticator app for account A. Submit it to the OTP verification endpoint while the pending session belongs to account B. If it succeeds, OTPs are not session-bound.
  5. Test OTP brute-force tolerance — Submit 10–20 sequential wrong OTPs. If no lockout occurs (no 429, no account lock, no CAPTCHA), document the absence of rate-limiting and estimate the feasibility of full brute-force within the TOTP window.
  6. Test OTP reuse after success — After correctly completing 2FA, attempt to reuse the same OTP code immediately. A secure implementation must reject it as already consumed.

Defensive Countermeasure — Treat the session as completely unauthenticated until all factors are verified server-side: issue a cryptographically opaque, step-bound state token at step 1 that grants access only to the OTP verification endpoint, never to application resources, and promote it to a full session token only after server-side OTP validation succeeds.

Common Assessment Errors

  • Testing only the happy path — Many testers verify that correct credentials plus correct OTP works. The logic flaw tests require intentionally incomplete or wrong inputs to probe state machine enforcement.
  • Forgetting to test the OTP endpoint from a separate session — Step-skipping must be tested with a cookie that has never visited the OTP page in the same browser context; testing from the same browser tab can exploit cached navigation state and give a false negative.
  • Not checking OTP validity window — TOTP implementations that accept codes from ±5 windows (±150 seconds) drastically reduce brute-force effort. Document the accepted window by submitting intentionally stale codes.
  • Missing the account enumeration in step 1 — The username validity check in step 1 is often distinct from the password check; different error messages can enumerate valid accounts even when 2FA is enabled.
  • Ignoring backup code flows — Backup/recovery codes are a separate authentication path that often lacks the same protections as TOTP. Always test the backup code flow independently.
  • Overlooking magic-link and SSO bypass paths — Applications that support "login with Google" or magic-link email login may bypass the 2FA step entirely if the SSO flow is not integrated with the 2FA state machine.

NICE Framework Alignment

Code Knowledge/Skill/Task Statement How This Card Develops It
K0007 Knowledge of authentication, authorisation, and access control methods Deeply covers multi-factor authentication state machine design and the logic flaws that arise from incorrect implementation
K0065 Knowledge of policy-based and role-based access controls Explains why partial session promotion creates an access control gap in role-based systems
S0001 Skill in conducting vulnerability scans and recognising vulnerabilities in security systems Trains step-skipping, response manipulation, and brute-force testing techniques with concrete tooling
T0028 Conduct and/or support authorised penetration testing on enterprise network assets Provides an end-to-end MFA bypass assessment methodology applicable to real engagement scenarios

Further Reading

  • OWASP Testing Guide v4.2, OTG-AUTHN-006: Testing for Bypassing Authentication Schema — OWASP Foundation
  • OWASP Cheat Sheet Series: Multifactor Authentication — OWASP Foundation
  • Real-World Two-Factor Authentication Bypasses — Portswigger Web Security Research (blog series)

Challenge Lab

Reinforce your learning with a hands-on generated challenge based on this card's competency.