常见的任意用户密码重置漏洞解析

任意用户密码重置的10种常见姿势
https://www.ichunqiu.com/course/59045

讲师: carry_your (上海富友集团 信息安全部门)

目录

顺带一提
密码重置处还很有可能可以产生 盲注

1 验证码(不更新/不失效)
2 验证码直接返回
3 验证码未绑定用户
4 修改接收的手机或邮箱
5 本地验证绕过
6 跳过验证步骤
7 未校验用户字段的值
8 修改密码处id可替换
9 Cookie值的替换
10 修改信息时替换字段

1 验证码(不更新/不失效)

(危害还是比较大,可以重置任意用户密码)
业务逻辑是先检查短信验证码是否正确,之后再修改密码。
实际过程中 短信校验码和修改后的密码 最好同时作为参数传入到服务端处理。
不要分先后次序。

短信获取的校验码
如果有判断接口(条件一),且判断接口不受限,可以多次判断(条件二)
则可以暴力枚举短信中校验码的值。
(直接用 Burp Intruder,区分一下返回包长度)

2 验证码直接返回

(根本原因在于开发人员过于信任前端)

点击获取短信验证码后,Response包/(或者cookie中)里直接有短信验证码结果

测试方法:直接输入目标手机号,点击获取验证码,观察返回包信息/观察Cookie变化。

3 验证码未绑定用户

(开发需要把整个密码重置的过程作为一个事物transaction来处理)

测试方法一:
A用户申请验证码 (A用户是攻击者的目标)
B用户申请验证码 (B用户手机号为攻击者控制的手机号)
获取到B用户的验证码
用B用户获取到的验证码尝试去重置A用户的密码

有时Username会存在某种特殊的映射/加密,注意灵活变通

测试方法二
B用户申请验证码 (B用户手机号为攻击者控制的手机号)
获取到B用户的验证码
在B用户进行重置操作时篡改Username/UID

4 修改接收验证码的手机/邮箱(常见)

(可能原因 信任了来自客户端传输的数据)
客户端的传来的数据是不可信的,都要进行处理
原因: 用户名/手机号or邮箱/验证码 三者没有进行统一的验证

测试方法: 输入用户名获取验证码,观察这个请求,看能否修改email/phone字段,把接收地址修改成自己控制的地址。

5 本地验证绕过

造成原因: 前端不可信

测试方法: 重置目标用户,输入错误验证码,修改返回包,把错误改为正确,即可绕过验证步骤,最终重置用户密码。

6 跳过验证步骤

1
2
3
/veifyAccess.html?username=&email=
/verifyAccess.html?username=&email=
login/verifyAccess.html?username=&email=

一般而言 有4个页面

页面1 输入手机号,获取验证码
页面2 输入验证码
页面3 输入新密码
页面4 重置成功

请求尽可能保持一致,包括Refer等字段

测试方法:首先使用可控的帐号走一次完整的流程,获取每个步骤的页面链接,尤其记录页面3输入新密码的页面的URL。重置其他用户时,获取验证码后,直接进入页面3输入新密码的URL。

7 未校验用户字段的值

测试方法:使用可控的手机号走正常流程,在最后一步设置密码流程时,修改数据包中的Username。

8 修改密码处id可替换

类似方法7
批量用户密码重置 (id自增即可)

测试方法:修改可控账户的密码,抓取数据包,替换数据包中用户对应的id值,即可修改他人密码。

9 Cookie值的替换(思路不错)

(白盒吧 黑盒测这种太蠢了)

Username的映射是 JSESSIONID/PHPSESSIONID
或者 可能的判断逻辑
Cookie 是否存在,只要cookie存在即可。

测试方法:
重置wangshuai,只走第一步,记录JSESSIONID
用可控账户wangnima,走全程,最后一部替换JSESSIONID.

10 修改信息时替换字段值 (常见)

(白盒比较稳+1)
(隐藏字段)
同时替换key=value对

测试方法:修改个人资料的时候,抓取数据包,然后在数据包中(替换一对key:value对)/(新增一堆key:value对),有可能可以替换到隐藏字段。

可能的效果是,把另一个用户的密码重置成和当前用户的密码一致。

其他课程

企业渗透测试全面解析
https://www.ichunqiu.com/course/56769

PHP代码审计实战
https://www.ichunqiu.com/course/54473