3.1 密码重置:被忽视的认证后门


3.1 密码重置:被忽视的认证后门

本节摘要:本节拆解密码重置流程的攻击面:可预测的重置令牌、不过期的链接、可重放的验证码、回答即可改密的-secret 问题。重置是认证体系里授权最重的接口之一,却常常按"辅助功能"的标准开发,本节给出令牌设计五要素与旁路封堵清单。

绕过前门的侧门

口令回合铩羽而归的红队,在登录页角落发现了"忘记密码"。这四个字背后藏着的逻辑是:跳过你已设置的口令,直接换一把新钥匙。如果重置流程自身不够硬,它就是整栋大楼的侧门——正门换了装甲锁,侧门却是碰锁。真实事件里,重置链路被攻破导致账号接管的案例屡见不鲜,社交媒体高管账号、加密资产账户的失守,相当一部分走的就是这条路。

重置流程的特殊性在于它的信任锚换了:登录时信任"口令正确",重置时信任"能收到邮件或短信"。锚点一换,整个攻击面也跟着换——攻击者不再猜你的密码,而是想办法截你的邮件、猜你的令牌、骗你的短信。

后门是怎么留出来的

盘点典型的失守姿势。其一是令牌可预测:用时间戳、用户名哈希、自增序号当令牌,攻击者注册一个账号就能反推规律。其二是令牌不过期:一条重置链接几个月后仍有效,给了截获者充裕的使用窗口。其三是令牌可重放:用过的链接还能再用,重置完成不失效。其四是验证码可爆破:短信验证码连着数字,接口又无限流,几分钟内可穷举。其五是找回逻辑走"秘密问题",而问题的答案(母校、宠物名)早就挂在社交网络上。其六是旁路泄露:输入已注册邮箱提示"该账号存在",重置流程反过来成了账户枚举的素材库。

靶场里的翻车现场长这样:

# 反面教材(靶场复现):几种危险的重置令牌生成方式 import hashlib, time def bad_token_v1(user_id: int) -> str: return hashlib.md5(str(user_id).encode()).hexdigest() # 规律可推 def bad_token_v2(user_id: int) -> str: return hashlib.md5(f"{user_id}:{int(time.time())}".encode()).hexdigest() # 时间戳粒度太粗,攻击者注册账号+收邮件即可夹逼出密钥空间 # 靶场演示:攻击者视角的夹逼思路(仅验证可预测性,不发起真实请求) # 1) 注册自己的账号,请求重置,收到的 token 记为 t1,本地时间为 s1 # 2) 对目标请求重置,收到时间窗内的候选 token = md5(uid:s) for s in [s1-60, s1+60] # 3) 候选集合仅数千个,逐个试接口即可命中——熵值崩塌全过程

3) 候选集合仅数千个,逐个试接口即可命中——熵值崩塌全过程

靶场演示:整改版的正确姿势

# 本地靶场:合格的重置令牌全生命周期 import secrets, time RESET_TTL = 600 # 十分钟 def issue_reset_token(user) -> str: token = secrets.token_urlsafe(32) # 高熵随机,不可夹逼 reset_store.set( token, {"uid": user.id, "exp": time.time() + RESET_TTL, "used": False}, ttl=RESET_TTL, # 存储层同步过期 ) send_mail(user.email, render("reset", token=token)) # 无论如何都返回同一句话,防枚举: return "若该邮箱已注册,重置邮件已发出" def consume_reset_token(token: str, new_password: str): rec = reset_store.get(token) if rec is None or rec["used"] or rec["exp"] < time.time(): return fail("链接无效或已过期") # 不区分原因,不给旁路信息 reset_store.mark_used(token) # 先占位,防并发重放 user = db.get_user(rec["uid"]) user.set_password(new_password) # 走慢哈希存储 session.revoke_all(user.id) # 吊销全部旧会话 notify(user, "您的密码已被重置,如非本人操作请立即联系客服") return ok("密码已重置")

几处细节值得放大:secrets 而非随机数模块,保证密码学强度;"先标记已用再处理"防并发窗口内重放;重置完成后吊销全部会话,把"改钥"的效力立刻传导到所有在线身份;通知用户是最后一道人肉哨兵——本人没操作却收到重置成功,就是最准的告警。

蓝队整改:重置流程的硬性清单

把要求压成一张可审计的清单:令牌高熵随机、短时效、单次有效、绑定账号、服务端可吊销;入口与出口都不泄露账号存在性;短信与邮件验证码接口限速(验证码位数不足时配合失败锁定);秘密问题机制直接下线,若业务必须保留,答案按口令标准慢哈希存储且只允许线下重置;高危角色重置必须叠加第二因素;全流程动作进审计日志。这份清单可以直接当作安全评审的用例表,逐条打勾。

检测与应急

重置链路的检测信号:同源对重置接口的高频请求(令牌爆破)、大量"令牌无效"失败(夹逼尝试)、重置成功后短时间内异地登录、用户从未请求重置却消耗了令牌。后两条组合出现时几乎可以断定接管发生,应急动作是立即冻结账号、吊销会话、回溯改密前后的全部操作,并保留重置请求的原始日志供溯源。预防性的运营动作同样重要:把"重置成功"通知做成默认开启、不可关闭,等于给每个用户配了一名免费的值机员。

审计自家系统时,别只看登录框。把"忘记密码"四个字下面的每一行代码翻出来过一遍清单,侧门往往就开在那里。

一分钟自测:五问重置流程

拿自家系统立刻能做的快速体检,五问五答:重置令牌是密码学随机源生成的吗(时间戳与用户名的组合不算)?链接多久过期(超过半小时就该收紧)?用过的令牌还能再用吗(并发重放最常漏)?重置成功后旧会话全部吊销了吗(不吊销等于换锁不收卡)?本人没操作时会收到通知吗(最后一道人肉哨兵)。任何一问答不上来或答案不对,就把这一节贴给对应的开发同学——整改清单现成的,就在上面。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U