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

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

缺陷编号:wooyun-2015-0152291

漏洞标题:PHPCMS设计缺陷可重置前台任意用户密码

相关厂商:phpcms

漏洞作者: loopx9

提交时间:2015-11-06 12:39

修复时间:2015-12-17 14:48

公开时间:2015-12-17 14:48

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

危害等级:中

自评Rank:10

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-11-06: 细节已通知厂商并且等待厂商处理中
2015-11-06: 厂商已经确认,细节仅向厂商公开
2015-11-09: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航
2015-12-31: 细节向核心白帽子及相关领域专家公开
2016-01-10: 细节向普通白帽子公开
2016-01-20: 细节向实习白帽子公开
2015-12-17: 细节向公众公开

简要描述:

验证逻辑设计缺陷.

详细说明:

\phpcms\modules\member\index.php:

//通过用户名找回密码
public function public_forget_password_username() {
$step = intval($_POST['step']);
$step = max($step,1);
$this->_session_start();

if(isset($_POST['dosubmit']) && $step==2) {
//处理提交申请,以手机号为准
if ($_SESSION['code'] != strtolower($_POST['code'])) {
showmessage(L('code_error'), HTTP_REFERER);
}
$username = safe_replace($_POST['username']);
$r = $this->db->get_one(array('username'=>$username),'userid,email');
if($r['email']=='') {
$_SESSION['userid'] = '';
$_SESSION['code'] = '';
showmessage("该账号没有绑定手机号码,请选择其他方式找回!");
} else {
$_SESSION['userid'] = $r['userid'];
$_SESSION['email'] = $r['email'];
}
$email_arr = explode('@',$r['email']);
include template('member', 'forget_password_username');
} elseif(isset($_POST['dosubmit']) && $step==3) {
$sms_report_db = pc_base::load_model('sms_report_model');
$mobile_verify = $_POST['mobile_verify'];
$email = $_SESSION['email'];
if($email){
if(!preg_match('/^([a-z0-9_]+)@([a-z0-9_]+).([a-z]{2,6})$/',$email)) exit('check email error');
if($_SESSION['emc_times']=='' || $_SESSION['emc_times']<=0){
showmessage("验证次数超过5次,验证码失效,请重新获取邮箱验证码!",HTTP_REFERER,3000);
}
$_SESSION['emc_times'] = $_SESSION['emc_times']-1;
if($_SESSION['emc']!='' && $_POST['email_verify']==$_SESSION['emc']) {

$userid = $_SESSION['userid'];
$updateinfo = array();
$password = random(8,"23456789abcdefghkmnrstwxy");
$encrypt = random(6,"23456789abcdefghkmnrstwxyABCDEFGHKMNRSTWXY");
$updateinfo['encrypt'] = $encrypt;
$updateinfo['password'] = password($password, $encrypt);

$this->db->update($updateinfo, array('userid'=>$userid));
$rs = $this->db->get_one(array('userid'=>$userid),'phpssouid');
if(pc_base::load_config('system', 'phpsso')) {
//初始化phpsso
$this->_init_phpsso();
$this->client->ps_member_edit('', '', '', $password, $rs['phpssouid'], $encrypt);
}
$_SESSION['email'] = '';
$_SESSION['userid'] = '';
$_SESSION['emc'] = '';
$_SESSION['code'] = '';
pc_base::load_sys_func('mail');
sendmail($email, '密码重置通知', "您在".date('Y-m-d H:i:s')."通过密码找回功能,重置了本站密码。");
include template('member', 'forget_password_username');
exit;
} else {
showmessage("验证码错误!请重新获取!",HTTP_REFERER,3000);
}
} else {
showmessage("非法请求!");
}
} else {
include template('member', 'forget_password_username');
}
}
//邮箱获取验证码
public function public_get_email_verify() {
pc_base::load_sys_func('mail');
$this->_session_start();
$code = $_SESSION['emc'] = random(8,"23456789abcdefghkmnrstwxy");
$_SESSION['emc_times']=5;
$message = '您的验证码为:'.$code;
sendmail($_SESSION['email'], '邮箱找回密码验证', $message);
echo '1';
}


通过用户名找回密码方式存在设计缺陷。找回密码流程可分作三步来看:
步骤1: 客户端提交用户名,服务端在数据库中查询记录,如果存在此用户就在session中保存用户身份信息;
步骤2: 生成验证码并保存在session,然后将验证码发往用户注册邮箱;
步骤3: 服务端将客户端提交的验证码与session中保存的进行比对,验证通过后重置用户密码。
从代码中可以看到验证码没有绑定用户身份,这样就导致可以使用用户A的验证码来重置用户B的密码。
使用用户A(可控账户)走正常密码找回流程来获取验证码,但不使用,然后再使用用户B(要攻击的账户)走步骤1,接着跳过步骤2使用前面获取到的验证码直接走步骤3,就能重置用户B的密码了。

漏洞证明:

http://**.**.**.**/index.php?m=member&c=index&a=public_get_password_type
选择“通过用户名找回密码”
输入自己的账户获取验证码:

-1.png


0.png


1.png


回到第一步输入要重置的用户名:

3.png


使用前边获取的验证码直接重置密码:

4.png


5.png


登录成功:

6.png

修复方案:

将步骤1步骤2合为一步或者验证码绑定用户身份

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


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:7

确认时间:2015-11-06 14:17

厂商回复:

感谢发现

最新状态:

暂无