YCCMS
YCCMS是一款PHP版輕量級CMS建站系統,程序頁面設計簡潔,生成靜態html,後臺功能強大,利於優化、超強收錄、超強排名,適合做關鍵詞排名、淘寶客程序,是個人、企業建站的理想選擇。
審計版本:YCCMS建站系統 3.3
更新時間:2018-08-29
審計準備
下載源碼,本地phpstudy搭建環境。
打開seay,自動審計cms代碼,確定審計範圍和目標點。
瀏覽CNVD,看看已經披露的漏洞有哪些。
接下來就是逐一進行有目標的審計,看看能不能復現出來。
代碼審計
代碼執行漏洞
確定漏洞點,/public/class/Factory.class.php
關鍵代碼:
class Factory{
static private $_obj=null;
static public function setAction(){
$_a=self::getA();
if (in_array($_a, array('admin', 'nav', 'article','backup','html','link','pic','search','system','xml','online'))) {
if (!isset($_SESSION['admin'])) {
header('Location:'.'?a=login');
}
}
if (!file_exists(ROOT_PATH.'/controller/'.$_a.'Action.class.php')) $_a = 'Index';
eval('self::$_obj = new '.ucfirst($_a).'Action();');
return self::$_obj;
}
static public function setModel() {
。。。
}
static public function getA(){
。。。
}
}
分析 setAction() 方法,首先調用 getA() 方法獲取 get 過來的 a 參數進行跳轉檢查操作,然後 file_exists() 函數進行檢查頁面文件是否存在,最後調用 eval() 執行PHP代碼。
我們想要利用 eval 執行代碼,就得先成功逃逸 file_exists 函數。
file_exists() 主要作用是檢查文件是否存在,但是這個函數在進行檢查會有一個bug,如 /controller/admin;/…/,函數允許路徑中有一些特殊字符,並且遇到 /…/ 會返回到上級目錄,可以利用這個策略逃逸出 file_exists() 函數檢查。
payload:Factory();phpinfo();//../
全局搜索,看看那裏實例化了 Factory 這個類。
可以看到 /config/run.inc.php 有實例化,那再看看那裏包含了該文件。
可以看到 /admin/index.php 和 /config/count.php 包含了該文件。
漏洞復現:
文件上傳漏洞
前臺似乎沒有找到,後臺找到一處上傳點。
處理其代碼邏輯在 /public/class/LogoUpload.class.php,關鍵代碼如下:
//構造方法,初始化
public function __construct($_file,$_maxsize) {
$this->error = $_FILES[$_file]['error'];
$this->maxsize = $_maxsize / 1024;
$this->type = $_FILES[$_file]['type'];
$this->path = ROOT_PATH.'/'.UPLOGO;
$this->name = $_FILES[$_file]['name'];
$this->tmp = $_FILES[$_file]['tmp_name'];
$this->checkError(); //驗證錯誤
$this->checkType(); //驗證類型
$this->checkPath(); //驗證目錄
$this->moveUpload(); //移動文件
}
繞過很簡單,上傳一個PNG格式,大小不超過2M的圖片,bp抓包,修改內容爲php一句話,後綴改爲php。
有警告不要緊,php文件其實已經生成了。
使用菜刀去連接就行了。
任意文件刪除漏洞
確定漏洞點,/controller/PicAction.class.php
關鍵代碼如下:
//圖片控制器
class PicAction extends Action{
public function __construct(){
parent::__construct();
}
public function index(){
。。。
}
public function delall(){
if(isset($_POST['send'])){
if(validate::isNullString($_POST['pid'])) tool::layer_alert('沒有選擇任何圖片!','?a=pic',7);
$_fileDir=ROOT_PATH.'/uploads/';
foreach($_POST['pid'] as $_value){
$_filePath=$_fileDir.$_value;
if(!unlink($_filePath)){
tool::layer_alert('圖片刪除失敗,請設權限爲777!','?a=pic',7);
}else{
header('Location:?a=pic');
}
}
}
}
}
可以看出 filePath 中拼接了 post 過來的 pid 參數,然後執行 unlink 刪除該路徑的文件。
pid 參數是可控的,這就造成了漏洞。
漏洞觸發處:
先在本地創建一個測試文件,test.txt。
點擊刪除圖片,bp抓包,修改 pid 參數。
成功刪除文件。