PHPCMS v9.5.8-设计缺陷可重置前台任意用户密码

Posted 羊小弟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHPCMS v9.5.8-设计缺陷可重置前台任意用户密码相关的知识,希望对你有一定的参考价值。

验证。参考漏洞:http://wooyun.jozxing.cc/static/bugs/wooyun-2015-0152291.html

漏洞出现在/phpcms/modules/member/index.php   第1687-1756行 

public_forget_password_username()函数

	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\');
		}
	}

 经历了第一步:

$step = intval($_POST[\'step\']);
$step = max($step,1);
$this->_session_start();

这时候开启_session_start(),然后从phpcms_session取session的值,

 

然后在第二步时,验证下账户有没有绑定邮箱。然后就返回这个页面。点击获取邮箱校验码。

 


 

 

这时候的url是这样的。 

/index.php?m=member&c=index&a=public_get_email_verify&session_code=ftrz&random=0.08188270693514244

 执行public_get_email_verify()函数。

    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\';
    }
}

  然后随机生成$_SESSION[\'emc\']的值,利用sendmail发送邮件,发完以后走第三步,验证校验码。

这时候的session中存在$_SESSION[\'emc\']的值,也就是发送到邮件中的值。对于session,只要浏览器不关,session值就会一直存在本地,除非过期了。

然后我们退回到第一步,输入要重置的另一个账号,这时候的$_SESSION[\'emc\']值是第一个账户的。

然后不走点击获取验证码,直接来到

elseif(isset($_POST[\'dosubmit\']) && $step==3) {

  输入第一个账户的$_SESSION[\'emc\']值,然后进行第三步校验,

if($_SESSION[\'emc\']!=\'\' && $_POST[\'email_verify\']==$_SESSION[\'emc\']) 

  这时候的浏览器中的$_SESSION[\'emc\']值我们是知道的,所以也能进入这个if,然后重置第二个账户的密码。

这个漏洞在phpcmsv9.6.0 中修复了,修复方案就是在第一步查询$username是否有绑定邮箱的时候加入两句话,清空$_SESSION[\'emc\']的值,确保在重置当前账户的时候,session中的userid,email是用户所指定的。

 

 

 

以上是关于PHPCMS v9.5.8-设计缺陷可重置前台任意用户密码的主要内容,如果未能解决你的问题,请参考以下文章

phpcms v9前台getshell

PHPCMS9.6.0最新版SQL注入和前台GETSHELL漏洞分析 (实验新课)

phpcms前台分页链接怎么自定义参数?前台html里的$pages是从哪里传过来的?

任意用户密码重置:重置凭证可暴破

phpcms V9 前台自定义表单中提交多图字段

PHPCMS v9.5.6 通杀getshell(前台)