查看原文
其他

Web漏洞分析之zzcms多个CVE分析

孑狱天 看雪学院 2019-09-16

本文为看雪论坛优秀文章

看雪论坛作者ID:孑狱天



这次接着上次的分析:


前篇传送门:Web漏洞分析之——CVE-2019-1010153


这次直接分析剩下四个RCE漏洞。说是四个,其实真正的漏洞可以说是只有一个。漏洞编号分别是:CVE-2019-1010148、CVE-2019-1010152、CVE-2019-1010150、CVE-2019-1010149。


这里先选择最后一个(需要本文复现的cms附件在上一篇文章内)。



漏洞分析





好了,直接步入正题。漏洞之一发生在install/index.php中——这是cms应用安装文件。

使用seay打开zzcms的根目录。打开漏洞文件。


刚进来就看见两个extract():


if($_POST) extract($_POST, EXTR_SKIP)
 
if($_GET) extract($_GET, EXTR_SKIP);


遇见这个函数就要注意变量覆盖漏洞了(但这里没有)因为extract函数的flag参数设置的是EXTR_SKIP。


flags

对待非法/数字和冲突的键名的方法将根据取出标记flags参数决定。可以是以下值之一:

EXTR_OVERWRITE

如果有冲突,覆盖已有的变量。

EXTR_SKIP

如果有冲突,不覆盖已有的变量。

EXTR_PREFIX_SAME

如果有冲突,在变量名前加上前缀prefix。

EXTR_PREFIX_ALL

给所有变量名加上前缀prefix。

EXTR_PREFIX_INVALID

仅在非法/数字的变量名前加上前缀prefix。

EXTR_IF_EXISTS

仅在当前符号表中已有同名变量时,覆盖它们的值。其它的都不处理。举个例子,以下情况非常有用:定义一些有效变量,然后从$_REQUEST中仅导入这些已定义的变量。

EXTR_PREFIX_IF_EXISTS

仅在当前符号表中已有同名变量时,建立附加了前缀的变量名,其它的都不处理。

EXTR_REFS

将变量作为引用提取。这有力地表明了导入的变量仍然引用了array参数的值。可以单独使用这个标志或者在flags中用 OR 与其它任何标志结合使用。如果没有指定flags,则被假定为EXTR_OVERWRITE。


当flag为EXTR_OVERWRITE是可能会存在变量覆盖漏洞。

继续往下看,来到105-108行:


作用是打开 inc/config.php 并将响应相应的str值写入到文件。

但str变量中含有其他可控变量:


$str=str_replace("define('siteurl','".siteurl."')","define('siteurl','$url')",$str)


这一句中参数$url在文件之前并未初始化过。而之前又用extract函数将变量$url导入到当前的符号表,所所以url变量可控,这就导致了可向inc/config.php文件中写入任意代码。


二话不说,访问install/index.php文件看看:


果然不出所料,检测了安装锁文件。全局搜索一下””安装向导已运行安装过,如需重安装””字符串,发现在本文件安装第一步包含的文件中:

switch($step) {
 
case '1'://协议
 
include 'step_'.$step.'.php';
 
break;


进入step_1.php中:

if(file_exists("install.lock")){
 
echo "
<div style='padding:30px;'>安装向导已运行安装过,如需重安装,请删除 /install/install.lock 文件</div>";
 
}


要想写入任意代码,必须删除install/install.lock文件。


然后我们先来看下一个漏洞文件——user/licence_save.php:


if ($_GET["action"]=="add"){
 
query("Insert into zzcms_licence(title,img,editor,sendtime) values('$title','$img','$username','".date('Y-m-d H:i:s')."')") ;
 
}elseif ($_GET["action"]=="modify"){
 
$oldimg=trim($_POST["oldimg"]);
 
$id=$_POST["id"];
 
if ($id=="" || is_numeric($id)==false){
 
$FoundErr=1;
 
$ErrMsg="<li>". $f_array[0]."</li>";
 
WriteErrMsg($ErrMsg);
 
}else{
 
query("update zzcms_licence set title='$title',img='$img',sendtime='".date('Y-m-d H:i:s')."',passed=0 where id='$id'");
 
if ($oldimg<>$img && $oldimg<>"/image/nopic.gif"){
 
$f="../".$oldimg;
 
if (file_exists($f)){
 
unlink($f);
 
}
 
$fs="../".str_replace(".","_small.",$oldimg)."";
 
if (file_exists($fs)){
 
unlink($fs);
 
}
 
}
 
}
 
}


当action=‘modify’,oldimg=$_POST[“oldimg”],接着删除由oldimg拼接的文件$fs,造成了任意文件删除漏洞。



>>>>

思路


可以用任意文件删除漏洞删除安装锁文件即install/install.lock,再使用install/index.php文件的任意代码写入,最终写入并执行任意代码。



>>>>

漏洞复现


首先post数据删除install.lock(我用的postman):


这里访问user/licence_save.php前要先注册用户(浪费了好长时间,不知道公司的名称格式,最后索性直接删了验证公司名称的代码):


访问过后,install/install.lock文件果然没有了。


接着访问http://127.0.0.1/install/index.php进行重装,接着就和上一篇一样,安装到第4步时,将网站访问地址改为:(这个就是url参数):


http//:127.0.0.1');phpinfo();//



点击下一步,安装成功后可以看到:


已经在inc/config.php插入了代码,再次访问http://127.0.0.1/inc/config.php:


可以看到代码已经成功执行了。

最后,我们再来看一下剩下的几个漏洞。

CVE-2019-1010150

在/user/zssave.php文件中:

$oldimg=trim($_POST["oldflv"]);
 
if ($oldflv<>$flv && $oldflv<>""){
 
$f="../".$oldflv;
 
if (file_exists($f)){
 
unlink($f); }
 
}


仅仅是一个任意文件删除,接下来依旧是利用上一个任意代码写入,而且是同样的文件,一样的套路……


CVE-2019-1010152


在user/manage.php中:


$oldflv = isset($_POST['oldflv'])?$_POST['oldflv']:'';
 
if ($oldflv<>$flv){
 
$f="../".$oldflv;
 
if (file_exists($f)==true){
 
unlink($f);
 
}


依旧是一样的套路……


CVE-2019-1010148


这个依旧是一样的。/user/adv.php中:


$oldimg=$_REQUEST["oldimg"];
 
if ($oldimg<>$img){
 
$f="../".$oldimg;
 
if (file_exists($f)){
 
unlink($f);
 
}


依旧是RCE,但CNVD公布的是SQ注入,估计他们也对这些水漏洞感到无奈了吧。

这些漏洞其实RCE的只能算是一个,这个大佬为了刷CVE也是够水的了。




- End -




看雪ID: 孑狱天

https://bbs.pediy.com/user-805563.htm  


*本文由看雪论坛 孑狱天 原创,转载请注明来自看雪社区






推荐文章++++

Web漏洞分析之——CVE-2019-1010153

App免Root加载Xposed插件工具Xpatch源码解析(二)

彩蛋解密之物理内存读写到****的转变

某企业办公APP逆向TCP协议分析

FART正餐前甜点:ART下几个通用简单高效的dump内存中dex方法













“阅读原文”一起来充电吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存