*本文原创作者:yangyangwithgnu,本文属FreeBuf原创奖励计划,未经许可禁止转载
在逻辑漏洞中,任意用户密码重置最为常见,可能出现在新用户注册页面,也可能是用户登录后重置密码的页面,或者用户忘记密码时的密码找回页面,其中,密码找回功能是重灾区。我把日常渗透过程中遇到的案例作了漏洞成因分析,这次,关注因重置凭证可预测导致的任意用户密码重置问题。
想了解前六篇任意用户密码重置内容,可查看以下传送门:
通过邮箱找回密码时,邮件中将出现一个含有 token 的重置 URL,该 token 即为重置凭证。从经验来看,开发人员习惯以时间戳、递增序号、关键字段(如邮箱地址)等三类信息之一作为因子,采用某种加密算法或编码生成 token,攻击者可以基于能收集到的关键字段,用常见加密算法计算一遍,以判断是否可以预测出 token。
案例一:基于时间戳生成的 token
http://lab1.xseclab.com/password1_dc178aa12e73cfc184676a4100e07dac/ 是一道在线 CTF 题目:
“忘记密码”功能是攻击点,尝试重置 admin 的密码:
对应请求与应答为:
除了提示已发送重置邮件外,并无其他信息。尝试重置其他账号 yangyangwithgnu:
获得重置 URL 信息 http://lab1.xseclab.com/password1_dc178aa12e73cfc184676a4100e07dac/reset.php?sukey=8135f8b07653b2cbc3ec05c781a29591&username=yangyangwithgnu,访问后提示重置成功。那么,现在的情况是,admin 的重置 URL 无显示,其他账号的 URL 有显示,只要拿到 admin 的重置 URL,很可能就能看到 flag。
上面重置 URL 中 sukey 参数引起我的注意,显然它就是重置凭证。将其值 8135f8b07653b2cbc3ec05c781a29591 先用 base64 解码无果,后将其进行 MD5 解密得到明文 1530342360:
貌似 unix 时间戳,验证之:
果然,重置凭证是对当前 unix 时间戳进行 MD5 加密所得。
那么,可以设计这样一种攻击模型,达到重置任意账号密码的目的:第一次找回 yangyangwithgnu 的密码,获得重置 URL,其中 sukey 参数含有时间戳信息;第二次找回 admin 的密码,暂时虽无法获得重置 URL,没关系,服务端是已经生成好了;第三次又找回 yangyangwithgnu 的密码,获得重置 URL,其中 sukey 参数含有时间戳信息。以第一、三次获得的时间戳作为时间区间,由于整个过程都在短时间内完成,所以,可以轻松暴破出第二次的时间戳。
具体而言,先发起找回 yangyangwithgnu 密码的请求:
得到时间戳 1530347130;接着发起找回 admin 密码的请求:
然后再次发起找回 yangyangwithgnu 密码的请求:
得到时间戳 1530347161。现在可知 admin 的时间戳在 [1530347130, 1530347161] 中,基于之前获得的重置 URL 格式,我们可以构造出 admin 的密码重置 URL 类似 http://lab1.xseclab.com/password1_dc178aa12e73cfc184676a4100e07dac/reset.php?sukey={md5(unix_timestamp)}&username=admin。接下来,我将该 URL 放入 intruder 中进行暴破,将 unix_timestamp 定义为枚举变量:
以 [1530347130, 1530347161] 为字典,并设置 MD5 加密算法作为载荷预处理:
很快暴破出 admin 的重置 URL,并成功拿到 flag:
案例二:基于递增序号生成的 token
金蝶云之家密码找回,带凭证的密码找回链接如下:
从参数名猜测,u 可能为 username、t 为 token,为减少复杂性,测试发现,删掉 u 参数及值也可正常重置密码,所以,可忽略 u 参数,重点关注 t 参数。
连续 5 次获取重置链接,从邮件中提取 5 个 t 参数值如下:
仔细观察发现变化点如下:
可以看出,t 参数值的 5~8位、最后 4 位,按 2 的增量呈现递增变化。
分析清楚凭证的变化规律,要重置任意账号就轻松了。比如,要重置普通账号 admin 的密码,可以先触发找回攻击者账号的密码,获取 t 为 52df773f24ac5b651d288d42,然后触发找回 admin 的密码,t 未知,再次触发找回攻击者账号的密码,获取 t 为 52df774d24ac5b651d288d54,根据前面分析得知的变化规律,普通账号的 t 的 5~8 位一定是 [7740, 774c] 间的偶数,后 4 位范围一定在 [8d44, 8d52] 间的偶数。几次枚举便可得有效 t 参数值:
案例三:基于关键字段生成的 token
某网站密码找回功能,请求含有三个参数:
username 是邮箱、rvcode 图片验证码、sid 未知,登录邮箱查看重置 URL:
key 参数为重置凭证,尝试分析生成方式。直接将其放入 md5 在线破解网站无果,尝试用 username、rvcode、sid 等三个参数的排列组合进行 md5,当尝试到 md5(username + sid) 时发现生成结果与邮件中的凭证一致:
猜测出其 key 的生成算法,那么,后续将豪无压力重置任意账号的密码了。
类似的还有,带凭证的重置链接为 http://mysite.com/sms.php?k=a18f057d5aF,多次获取重置链接发现,凭证 f198a79b9cF 末尾的 F 恒定不变,前面 10 位字符疑似 md5 加密,尝试对不同参数的排列组合进行 md5 加密,当尝试到 md5(手机号+图片验证码) 时发现生成结果与邮件中的凭证一致:
加固措施
密码重置链接中 token 尽可能随机化,若用常规加密算法,一定用客户端无法查看且猜测的因子作为盐值。另外,服务端应限制枚举等恶意请求。
*本文原创作者:yangyangwithgnu,本文属FreeBuf原创奖励计划,未经许可禁止转载