Gitlab 密码重置漏洞让超过 5.3K 台服务器任人“捡走”
一个严重的 GitLab 漏洞(CVE-2023-7028)让攻击者能够利用基于 Rails 的应用对多个 email 参数的处理方式,诱使系统同时向受害者和攻击者自己的地址发送密码重置邮件,可能影响数千台自建服务器。评论者借此强调了基于邮箱的密码找回、类型不安全的 Web 框架以及仓促功能开发的长期隐患,同时强调了严格的后端校验、仅通过 VPN 访问、SSO 和强制 2FA 等缓解措施。
利用机制与根因
- 核心漏洞:密码重置端点接受多个
email参数(一个数组)。 - GitLab 会先按其中一个邮箱查找用户,但随后把重置码发送给 所有 提供的地址,包括攻击者控制的地址。
- 示例载荷:
user[email][][email protected]&user[email][][email protected]。 - 修复方式:使用用户记录中保存的邮箱发送重置指令,而不是使用用户提交的值,并且从“可恢复”对象本身获取地址。
- “RecoverableByAnyEmail” 这个特性(最初意在支持任意/任意已验证邮箱)被认为在概念上很危险,其命名也受到了批评。
密码重置与账户标识设计
- 很多人认为基于邮箱的重置流程“令人恐惧”,长期以来一直是漏洞高发区,尤其是在“关联备用邮箱”之类功能周围。
- 推荐设计:将账户 ID 和邮箱视为不同概念;内部使用账户 ID,只从数据库派生邮箱,绝不从请求参数中获取。
- 有人建议使用用户名,或者恢复时同时要求用户名和邮箱;也有人指出这会带来可用性权衡以及用户对额外摩擦的反感。
- 邮箱别名(
+tag)可以帮助掩盖真实标识符,但如果服务与邮件提供商对地址的规范化方式不同,就会带来 UX 问题和冲突问题。
邮箱作为薄弱的安全通道
- 邮箱被批评为不安全:令牌容易被转发或泄露,发件人验证只做了部分且不一致的检查,默认没有端到端加密,规范化也含糊不清,而且高度依赖某一个收件箱的安全性。
- 如果一个邮箱账户或其域名被劫持或重新注册,许多关联服务都会变得极易被入侵。
- 有人希望恢复流程能要求多种因素(例如邮箱 + 短信),但表示这类支持很少见。
GitLab 的安全与工程质量
- 观点分歧很大:
- 一方认为,即使安全团队很强,关键漏洞也难免发生,而 GitLab 的开源特性让问题更容易被看见。
- 另一方则把频繁出现的高危 CVE、仓促交付功能、痛苦的升级,以及长期存在的 CI/UX 漏洞视为工程文化薄弱或资源不足的迹象。
语言/框架与设计争论
- 一些人把问题归咎于 Rails/Ruby 灵活的参数处理(数组 vs 标量)以及“聪明过头”的抽象。
- 也有人反驳说,类似的逻辑漏洞同样会出现在静态类型栈(Java/C#)中,而且没有哪个主流生态能交出干净的安全记录。
- 更强的类型系统和更安全的 API(例如 Django 的
getlist、类型化查询构建器)被视为能把一部分逻辑错误变成编译期失败的手段。
运维缓解与部署实践
- 许多人认为 GitLab 不应直接暴露在公网;而应放在 VPN/SSO 之后,使用 2FA,并与企业身份系统(例如 AD)集成。
- 有些人表示,2FA 和有限的外部暴露在他们那里缓解了这次事件。
- 还有人指出,通过容器和 Watchtower 之类工具进行自动、频繁的 GitLab 更新,可以缩短攻击窗口,并质疑为什么仍有这么多实例没有及时更新。