乌云(WooYun.org)历史漏洞查询---http://wy.zone.ci/
乌云 Drops 文章在线浏览--------http://drop.zone.ci/
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步骤2合为一步或者验证码绑定用户身份
危害等级:中
漏洞Rank:7
确认时间:2015-11-06 14:17
感谢发现
暂无