织梦CMS_V5.7任意用户密码重置漏洞复现
织梦CMS_V5.7任意用户密码重置漏洞复现
前言
前端时间看了织梦CMS_V5.7版本的任意用户密码重置漏洞的分析,当时没有时间记录下来,现利用空闲时间又复现了一次。
什么是dedecms
织梦内容管理系统(DeDeCMS) 以简单、实用、开源而闻名,是国内最知名的PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统,在经历多年的发展,目前的版本无论在功能,还是在易用性方面,都有了长足的发展和进步。广泛应用于中小型企业门户网站,个人网站,企业和学习网站建设,在中国,DedeCMS应该属于最受人们喜爱的CMS系统。
漏洞复现
- 管理员的账户名为cmx,mid=1,当然下面这个页面我们是看不到的,只能登录后台才能看到,这里
id=1
的账户恰好是管理员账户,现在我们就重置管理员密码
- 利用弱类型进入管理员的密码重置
http://127.0.0.1/dedecms/member/resetpassword.php?dopost=safequestion&safequestion=0.0&safeanswer=&id=1
- 页面跳转,通过抓包获得key值
http://127.0.0.1/dedecms/member/resetpassword.php?dopost=getpasswd&id=1&key=D6EG3amI
- 去掉多余的字符访问修改密码链接
http://127.0.0.1/dedecms/member/resetpassword.php?dopost=getpasswd&id=1&key=D6EG3amI
- 跳转到管理员 cmx 密码重置页面
- 修改后,登录到管理员账户
漏洞分析
漏洞文件入口:member/resetpassword.php:75
在找回密码时,使用安全问题:$dopost == "safequestion"
,通过传入的 $mid
对应的 id
值来查询对应用户的安全问题。这里的大问题就是使用==
判断安全问题和安全问题答案,这就给了我们利用弱类型绕过的可能,我们就可以绕过验证进行下一步的密码重置。
当用户没有设置安全问题和答案,那么默认情况下安全问题的值为 0 ,答案的值为 null ,此时:$row['safequestion']="0"、 $row['safeanswer']=null
,当没有设置 safequestion
和 safeanswer
的值时,它们的值均为空字符串。if表达式也就变成了 if('0' == '' && null == '')
,即 if(false && true)
,所以我们只要让表达式 $row['safequestion'] == $safequestion
为 true 即可。
通过测试,”0.0”、”0.”、”0e1”可以使$row['safequestion'] == $safequestion
为 true,成功进入sn()
函数
这里当第一次进行忘记密码操作时,$row
应该时空,开始执行newmail()
函数,发送邮件insert
一条记录到dede_pwd_tmp
表里;如果之前进行过忘记密码操作,但是时间已经超过10分钟,那么继续进行发送新验证码的操作update dede_pwd_tmp
表里面的数据,跟进当前文件的newmail()
函数。
这里第一次进行insert
操作(update
操作也是一样的)时,将8位的随机字符串$randval
加密后添加到dede_pwd_tmp
表中,然后当$send = N
时,将随机字符串$randval
拼接到url
中返回,返回的url
为:
http://127.0.0.1/member/resetpassword.php?dopost=getpasswd&id=$mid&key=$randval
也就是说这里的id
和key
我们可控,跟进dopost=getpasswd
的操作,在member/resetpassword.php:96
首先判断 id 是否为空,如果不为空,进入$row = $db->GetOne("SELECT * FROM #@__pwd_tmp WHERE mid = '$mid'");
,这里如果$row
为空,就会退出,但是前面的insert
操作使得mid
在临时密码表中存在了,继续判断时间是否超时,如果没有,进入templets/resetpassword2.htm
这里密码修改页面会将 $setp
赋值为2,继续回到member/resetpassword.php
从临时密码表中取出来 key 和我们前端 url 中的 key 对比,相等执行密码修改。
以上就是分析的整个过程,但是这个漏洞存在一个缺陷,因为通过分析可以看出来只有没有设置安全问题的用户才会受此漏洞的影响;而且只能修改前台用户的密码。