0x01:介紹
PHPCMS V9(後面簡稱V9)採用PHP5+MYSQL做爲技術基礎進行開發。V9採用OOP(面向對象)方式進行基礎運行框架搭建。模塊化開發方式做爲功能開發形式。框架易於功能擴展,代碼維護,優秀的二次開發能力,可滿足所有網站的應用需求。 5年開發經驗的優秀團隊,在掌握了豐富的WEB開發經驗和CMS產品開發經驗的同時,勇於創新追求完美的設計理念,爲全球多達10萬網站提供助力,並被更多的政府機構、教育機構、事業單位、商業企業、個人站長所認可。
0x02:漏洞分析
在中 v9phpcmsmodulesmemberindex.php381行處
public function account_manage_avatar() { $memberinfo = $this->memberinfo; //初始化phpsso $phpsso_api_url = $this->_init_phpsso(); $ps_auth_key = pc_base::load_config('system', 'phpsso_auth_key'); $auth_data = $this->client->auth_data(array('uid'=>$this->memberinfo['phpssouid'], 'ps_auth_key'=>$ps_auth_key), '', $ps_auth_key); $upurl = base64_encode($phpsso_api_url.'/index.php?m=phpsso&c=index&a=uploadavatar&auth_data='.$auth_data); //獲取頭像數組 $avatar = $this->client->ps_getavatar($this->memberinfo['phpssouid']); include template('member', 'account_manage_avatar'); }
這裏是一個上傳頭像的功能模塊,我們繼續跟蹤上傳地址爲
v9/phpsso_server/index.php?m=phpsso&c=index&a=uploadavatar
讀取v9phpsso_serverphpcmsmodulesphpssoindex.php文件
其中uploadavatar爲我們處理上傳頭像函數
具體函數如下
public function uploadavatar() {
//根據用戶id創建文件夾 if(isset($this->data['uid']) && isset($this->data['avatardata'])) { $this->uid = $this->data['uid']; $this->avatardata = $this->data['avatardata']; } else { exit('0'); } $dir1 = ceil($this->uid / 10000); $dir2 = ceil($this->uid % 10000 / 1000); //創建圖片存儲文件夾 $avatarfile = pc_base::load_config('system', 'upload_path').'avatar/'; $dir = $avatarfile.$dir1.'/'.$dir2.'/'.$this->uid.'/'; if(!file_exists($dir)) { mkdir($dir, 0777, true); } //存儲flashpost圖片 $filename = $dir.$this->uid.'.zip'; file_put_contents($filename, $this->avatardata); echo $filename;exit(); //解壓縮文件 pc_base::load_app_class('pclzip', 'phpsso', 0); $archive = new PclZip($filename); if ($archive->extract(PCLZIP_OPT_PATH, $dir) == 0) { die("Error : ".$archive->errorInfo(true)); } //判斷文件安全,刪除壓縮包和非jpg圖片 $avatararr = array('180x180.jpg', '30x30.jpg', '45x45.jpg', '90x90.jpg'); if($handle = opendir($dir)) { while(false !== ($file = readdir($handle))) { if($file !== '.' && $file !== '..') { if(!in_array($file, $avatararr)) { @unlink($dir.$file); } else { $info = @getimagesize($dir.$file); if(!$info || $info[2] !=2) { @unlink($dir.$file); } } } } closedir($handle); } $this->db->update(array('avatar'=>1), array('uid'=>$this->uid)); exit('1'); } 其中關鍵代碼 pc_base::load_app_class('pclzip', 'phpsso', 0); $archive = new PclZip($filename); if ($archive->extract(PCLZIP_OPT_PATH, $dir) == 0) { die("Error : ".$archive->errorInfo(true)); }
這裏爲解壓縮文件
接下來爲判斷是否爲圖片類型
//判斷文件安全,刪除壓縮包和非jpg圖片 $avatararr = array('180x180.jpg', '30x30.jpg', '45x45.jpg', '90x90.jpg'); if($handle = opendir($dir)) { while(false !== ($file = readdir($handle))) { if($file !== '.' && $file !== '..') { if(!in_array($file, $avatararr)) { @unlink($dir.$file); } else { $info = @getimagesize($dir.$file); if(!$info || $info[2] !=2) { @unlink($dir.$file); } } } } closedir($handle); }
爲180×180.jpg’, ’30×30.jpg’, ’45×45.jpg’, ’90×90.jpg ,如果不爲這幾種,則就刪除,但是他考慮到的僅僅是當前目錄下的,沒做循環遍歷,導致我們可以新建一個目錄,然後裏面放入我們的PHP***,然後壓縮成zip,然後再上傳,然後即可達到任意上傳文件,直接前臺無限制getshell
0x03:漏洞利用
新建一個如圖文件
新建一個22目錄,目錄裏面放入我們的test.php文件,test.php裏面放入我們的一句話,然後壓縮成zip文件
然後上傳一個正常頭像,獲取一個路徑,如正常頭像地址爲http://127.0.0.1/v9/phpsso_server/uploadfile/avatar/1/1/3/90×90.jpg
然後我們再次上傳,通過burpsuit抓包,將其中post的內容用paste from file替換掉
然後發送
最好獲取shell路徑爲 在之前的正常路徑下面加上我們的解壓路徑,如http://127.0.0.1/v9/phpsso_server/uploadfile/avatar/1/1/3/22/test.php