用户密码重置找回10种常见姿势

本篇文章是参考大神carry_your讲师(360补天排名第一)的任意用户密码重置的10种常见姿势总结的笔记。
原视频地址:https://www.ichunqiu.com/course/59045

介绍

本次课程主要针对挖掘逻辑漏洞中的任意用户密码重置方法和原理从10种常见情况进行了讲述,并结合漏洞挖掘中的真实案例场景与数据包演示了重置密码漏洞的检测方法,让大家对这一类逻辑漏洞有从浅入深,逐步深奥的见解。

验证码不失效

造成原因

找回密码的时候获取的验证码缺少时间限制仅值判断了验证码是够正确未判断验证码是否过期

测试方法

通过枚举找到真正的验证码输入验证码完成验证

案例

输入目标手机号,获取验证码随意输入验证码1234点击下一步,拦截数据包:

数据包

POST /Account/CheckYQCode HTTP/1.1
Host: www.xxxx.cn
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: */*Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer:
http://www.xxxx.cn/userCenter/toForgetPsdPage.html?mobile=
Content-Length: 11
Cookie: ASP.NET_SessionId=30jfruwn22h2xng3ahhzo2jxConnection: close

YQCode=1234

这种验证码不失效而且验证码是4位数的情况下,直接爆破 看包的返回长度或者内容来找到正确的验证码。

得到正确的验证码是1059然后到网站上输入验证码跳转到输入新密码的页面完成重置密码

总结

这种验证码不失效的情况现在已经是非常少见的了,而且验证码的位数也很少有简单的4位验证码了。现在绝大多数是这样的:6位数的验证码而且15分钟内有效,这样子的话爆破的可能性就非常的低了。

验证码直接返回

造成原因

输入手机号后点击获取验证码,验证码在客户端生成,并直接返回在Response方便对接下来的验证码进行比对。

测试方法

直接输入目标手机号,点击获取验证码,并观察返回包即可。在返回包中得到目标手机号获取的验证码,进而完成验证,重置密码成功。

案例

总结

这种情况上次狗哥也拿出来了这样一个类似的案例,记得他那个情况是在找回密码返回包中,直接返回了旧密码的md5值,然后修改返回包可以直接重置管理员的密码。

验证码未绑定用户

造成原因

输入手机号和验证码进行重置密码的时候,仅对验证码是够正确进行了判断,未对该验证码是否与手机号匹配做验证。

测试方法

在提交手机号和验证码的时候,替换手机号为他人手机号进行测试,成功通过验证并重置他人密码。

案例一

首先使用自己的手机号接收验证码,

然后输入自己的手机号接收到的验证码,点击下一步并拦截数据包。

最后替换数据包里的目标手机号,然后发包
数据包

POST /tofindPasswordByPhone3.do HTTP/1.1
Host: www.xxxx.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.xxxx.com/tofindPasswordByPhone2.do?mobile=131234xxxxx&captcha=qkan&checkbox=on
Cookie: JSESSIONID=D4DB3147DBF941799B9CA74E4364F2F9; CNZZDATA1257851838=1754906772-1467355802-%7C1467355802; Hm_lvt_203f11422b4fcc8e2be8c54b036c5ff9=1467357432; Hm_lpvt_203f11422b4fcc8e2be8c54b036c5ff9=1467357978; smsRand="d9[x]1gSjADrs[d]"; td_cookie=699947232;
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 33

mobile=13888888888&smsCode=561768

mobile的值改为我们想要重置的用户手机号点击下一步,跳转到设置密码的页面输入新密码,提交就成功重置了13888888888的密码。

案例二

这个案例是验证码未绑定用户延伸一下,有时候测试会遇到这种,我们发现用户名被加密了,有无法得到具体的加密算法,怎么办?

其实大部分这种情况我们都不需要知道加密算法,比如这里例子,得到liuyy的加密后的值是80e688602c4b11e66320c421e3b71ef2,那么我们就可以直接利用这个keyCode参数了。

步骤是一样的,输入我们的用户名和收到的验证码,然后把我们的keycode替换为liuyy的那个keycode,这样就可以重置liuyy的密码了。(漏洞原因还是是判断了验证码是否正确,而没有判断该验证码是否跟该用户匹配。)

总结

这种情况没有遇到过,学习了,以后在找回密码的时候会这么测试的。现在看来对于白帽子来说有2个手机号是多么的方便了。
案例二中如何获取到其他用户的keyCode呢?这里的话正常走一遍找回密码的流程,然后抓包就会在数据包中找到加密后的keyCode了,这样就可以重置任意用户的密码了。

修改接受验证码的手机或邮箱

造成原因

用户名、手机号、验证码三者没有统一进行验证,仅判断了三者中的手机号和验证是否匹配和正确,如果正确则判断成功并进入下一流程。

测试方法

输入用户名获取验证码,修改接收验证码的手机号为自己的号码,自己手机成功接收验证码,提交到网站进行验证,验证成功并进入下一流程。

案例


点击找回密码,首先我们输入zhangwei,然后点击获取验证码,这个时候把手机号改为我们自己的号码,(一般情况下这里是在数据包中进行修改的),然后输入我们自己的号码和验证码,成功跳到重置密码的页面,密码重置成功。

总结

carry_your大神说这种情况下还是比较常见的,这里不是很能理解,为什么程序员开发的时候不做用户名和手机号的匹配呢?我平时测试的时候,很少遇到这种不做用户名和手机号匹配的情况 ⊙﹏⊙|||

本地验证绕过

造成原因

客户端在本地进行验证码是否正确的判断,而该判断结果也可以在本地修改,最终导致欺骗客户端,误以为我们已经输入了正确的验证码。

测试方法

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

案例


输入手机号13888888888,输入验证码123456,验证码错误的时候,返回包返回的是0

这里我们所做的就是把0修改为1,可以借工具修改返回包,我们把0改为1,然后查看页面,成功跳转到修改密码的页面,输入新密码即可修改用户13888888888的密码

总结

who_jeff大神曾经分享给过这样一个类似的案例,当时他是在一个安卓app上进行抓包测试的,当时就直接修改返回包 来欺骗本地的app客户端的,成功重置任意用户的密码。

跳过验证步骤

造成原因

对修改密码的步骤,没有做校验,导致可以直接输入最终修改密码的网址,直接跳转到该页面,然后输入新密码达到重置密码的目的。

测试方法

首先使用自己的账号走一次流程获取每个步骤的页面链接,然后记录页面3对应的输入新密码的链接,重置他人用户时,获取验证码后,直接输入页面3链接到新密码的界面,输入密码重置成功。

案例


首先我们走一下所有的步骤,页面1、页面2、页面3,然后记录下页面3的链接

然后尝试重置他人的用户。(ps:页面3是在我们的邮箱里接收到的链接)
是某集团系统,所以用户wangshuai,邮箱对应wangshuai@xxx.com.cn

使用账户wangshuai,点击获取验证码,然后补齐下面的链接 https://xxx/page/login/veifyAccess.html?username=wangshuai&email=wangshuai@xxx.com.cn访问后即可直接重置该用户的密码

总结

这个漏洞不用按照正常的流程来走,这里的话直接补齐设置新密码的链接,然后利用这里链接可以直接重置任意用户的密码。

未校验用户字段的值

造成原因

在整个重置密码的流程中,只对验证码手机号做了校验,未对后面设置新密码的用户身份做判断,导致在最后一步通过修改用户身份来重置他人的密码。

测试方法

使用自己的手机号走流程,在走到最后一个设置密码的流程时,修改数据包里的用户信息。

案例


使用自己的手机号走流程,最后一步的数据包:
数据包

POST /yw_xxx/regist/saveNewPwd.action HTTP/1.1
Host: www.xxx.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.xxx.com/yw_xxx/regist/toSetPwd.action
Cookie: td_cookie=2080441838; JSESSIONID=530DD2516536F63131A1C098089CF2FB; JSESSIONID=5F3E182FAE378C1E799342C059F923B9Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 57

upassword=qwer1111&upassword1=qwer1111&mphone=131234xxxxx

我们可以看到密码找回成功

而且参数中只有密码用户名cookie值无效,只需要修改指定用户名的值,就可以重置他人的用户密码。

修改用户为13888888888,在发送数据包,我们就成功的把138的密码修改为qwer111

总结

这里的话关键是在最后一步重置密码的时候替换目标手机号,这种其实也是比较暴力的,拿到这个链接的话 可以无条件批量重置任意用户的密码,这里面利用burp可以批量枚举手机号码的mphone参数。

修改密码处id可替换

造成原因

修改密码的时候,没有对原密码进行判断,且根据id的值来修改用户的密码,类似的SQL语句:

update user set  password="qwer1234" where id =1

修改数据包里的id的值,即可修改他人密码。

测试方法

修改自己用户密码,抓取数据包,替换数据包中用户对应的id值,即可修改他人的密码。

案例


点击立即提交,得到右边的数据包,测试发现修改id为5,就可以把对应的用户密码修改为123456,没有对用户的原始密码判断,也没有判断id是否属于该用户。
数据包

POST /Index/user/userinfo.html HTTP/1.1
Host: 192.168.8.31:8088Content-Length: 63Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://192.168.8.31:8088
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2107.202 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://192.168.8.31:8088/Index/user/userinfo.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Cookie: PHPSESSID=28af1649bcbcb0e0dd83afa017691a03; __sticket=hKdyp310daeBfKWqgnimZoB2zrKwespkfaaVm4KKpN-Fp3tokWJ-YJeQqWOXe9mpf5-br8dox6SUlX_Rgn2t05GVpZ6Jqoaqg3zMoY-rnnM.6.a.

id=6&user_name=kefu1&password=123456&name=kefu123&email=&phone=

这里的idkefu1的所在参数user_name并没有去判断是否为用一个用户,这里修改id是可以任意修改其他用户的密码的。

这里在不修改user_name的情况下,只修改id值就成功重置了用户的密码。

总结

这种也比较暴力流氓,可以通过枚举id的值 ,来大批量重置任意用户密码的漏洞,因为不需要用户名了,只需要知道id值即可,危害比较大。

cookie值的替换

造成原因

重置密码走到最后一步的时候仅判断唯一的用户标识cookie是否存在,并没有判断该cookie有没有通过之前重置密码过程的验证,导致可替换cookie重置他人用户密码。(cookie可指定用户获取。)

测试方法

重置自己用户密码到达最后阶段,抓到数据包,并在第一阶段重新获取目标用户cookie,替换cookie到我们抓取的数据包中,发包测试。

案例


首先我们重置自己的用户wang111的密码到最后一步,成功重置密码,抓到如下数据包。
数据包

POST /ppc/valid/resetPassword.do HTTP/1.1
Host: www.xxx.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://www.xxx.com/ppc/valid/showResetPassword.do
Content-Length: 37
Cookie: JSESSIONID=E1AC27A7302C03C9432DE2254B99311A
Connection: close

password=qwer1111&rePassword=qwer1111

这里的数据包中并没有出现用用户的参数信息,所以这里面的话,可以判断这里应该是用cookie作为身份的判断的。

到第一步去获取验证码的时候,点击下一页,可以获取到该用户wangshuai对应的内容

Cookie: JSESSIONID=E1AC27A7302C03C9432DE2254B99311A

拿到这个cookie就意味着可以利用这个身份判断标识去重置这个用户的密码了。

替换得到的cookie值,即把cookie对应的用户wangshuai的密码修改为qwer1234

总结

关键点:cookie可指定用户获取,尝试用他人账号来找回密码的时候,抓取数据包,可以从中提取出cookie值,然后就可以利用这个cookie值,就可以重置指定用户的密码了。

修改信息时替换字段值

造成原因

在执行修改信息的sql语句的时候,用户的密码也当作字段执行了,而且是根据隐藏参数loginid来执行的,这样就导致修改隐藏参数loginid的值,就可以修改他人的用户密码。

测试方法

修改个人资料的时候,抓取数据包,然后来修改数据包的参数和对应的值,参数名一般可以在其他地方找到,替换隐藏参数即可修改他人的密码等信息。

案例


点击 保存信息 抓取数据包
数据包

POST /xxxxx/employee_updateEmployeeInf.action HTTP/1.1
Host: www.xxxxx.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Referer: https://www.xxxxx.com/xxxxx/employee_forUpdate.action
Cookie: JSESSIONID=A115648DB5F49215078E583ABB6A665A; FLGSID=FLGSRV1; loginUrl=""Connection: close
Content-Type: multipart/form-data;boundary=---------------------------222991508618208
Content-Length: 709
-----------------------------222991508618208
Content-Disposition: form-data; name="mobileNo"
177XXXXXXXX
-----------------------------222991508618208
Content-Disposition: form-data; name="departId"
49
-----------------------------222991508618208
Content-Disposition: form-data; name="minority"
-----------------------------222991508618208
Content-Disposition: form-data; name="sex"
1
-----------------------------222991508618208
Content-Disposition: form-data; name="birthday"
19920829
-----------------------------222991508618208
Content-Disposition: form-data; name="photo"; filename=""
Content-Type: application/octet-stream
-----------------------------222991508618208--

可以看到数据包里只有这几个参数mobileNo、departId、minority、sex、birthdaymobileNo是用户对应的手机号我们尝试修改mobileNo的值,所获得的效果就是我们的手机号修改了,而这个手机号本身就是可以修改的。这个数据包中并没有找到我们标识用户身份的参数信息,唯一可以修改的手机号也只是表单中直接修改可以改变的。接下来我们去找一下隐藏参数。。。

view-source:https://www.xxx.com/ua/employee/forUpdate.do

查看下这个页面的源代码,找到了一个参数loginId,这个参数是对应用户身份的而我们发现 上面的数据包里没有这个参数,那么我们是否可以自己添加上去呢?

这里修改数据包,添加字段loginId,并且把值修改为他人的用户,发包返回修改成功,这样就成功的把用户871xxxx的密码改为跟我们密码相同的值。

总结

最后一种要稍微复杂一点,得去找到隐藏参数:loginId 然后再修改数据包,以后挖洞的时候,多留意这些。


文章作者: 国光
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 国光 !
 上一篇
一道Py杂项题 bitwise 一道Py杂项题 bitwise
PW给的一道CTF题,由于实验吧把这一道题目归类于逆向,实际上感觉还是考察Python基础的,现在感觉以前的题目好简单呀。 题目You see the doors to the loading bay of the hangar, bu
2017-11-03
下一篇 
一个简易的APP 一个简易的APP
记录了第一个简易app开发中遇到的知识点,以及一些自己对代码的理解 APP 预览首先这一次我们要做一个类似于问卷的app: 字符串资源 strings.xml每个项目都包含一个名为strings.xml的默认字符串文件。在项目的app/r
2017-09-14
  目录