WPMgr 邀请链接绕过 2FA:一条旁路如何吃掉整条不变量
信益安研究院
信益安研究院
信益安信息安全研究院
2026年11月11日 19:04
湖北
去阅读
一句话结论:被邀请链接的密码验证接管了会话签发,绕过了 2FA 挑战门。
阅读说明:本文保留源码路径、关键代码、架构判断、检测与修复细节;为避免把公众号写成操作手册,具体复现命令、自动化脚本和攻击步骤移至受控技术附录。
0. 漏洞定位
WPMgr 的组织邀请接受流程会验证受邀账户的密码。在所审计的代码版本中,该流程随后直接创建登录会话,没有经过用于常规登录的 2FA 挑战门。
关键信息
- • 缺陷类别:认证流程不一致 / 会话签发旁路
- • 关键模块:
apps/api/internal/invitation/service.go - • 根因位置:
service.go:322的s.sessions.Login(...) - • 对照门禁:
apps/api/internal/auth/handler.go的issueSessionOrChallenge - • 影响前提:账户启用 2FA 且存在可用密码;邀请流程可被触发
- • 风险本质:密码被当作认证终点,第二因子没有成为所有会话签发的共同前置条件
这不是“2FA 被破解”
常规登录流程仍会在密码正确后要求第二因子。问题在于,邀请流程没有复用该认证出口。因此,安全边界被定义在“登录页”,而不是更准确的“会话签发点”。
1. 两条流程的关键差异
正常认证路径
密码验证成功
↓
issueSessionOrChallenge
↓
读取 TwoFactorEnabled
↓
已启用 2FA:返回 challenge,不签发会话
未启用 2FA:创建会话
存在问题的邀请路径
验证邀请令牌 + 验证账户密码
↓
认领邀请并写入成员关系
↓
SessionManager.Login
↓
创建会话
两个流程最终都会使用同一个会话组件,但它们在抵达会话组件前没有汇合:auth 包走统一门禁,invitation 包直接调用会话管理器。
关键判断:底层调用本身没有错;错误在于调用方绕过了“是否必须完成第二因子”的决策。
2. 源码级证据:同一个能力,两种调用语境
会话签发旁路
// apps/api/internal/invitation/service.go:322
if err := s.sessions.Login(ctx, u.ID, tenantID); err != nil {
// ...
}
这段逻辑位于邀请接受服务中。在密码验证、令牌认领和成员授权完成后,它直接创建会话;在该调用之前没有 TwoFactorEnabled 判断,也没有挑战完成状态。
受保护的对照实现
// apps/api/internal/auth/handler.go(认证门内)
if res.User.TwoFactorEnabled {
// 返回挑战,暂不创建会话
}
if err := h.sessions.Login(ctx, res.User.ID, res.ActiveTenant); err != nil {
// ...
}
对照代码说明,系统并非没有 2FA 会话门;而是邀请流程没有被纳入这个门。
应优先检查的调用点
- •
auth/handler.go:常规登录与可信设备流程,受认证门控制。 - •
auth/twofa_handler.go:TOTP、恢复码、WebAuthn 完成后才创建会话。 - •
invitation/service.go:322:邀请接受后创建会话,未进入门禁。
对这类问题,最有价值的审计动作并不是只看登录页,而是枚举全部 sessions.Login、CreateSession、SetCookie 或 token minting 调用,并逐一问:此处如何证明第二因子已经完成?
3. 架构问题:不变量写了,但没有被系统强制执行
原始设计文档把目标描述为“所有会话签发路径都通过一个 2FA 门”。这是一个正确的不变量,但实现上仍有两个薄弱点。
3.1 签发能力跨包暴露
invitation 包可以直接持有 SessionManager 并调用 Login。这使业务模块拥有了本应由认证域集中掌控的高权限能力。
更稳妥的依赖方向应是:
业务流程(邀请 / 邮箱验证 / OIDC)
↓
统一认证编排层:决定“挑战”或“签发”
↓
仅认证域可调用的会话创建能力
3.2 测试覆盖“已知入口”,而不是“所有签发点”
如果测试只覆盖密码登录、邮箱验证、OIDC 回调和首用户初始化,那么后来加入的邀请流程即使绕开门禁,也未必会让测试失败。
更有效的测试策略包括:
- • 对生产代码中的所有会话签发调用点建立清单;
- • 在代码审查或静态分析中禁止业务包直接调用会话创建;
- • 对“2FA 已开启的用户绝不在挑战前得到会话”写跨流程集成测试;
- • 将新增认证入口作为威胁建模与安全评审的必填项。
4. 这段邀请代码做对了什么,又漏了什么
做对了:单次邀请的原子性
邀请认领与成员授权采用同一事务语义,避免“令牌已消耗但授权未完成”。这一点很重要,因为单次令牌不能以“先查询、后更新”的方式实现。
if !claimed {
return AcceptResult{}, domain.Conflict(
\"invitation_already_used\",
\"this invitation has already been accepted\",
)
}
这种处理把并发失败明确为“本次认领没有发生”,避免半完成状态。
做对了:不区分撤销令牌与未知令牌
对外返回相同的“不存在”结果,可避免接口成为令牌状态探测器。这是典型且正确的 anti-oracle 设计。
漏了:认证完成与密码正确被混为一谈
密码校验只是认证的一步。对于启用 2FA 的账户,“认证完成”应当是:
密码 / 已有登录态成立
+
第二因子挑战完成
=
允许签发新会话
邀请流程在第一项成立后直接跳到了最后一步,导致原本正确的事务设计与错误的会话签发顺序并存。
5. 为什么修复不能只加一个 if
最直觉的补丁是在密码校验成功后检查 TwoFactorEnabled。但如果这时邀请已经被认领,用户尚未完成第二因子,单次令牌就可能被提前消耗。
因此,修复要同时满足两条约束:
-
- 启用 2FA 的用户在完成挑战前不能获得会话;
-
- 邀请不会因未完成的挑战而进入不可恢复的已消费状态。
可行的工程方向是:
- • 邀请流程仅创建“待完成”的接受意图;
- • 认证编排层发起或恢复 2FA 挑战;
- • 仅当挑战成功,才在同一最终化流程中认领邀请、写入成员关系并创建会话;
- • 挑战超时或失败时,待处理状态可安全清理或重试。
这也是此类修复最容易踩坑的地方:修住了 2FA 旁路,却意外制造“用户无法再次接受邀请”的可用性故障。
6. 检测:不要只盯单条日志
应用审计中的“邀请已接受”往往看起来完全合法。因此,检测重点应从单事件转向关联分析。
应收集的数据源
- • 应用
audit_log:关联邀请创建与接受事件。原稿所述表结构不包含 IP、User-Agent。 - • 反向代理访问日志:获取请求路径、来源、Cookie / Set-Cookie 元数据;必须确认日志已开启且有保留周期。
- • 会话存储遥测:将会话创建时间与认证状态关联;需控制访问权限与敏感数据暴露。
- • 2FA 挑战记录:判断会话前是否完成挑战;需处理时钟偏移与挑战有效期。
三类高价值检测思路
- 1. 会话创建与挑战缺失的关联:新会话建立附近没有相应的 2FA 成功事件时,产生高优先级告警。
- 2. 邀请者与接受者关系异常:邀请创建者和最终接受账户的审计身份不一致时,结合业务上下文复核。
- 3. 邀请接受后的会话异常:接受流程后短时间出现从未见过的组织切换、敏感权限操作或来源突变时,进行风险加权。
这些规则都需要基线与豁免机制:新用户首次接受邀请、多设备登录等正常场景可能相似,不能把简单 HTTP 特征直接当成定罪证据。
7. 防御加固优先级
P0:消除旁路
- • 把所有会话签发收敛到一个认证编排接口;
- • 禁止
invitation等业务包直接调用底层会话管理器; - • 增加“启用 2FA 后,所有入口均不得在挑战前创建会话”的回归测试。
P1:降低令牌暴露面
若业务允许,避免在创建成员邀请的 API 响应中长期返回原始邀请链接;至少限制返回场景、记录访问、缩短有效期,并避免其进入不必要的日志链路。
P1:完善可追溯性
审计事件应在隐私与合规许可范围内记录可信来源信息,例如来源 IP、User-Agent 摘要、认证强度、会话创建原因和关联挑战 ID。若审计表带哈希链,字段变更需要同步评估哈希计算与迁移策略。
P2:会话使用侧的纵深防御
对组织管理、密钥操作等高风险动作,可校验近期认证强度或第二因子完成状态,避免一次签发层遗漏立刻扩大为全局权限问题。
结语
2FA 的关键不在于登录页面多了一个验证码,而在于它必须成为所有会话创建行为都绕不过去的共同规则。
这次复盘最值得带走的工程结论是:把“创建会话”当成受控能力,而不是普通业务流程的一个便利函数。 一条未纳入认证门的边缘路径,就足以使整条安全不变量失去意义。
信益安信息安全研究院出品 | XinYiAn Security Research Institute
免责声明
本工具及相关技术内容仅供授权渗透测试、攻防演练及安全研究使用。使用者须在取得目标系统所有者书面授权的前提下开展相关工作,并严格遵守《网络安全法》及适用的法律法规。
未经授权对任何系统实施社会工程攻击或渗透测试,属于违法行为,相关法律责任由使用者自行承担,与工具作者及信益安信息安全研究院无关。
发布本文旨在提升安全从业人员的攻防认知与防御能力,请勿将上述技术用于任何非法用途。
🌟感谢您看到这里,您的支持与关注,是我们持续输出内容的最大动力
🌟欢迎加入我们的交流群
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论