zoukankan      html  css  js  c++  java
  • DeDecms(织梦CMS) V5.7.72任意用户密码重置漏洞复现

    前言

    好几天没审计了,就来复现一下这个cms,难度也不是太高。

    漏洞攻击流程

    1:首先利用弱类型进入密码重置

    http://127.0.0.1/dedecms/member/resetpassword.php?dopost=safequestion&safequestion=0.0&safeanswer=&id=1
    

    admin默认mid是1

    2:通过抓包获取到 key 值

    3:去掉多余的字符访问修改密码链接

    dedecms/member/resetpassword.php?dopost=getpasswd&id=1&key=xxxxx
    

    这样我们就跳转得到了密码重置页面

    代码分析

    环境DeDecms(织梦CMS) V5.7.72+php7.2+apache
    漏洞文件入口:

    member/resetpassword.php 文件

    这里是一个重新设置登陆密码功能,我们使用的是使用安全问题找回密码:

    $dopost == "safequestion"

    通过传入的 $mid 对应的 id 值来查询对应用户的安全问题
    这里的大问题就是使用==判断安全问题和安全问题答案,这就给了我们利用弱类型绕过的可能,我们就可以绕过验证进行下一步的密码重置
    怎么绕过呢?

    假设用户没有设置安全问题和答案,那么默认情况下安全问题的值为 0 ,答案的值为 null (这里是数据库中的值,即 $row['safequestion']="0" 、 $row['safeanswer']=null )。当没有设置 safequestion 和 safeanswer 的值时,它们的值均为空字符串。第11行的if表达式也就变成了 if('0' == '' && null == '') ,即 if(false && true) ,所以我们只要让表达式 $row['safequestion'] == $safequestion 为 true 即可。下图是 null == '' 的判断结果:

    我们可以利用 php弱类型 的特点,来绕过这里 $row['safequestion'] == $safequestion 的判断,通过测试找到了三个的payload,分别是 0.0 、 0. 、 0e1 ,这三种类型payload均能使得 $row['safequestion'] == $safequestion 为 true ,即成功进入 sn 函数。

    默认状态下,临时密码的表为空,如下

    mysql> select * from dede_pwd_tmp;
    Empty set (0.00 sec
    

    当我们访问完payload时,
    链接会自动跳转到http://localhost/dedecms/member/resetpassword.php?dopost=getpasswd&id=1&key=xxxx

    key的值就是admin的临时密码,这时再查询数据库的临时密码表,你会发现多了一条admin的记录
    这也是为什么
    执行 SELECT * FROM #@__pwd_tmp WHERE mid = '$mid' 语句时,返回结果为空
    我们看到继续执行了newmail函数执行插入操作:

    function newmail($mid, $userid, $mailto, $type, $send)
    {
        global $db,$cfg_adminemail,$cfg_webname,$cfg_basehost,$cfg_memberurl;
        $mailtime = time();
        $randval = random(8);
        $mailtitle = $cfg_webname.":密码修改";
        $mailto = $mailto;
        $headers = "From: ".$cfg_adminemail."
    Reply-To: $cfg_adminemail";
        $mailbody = "亲爱的".$userid.":
    您好!感谢您使用".$cfg_webname."网。
    ".$cfg_webname."应您的要求,重新设置密码:(注:如果您没有提出申请,请检查您的信息是否泄漏。)
    本次临时登陆密码为:".$randval." 请于三天内登陆下面网址确认修改。
    ".$cfg_basehost.$cfg_memberurl."/resetpassword.php?dopost=getpasswd&id=".$mid;
        if($type == 'INSERT')
        {
            $key = md5($randval);
            $sql = "INSERT INTO `#@__pwd_tmp` (`mid` ,`membername` ,`pwd` ,`mailtime`)VALUES ('$mid', '$userid',  '$key', '$mailtime');";
            if($db->ExecuteNoneQuery($sql))
            {
                if($send == 'Y')
                {
                    sendmail($mailto,$mailtitle,$mailbody,$headers);
                    return ShowMsg('EMAIL修改验证码已经发送到原来的邮箱请查收', 'login.php','','5000');
                } else if ($send == 'N')
                {
                    return ShowMsg('稍后跳转到修改页', $cfg_basehost.$cfg_memberurl."/resetpassword.php?dopost=getpasswd&id=".$mid."&key=".$randval);
                }
    

    该代码主要功能是发送邮件至相关邮箱,并且插入一条记录至 dede_pwd_tmp 表中。而恰好漏洞的触发点就在这里,我们看看 第13行 至 第18行 的代码,如果 ($send == 'N') 这个条件为真,通过 ShowMsg 打印出修改密码功能的链接。 第17行 修改密码链接中的 $mid 参数对应的值是用户id,而 $randval 是在第一次 insert 操作的时候将其 md5 加密之后插入到 dede_pwd_tmp 表中,并且在这里已经直接回显给用户。那么这里拼接的url其实是

    http://127.0.0.1/member/resetpassword.php?dopost=getpasswd&id=$mid&key=$randval
    也就是说这里的id,key我们可控

    继续跟进一下 dopost=getpasswd 的操作,相关代码位置在 member/resetpassword.php 中,

    我们先从96行看,dopost=getpasswd时
    会先判断id是否为空
    如果不为空,进入
    $row = $db->GetOne("SELECT * FROM #@__pwd_tmp WHERE mid = '$mid'");

    这里如果$row为空,就会退出,但是我们第一步payload使得mid已经在临时密码表中存在了,所以一定不为空,继续执行:
    判断时间是否超时,如果没有,进入

    templets/resetpassword2.htm

    我们去看看

    这里密码修改页面会将 $setp 赋值为2

    由于现在的数据包中 $setp=2 ,因此这部分功能代码实现又回到了 member/resetpassword.php 文件中。

    从临时密码表中取出来key和我们前端url中的key对比,相等执行密码修改。
    到此,这就是整个漏洞利用过程。

    攻击过程

    这里我们使用test账户重置admin密码
    开始也提过了
    1:首先利用弱类型进入密码重置

    http://127.0.0.1/dedecms/member/resetpassword.php?dopost=safequestion&safequestion=0.0&safeanswer=&id=1
    

    admin默认mid是1

    2:通过抓包获取到 key 值:key=KUvaNLpw
    此时临时密码表中有了我们的key:

    3:去掉多余的字符访问修改密码链接

    dedecms/member/resetpassword.php?dopost=getpasswd&id=1&key=KUvaNLpw
    

    这样我们就跳转得到了密码重置页面

    PS

    这个漏洞利用还有一个条件:

    网站开启了会员注册功能,如果不知道如何开启的话,可以按照下图进行开启测试

    这里我一开始不知道。。导致耽误了一会时间。‘
    还有就是一开始不知道默认后台是dede。。使用了爆破的方法。。

    从网上直接找的dedecms检测插件也能检测出来漏洞:

    这里看到有getsghell漏洞,确实存在不过不是这个
    是后台存在多处fwrite函数导致getshellgetshell

    这里这个不是我们的重点简单提一句。。

    参考

    https://github.com/hongriSec/PHP-Audit-Labs/blob/master/Part1/Day4/files/README.md

  • 相关阅读:
    JPA注解 @DiscriminatorValue 使用
    随笔
    Win10 启用 FTP
    Java后端模拟前端请求
    ueditor上传路径改成绝对路径
    CSS Web Fonts 网络字体
    调试:'Object reference note set to an instance of an object.'
    类转json、 json转xml的方法,转SortedDictionary转 xml 的方法。
    xml的问题 XmlDocument 与json转换
    websocket
  • 原文地址:https://www.cnblogs.com/wangtanzhi/p/12813642.html
Copyright © 2011-2022 走看看