找回过程中不应向未验证身份者暴露账号是否存在
别名: 账号枚举 · user enumeration via forgot password · 邮箱是否注册
概念解释
未登录的人在找回框里输入一个邮箱或手机号。若界面回答「该账号不存在」或「验证码已发送」这两种不同结果,等于告诉对方这个标识有没有注册。不暴露存在性指对未验证者始终给出同一类响应(「如果该邮箱有账号,我们发了邮件」),真正的差异只出现在持有该邮箱的收件箱里。这条管找回流程的枚举面。已登录设置里列出自己的绑定方式不是枚举;登录页用错密码的时机差来猜存在性也是枚举,但那是登录而不是找回。
机制
账号存在性是攻击者的通讯录:可被用来定向钓鱼、撞库、或判断哪位名人用了这款产品。找回接口天然按标识查询,最容易把存在性做成错误码。即使用词中性,响应时间、邮件是否真的发出、HTTP 状态码不同,仍会泄漏。防护要把查询、发信、计时做成常量化:不存在的标识也走同样时长和同样的前端句子;发信只在标识确实绑定且通道可用时发生,但前端不报告这一支。持有通道的人从邮件内容得知「有账号」;不持有的人什么也得不到。限流仍然需要,否则枚举改走「对每个地址等一封信」。
怎么研究
对已知存在与已知不存在的标识各打找回接口,比较响应体、状态码、时延分布,以及前端文案。
自变量:文案是否成对差异、是否做常量化时延、是否对不存在的标识也假装成功。 因变量:仅凭响应区分存在性的准确率、持有邮箱者是否仍能完成找回、因「没明说发出」而不知去查收件箱的比例。
不要在实验室只看文案字符串——要看时延直方图和状态码。可用性上,中性文案会让部分人以为没发出;补救是在文案里教人查垃圾箱,而不是改回「账号不存在」。登录接口的枚举要单独测,不能用找回修了就宣布登录也修了。
边界
企业 IdP 发现未知邮箱时必须拒绝开通,存在性泄漏是开通流程的一部分,与面向公众的自助找回不同。已登录用户改自己的邮箱,系统必须告诉「这个新地址已被占用」,那是对已验证者的冲突提示。公开个人主页本身就声明了存在,找回接口再藏存在性意义有限,但仍不该在找回框里多嘴。客服人工查找账号可以确认存在,前提是客服已通过自己的身份核验,不是网页上的未验证者。
怎么落地
- 找回提交对任何格式合法的标识返回同一句话和同一状态码,例如「如果有这个账号,重置说明已发送」。
- 后端对存在与不存在走相近耗时;不存在不发信,存在才发;前端无分支。
- 邮件主题与预览不要在未打开时就用「你没有账号」这种句子;有账号才发信。
- 验证:脚本对一批存在与不存在的地址提交找回,仅凭响应无法优于随机地分类。持有测试邮箱的人应仍能收到链接并完成重置。把时延画成分布,两组应重叠而非双峰。