查看原文
其他

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

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

本文为看雪论坛优秀文章

看雪论坛作者ID:孑狱天






在逛cnnvd的时候发现了近期的cms cve,今天复现一下。

本漏洞由一化名Lzly的人发现,今年七月一下发出来5个zzcms的”超危”漏洞。接下来要一个个的分析,这是第一个sql注入。


环境:

phpstudy

seay

chrome浏览器

zzcmsV8.3(附件)



zzcms安装与运行





下载zip包解压到web目录,访问127.0.0.1/install/index.php


直接下一步,直到创建数据库,填写相应的信息后,就开始安装了。


sql语句执行过后,点击下一步就安装成功了。


分析





在cnnvd的介绍中,漏洞文件在zs/subzs.php 中。


用seay加载zzcms根目录,打开zs/subzs.php。


刚读第一个函数就发现了漏洞所在:


$sql="select id,proname,img from zzcms_main where id in (".$cpid.")";


只要cookie中有zzcmscpid键,且&cpid含有,就会执行这个sql查询。

漏洞原因是因为函数未对cookie值验证,sql查询语句没用引号引起来,是数字型注入,一定要注意,从前端传到后端的数据都是可更改的。

全局搜索一下,看看哪里调用了这个函数:


可以看到在/label.php中调用了,跟进去看看。


function fixed($cs,$channel){

switch ($channel){

case 'ad':return showad($cs); break;

case 'zs':return showzs($cs); break;

case 'dl':return showdl($cs); break;

case 'pp':return showpp($cs); break;

case 'job':return showjob($cs); break;

case 'zx':return showzx($cs); break;

case 'zh':return showzh($cs); break;

case 'announce':return showannounce($cs); break;

case 'cookiezs':return showcookiezs($cs); break;

case 'zsclass':return showzsclass($cs); break;

case 'keyword':return showkeyword($cs); break;

case 'province':return showprovince($cs); break;

case 'sitecount':return showsitecount($cs); break;

}


再次全局搜索一下调用fixed函数的地方,就在同一文件处,即label.php中的showlabel函数。

function showlabel($str){
global $b;//zsshow需要从zs/class.php获取$b;zxshow从s/class.php获取$b;
$channels=array('ad','zs','dl','zx','pp','job','zh','announce','cookiezs','zsclass','keyword','province','sitecount');
foreach ($channels as $value) {
if (strpos($str,"{#show".$value.":")!==false){
$n=count(explode("{#show".$value.":",$str));//循环之前取值
for ($i=1;$i<$n;$i++){
$cs=strbetween($str,"{#show".$value.":","}");//strbetween作用是提取’{#show‘与‘:’之间的字符串
if ($cs<>''){$str=str_replace("{#show".$value.":".$cs."}",fixed($cs,$value),$str);} //$cs直接做为一个整体字符串参数传入,调用时再转成数组遍历每项值
}
}
}

//重要代码分割线————————————————————————————
//自定义标签
$channels='zs,dl,zx,pp,job,wangkan,zh,company,special,baojia,ask,link,ad,about,guestbook,help';
$channel = explode(",",$channels);
for ($a=0; $a< count($channel);$a++){
//类别标签
if (strpos($str,"{@".$channel[$a]."class.")!==false) {
$n=count(explode("{@".$channel[$a]."class.",$str));//循环之前取值
for ($i=1;$i<$n;$i++){
$mylabel=strbetween($str,"{@".$channel[$a]."class.","}");
$str=str_replace("{@".$channel[$a]."class.".$mylabel."}",labelclass($mylabel,$channel[$a]),$str);
}
}
//内容标签
if (strpos($str,"{@".$channel[$a]."show.")!==false) {
$n=count(explode("{@".$channel[$a]."show.",$str));//循环之前取值
for ($i=1;$i<$n;$i++){
$mylabel=strbetween($str,"{@".$channel[$a]."show.","}");
$str=str_replace("{@".$channel[$a]."show.".$mylabel."}",labelshow($mylabel,$b,$channel[$a]),$str);
}
}
}
return $str;
}


我将重要函数说明在代码中注释说明了,其中最重要的就是前面的foreach遍历循环,作用是在传入字符串中,寻找含有channel标签内的值,再用相应的channel值调用fixed,在上一个fixed函数中可以看到要调用初始的漏洞函数showcookies(),要在fixed()函数中传入带有’cookiezs‘channel值。

再次搜索一下调用showlabel()函数的代码:


这次就很多了,那就看最重要的index.php文件吧。


由于代码太多,我将最重要的找出来,分别是第19行第25行和第30行:

$fp=dirname(__FILE__)."/template/".$siteskin."/index.htm";//$siteurl是模板文件夹
$strout = fread($fso,filesize($fp));
if (strpos($strout,"{@")!==false)
$strout=showlabel($strout);

作用是将指定的模板文件打开,将内容赋值给strout,再传入showlabel()中。

ok,流程看完了。

接下来梳理一下脉络:

首先在index.php文件中获取模板文件内容,将内容字符串作为参数调用showlabel(),若是模板文件中含有{#showcookiezs:字串,则通过fixed()调用漏洞函数showcookiezs()

但是我看了一下index.php文件中调用的模板文件中,并不含有{#showcookiezs:字串,所以就回到上面寻找调用showlabel()函数的地方,发现调用这个函数的地方绝大数是和index.php文件的思路一样——找出模板文件,调用showlabel();最终,在zs.php文件中找到了调用了showlabel(),而且,在/template/red13/zs.htm文件中,含有必须字串:{#showcookiezs:

关键代码是zs.php中第204,206与342行:


$fp="../template/".$siteskin."/zs.htm";
$
strout = fread($f,filesize($fp));
$
strout=showlabel($strout);


在/template/red13/zs.htm中第18行:


<div class="content1">{#showcookiezs:3,60,60}</div>


再次梳理一下:

首先在zs.php文件中获取模板文件-/template/red13/zs.htm内容,将内容字符串作为参数调用showlabel()。

若是模板文件中含有{#showcookiezs:字串,则通过fixed()调用漏洞函数showcookiezs(),在showcookies()中判断cookie中是否含有zzcmscpid字段;若是有,则判断zzcmscpid值是否含有,有的话,就去掉此字段值中的空格与deleted字符,之后就执行sql查询了。



poc构造



构造并不难,在cookie中加入zzcmscpid字段,不能使用空格,可使用/**/ 或者%0a来代替空格,这里注入是无回显的。所以可使用基于时间的盲注与联合查询。

zzcmscpid=1)%0aunion%0aselect%0asleep(5),2,3#
【刚开始安装的现在终于派上了一点用场】


直接访问http://127.0.0.1/zs/zs.php 

F12打开开发者工具,填入exp,发现sleep执行成功(建议先sleep(20),比较好判断。)


剩余的sql注入利用,已经呼之欲出了。


参考:

https://gist.github.com/Lz1y/31595b060cd6a031896fdf2b3a1273f5



- End -




看雪ID: 孑狱天

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


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






推荐文章++++

Unicorn 调用SO之加载模块

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

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

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

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













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

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

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