DedeCMS V5.7 SP2 前台任意用户密码重置漏洞分析
Jan 11, 2018
1 minute read

0x01 概述

DEDECMS在2018-01-09更新了V5.7 SP2正式版,然后在seebug有人提交存在前台任意用户密码修改漏洞。下面简单分析一下。

0x02 影响版本

2018-01-09及之前的版本

0x03 漏洞分析

问题出现在member/resetpassword.php75行:

else if($dopost == "safequestion")
{
    $mid = preg_replace("#[^0-9]#", "", $id);
    $sql = "SELECT safequestion,safeanswer,userid,email FROM #@__member WHERE mid = '$mid'";
    $row = $db->GetOne($sql);
    if(empty($safequestion)) $safequestion = '';

    if(empty($safeanswer)) $safeanswer = '';

    if($row['safequestion'] == $safequestion && $row['safeanswer'] == $safeanswer)
    {
        sn($mid, $row['userid'], $row['email'], 'N');
        exit();
    }
    else
    {
        ShowMsg("对不起,您的安全问题或答案回答错误","-1");
        exit();
    }
}

重置密码的时候需要进入sn函数,在这之前进行if判断if($row['safequestion'] == $safequestion && $row['safeanswer'] == $safeanswer) 当用户没有设置安全问题和答案时$row['safeanswer']0,后面一个条件成立,所以只要前面$row['safequestion'] == $safequestion成立就可以进入sn函数

此时默认的$row['safequestion']即为0,我们可以控制的变量是$safequestion,在此之前还需经过if(empty($safequestion)) $safequestion = '';判断,如果这个if成立即当$safequestion = ''时就不能通过前半个if判断了,所以我们要让$safequestion不为空而且让'0' == $safequestion成立

下面来看php中弱类型转换问题

php

可以看到当我们传进0.0时,empty($safequestion)就不成立了,而$row['safequestion'] == $safequestion'0' == '0.0'成立,所以可以进入sn方法。除了'0.0''0.' '0e123'等都可以绕过这个判断,因为0en被认为是0的n次方

跟进sn方法

sn

从数据库取出一个临时密码SELECT * FROM #@__pwd_tmp WHERE mid = '$mid',这里的mid我们可以控制,如果用户存在,发送含有临时密码的邮件,并且有个10分钟的限制(这里为了调试方便我把时间缩短了)

跟进newmail函数

newmail

可以看到$randval是一个8位随机字符串,而且先进行了md5再插入到数据库,理论上我们不好破解,但是注意85行和98行的return ShowMsg('稍后跳转到修改页', $cfg_basehost . $cfg_memberurl . "/resetpassword.php?dopost=getpasswd&id=" . $mid . "&key=" . $randval);,把含有$randval的链接直接返回显示在页面上,所以这里就没有必要去猜这个临时密码。有了这个临时密码就可以重置任意用户的密码。

0x04 漏洞利用

我们先注册一个用户,然后构造一个请求,GET /dedecms/uploads/member/resetpassword.php?i=0.0&dopost=safequestion&safequestion=0e123&safeanswer=&id=1,发送后可以看到页面跳转,然后返回含有key的链接,

key 利用这个key可以进入重置密码流程,简单看一下

重置密码/member/resetpassword.php?dopost=getpasswd&id=5

resetpwd1 先从dede_pwd_tmp表取出mid为5的临时密码

resetpwd2 与传入的临时密码MD5比较,通过验证就更新用户表dede_member为新的密码,同时删除临时密码

resetpwd3 newpwd

这样我们就可以重置任意用户的密码了——除了管理员,因为管理员信息存在另一个表dede_admin中,而且管理员默认不允许从前台登录,所以就算更改了dede_memberadmin的密码也没法登录。

0x05 总结

总的来说这个漏洞不算复杂,关键点就是php弱类型安全问题,这个已经有很多案例了,同时页面跳转的过程中泄露了临时的key,实际中一个尽量避免这种关键的参数泄露。

参考:https://www.seebug.org/vuldb/ssvid-97074


Back to posts


comments powered by Disqus