import secrets
raw = secrets.token_urlsafe(32)
reset_url = f'https://example.com/reset?t={raw}'

重置链接里的 token 是六位数字,来自 mt_rand(100000, 999999)。安全同事写了个脚本按时间种子枚举,两小时里撞中三个有效 token,这三次请求的间隔不到四十秒。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:mt_rand 是可预测的伪随机,种子只和时间与进程状态有关,拿到一个输出就能倒推后面的序列。位数也太短,六位数字的空间只有一百万,批量请求很快就扫完。接口还没做频率限制。

这次卡住的地方就在「重置 token 随机数」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。同一份配置存在多处的,先确认改的是被加载的那一份。

处理上按这个顺序:换成 secrets.token_urlsafe 或 random.SystemRandom 这类密码学随机器;token 长度至少 32 字节 用一次就作废;重置请求按账号和 IP 两个维度限流 超过阈值直接拒;token 表里只存哈希 不存原文。

确认没问题再收工,新生成的链接 token 是 43 位混合字符 同一链接第二次打开提示已失效。

作者 9823189