dedeCMS 5.7 任意用户密码重置漏洞

dedeCMS 5.7 任意用户密码重置漏洞

这篇文章主要对dedecms 5.7版本(SP2)的任意用户密码重置漏洞进行了复现,在第一部分进行了源码审计,在第二部分进行了利用过程的复现,最后,针对漏洞原因提供了一个解决方案。

一、源码审计

漏洞存在的位置:

http://127.0.0.1/DedeCMS-5.7.72/uploads/member/resetpassword.php

这是dedecms的密码重置页面,该页面的dopost参数决定了当前用户密码重置的流程,而这个漏洞的产生,就是在dopost的参数为safequestion时(以回答安全问题重置密码),传入的其余参数还有safequestion、safeanswer和id(用户id),下面贴上代码:

dedeCMS 5.7 任意用户密码重置漏洞
可以看到,它通过我们传入的用户id来查询该用户设置的安全问题和答案,在下面,对我们提交的答案以及问题进行比较,比较如果一致,就可以进行密码修改,但是这里使用了==,也就是弱类型比较,我们再来查看一下数据库中对于未设置安全问题的用户是怎样存储的:

dedeCMS 5.7 任意用户密码重置漏洞
safequestion为0,safeanswer为null,这样一来就可以通过弱类型来绕过检测,我们可以使用以下payload来进行测试:

resetpassword.php?dopost=safequestion&safequestion=0.0&safeanswer=&id=1
注意:这里id为要修改的用户的id

这里其实只要让提交的safequestion的值==0,safeanswer==null就可以绕过检测了。
然后我们继续跟踪sn函数,传入sn的参数是用户id、用户名、用户邮箱、自定义的值
贴上代码:

dedeCMS 5.7 任意用户密码重置漏洞
它首先查询了临时密码表,第一个判断为该用户的临时密码是否存在,第二个是临时密码是否过期,
由于我们是第一次进行修改密码,所以临时密码不存在,进入第一个分支。
执行了newmail函数,继续跟进:

dedeCMS 5.7 任意用户密码重置漏洞
该函数和sn在一个文件中。在该函数中,$randval就是随机生成的8位临时密码,由于在sn中,传给newmail的type是INSERT,所以进入第一个分支,$key为md5加密后的临时密码,然后向临时密码表中插入了该条数据,执行成功进入内部分支,由于调用时传入的$send为N,所以进入第二个分支,直接调用了ShowMsg函数,并且传入了提示信息和跳转的页面,注意,它再次跳转到了resetpassword.php的页面,我们根据传入的参数继续跟进。
贴上代码:

dedeCMS 5.7 任意用户密码重置漏洞
这里再次通过mid查询了该用户的临时密码是否存在,不存在就会返回登录页面,之后进入第一个分支,直接判断了临时密码是否过期,没过期将会包含一个页面,这个页面就是修改密码的页面了,继续跟进:

dedeCMS 5.7 任意用户密码重置漏洞
这里设置了setp的值为2,同时传入了临时密码及其他的参数,输入完密码之后,点击提交,就会来到之前setp为2的那个分支:

dedeCMS 5.7 任意用户密码重置漏洞
这里主要检测了临时密码是否一致,两次输入的新密码是否一致,如果一致,就删除临时密码,并修改用户密码。
至此,代码审计结束,进行如下总结

这个漏洞存在的主要原因是弱类型的检测,导致绕过了安全问题的验证,直接对上传的用户id进行了密码修改,其次就是在showmsg时直接将临时密码明文返回了,而且它在10分钟内有效,可能会被攻击者利用。

二、漏洞复现

几个重要路径:

后台页面:http://127.0.0.1/DedeCMS-5.7.72/uploads/dede/
登录页面:http://127.0.0.1/DedeCMS-5.7.72/uploads/member/

首先要进入后台开启会员功能:

dedeCMS 5.7 任意用户密码重置漏洞
然后创建两个用户aaa和bbb,密码和账户名相同:

dedeCMS 5.7 任意用户密码重置漏洞
创建完用户之后,我们先登录aaa账户:

dedeCMS 5.7 任意用户密码重置漏洞
这里直接从数据库中查看一下用户mid:

dedeCMS 5.7 任意用户密码重置漏洞

然后对id为3的,也就是bbb用户的密码进行修改,直接构造链接访问:

http://127.0.0.1/DedeCMS-5.7.72/member/uploads/resetpassword.php?dopost=safequestion&safequestion=0.0&safeanswer=&id=3

注意开启bp抓包,抓到我们构造的链接之后,点击放包,接下来它就会自动跳转,也就是showmsg函数执行的结果,这样就可以直接看到key值和整个修改密码的链接了:

dedeCMS 5.7 任意用户密码重置漏洞
然后我们访问这个链接,进入修改密码的页面,进行密码修改:

dedeCMS 5.7 任意用户密码重置漏洞
将密码修改为aaa并登录:

dedeCMS 5.7 任意用户密码重置漏洞
登录成功!

三、修复方案

这里直接将==改为===就可以检测完整了。

四、参考链接

https://www.cnblogs.com/wangtanzhi/p/12813642.html