基本信息
漏洞编号:SSV-97074
实验版本:dedecms v5.3
下载地址:http://www.dedecms/upimg/soft/2008/DedecmsV53-UTF8-Final.tar.gz
参考文章:https://www.seebug/vuldb/ssvid-97074
https://blog.csdn/qq_51569535/article/details/109211295
https://blog.csdn/l1028386804/article/details/48771375
前置知识
1.在php中进行不同类型数据比较是有以下特点
如果数据中有bool型,则全部转化为bool型比较,且true>false。
否则,如果有int型就转化为int比较。
否则,如果两边都是string型的纯数字,转为int比较。
否则就按string型比较。
2.举个例子
<?php
var_dump(0=='0.0'); // true
var_dump(0 == 'abc'); // true
var_dump(1 == '1abc'); // true
var_dump('1e0'=='1e2'); // false
var_dump('0.0'==0); // true
var_dump('0.0'==''); //false
//还有下面这样的
if(md5('s878926199a')==0){
echo 'true';
}
?>
因为 md5(‘s878926199a’)=0e545993274517709034328855841020就是0的n次方,所以还是等于0
<?php
if(strcmp('1a',1)){//此处比较为'1a'>1,strcmp与==比较方式不同('1a'==1为真)
echo 'true';
}else {
echo 'false';
}
?>
<?php
var_dump(in_array("1a", array(1,2,3))); //true
?>
以上In_array函数和array_search函数的问题可以在in_array函数后面加一个true选项,就能解决。
"0x1e240"=="123456"//true
"0x1e240"==123456//true
"0x1e240"=="1e240"//false
还存在一种十六进制余字符串进行比较运算时的问题。当其中的一个字符串是0x开头的时候,PHP会将此字符串解析成为十进制然后再进行比较,0×1240解析成为十进制就是123456,所以与int类型和string类型的123456比较都是相等。
漏洞分析
dedecms/member/resetpassword.php
//71行
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();
}
}
未设置安全问题的用户帐号的$row['safequestion']
默认是为'0'
(字符串),$row['safeanswer']
为空
。
如果$safequestion
为空
或'0'
,则empty($safequestion)
为真。
如果$safequestion
为'0.0'
,则empty($safequestion)
为假。
如果我们传入'0.0'
,则会顺利执行sn()
函数。
跟进函数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
完成之后跳转到了修改密码的页面,然后就可以修改密码了。
复现过程
1.配置dedecms
-
解压DedecmsV53-UTF8-Final并移入网站根目录。
-
打开首页,根据指引完成网站初始化。
http://localhost/DedecmsV53-UTF8-Final/upload/
-
登录后台,并开启会员模块(5.3版本默认打开)。
http://localhost/DedecmsV53-UTF8-Final/upload/dede/
2.注册会员
注册测hacker账号aaaaa,并且设置安全问题。
注册victim账号bbbbb,不设置安全问题。
3.找回密码
hacker用自己的账号通过安全问题找回密码
4.burpsuite抓包
开启代理,然后提交
用burpsuite抓包,并send to repeater
5.修改数据并发包
将id改为受害者id
userid不用管,这个参数并没有什么用
将safequestion设置成0.0
GO
查看返回数据,打开那个特别显眼链接
6.打开链接
这是怎么回事?
7.检查错误
参数中出现了奇怪的&
其实这是&的url编码,直接提交会把&
再次编码
故将&
改成&
即可
8.修改密码
漏洞复现完毕,感谢各位师傅阅读。
更多推荐
织梦cms前台任意用户密码修改
发布评论