web漏洞分析(1)之——CVE-2019-1010153
2019-08-29 15:43:50 Author: bbs.pediy.com(查看原文) 阅读量:195 收藏

看雪web板块有点冷清,那就那几篇文章与各位大佬分析与交流一下,增进社区活跃度。

本人学识有限,若有错误之处请多多包含。

在逛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

此文章已同时发布至我新建的个人博客,欢迎围观。

[活动]走进企业看安全第22站--蚂蚁金服!


文章来源: https://bbs.pediy.com/thread-254144.htm
如有侵权请联系:admin#unsafe.sh