1. 程式人生 > >PHPCMS v9.5.8-設計缺陷可重置前臺任意用戶密碼

PHPCMS v9.5.8-設計缺陷可重置前臺任意用戶密碼

mod log val his 手機 index cli exit images

驗證。參考漏洞: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([email protected]
/* */,$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-設計缺陷可重置前臺任意用戶密碼