0x00
1、 首先全局搜索危险函数eval:在zzz_template.php中存在该函数的调用。
详细看一下这个函数的内容:
在类ParserTemplate中,并且调用parserCommon函数时可以触发函数。
2、 首先分析parserIfLabel函数,要如何才能触发:单独把函数copy出来分析
首先24行,根据eval的字符串的拼接方式,查看什么样的$ifstr可以达到getshell的条件:
根据测试,如上可以使得整个字符串变成正确的php代码。
之后分析代码逻辑,如何构造$content,可以使得经过正则表达式匹配后的$content刚好是上面那个亚子。
我选择把正则表达式拷贝出来,然后利用匹配网站实时匹配,最后构造字符串:{if:1){}phpinfo();//};{end if}
将字符串赋值$content时,经过preg_match_all()函数之后出现了一丢丢问题,借助xdebug修改的到最后的字符串:{if:1);phpinfo();//}{end if}可以成功getshell;
3、 找到可以getshell的点之后,就要考虑如何触发这个函数了。上面我们看到函数是存在ParserTemplate类当中,通过parserCommon函数可以调用,限制我们可以全局搜索一下这两个关键字:
全局共有两处调用:zzz_client.php和save.php。
0x01 zzz_client.php
在第122行调用函数。
分析一下如何能够使程序运行到122行。
当$location变量为user的时候可以进入,$location变量来源于getlocation函数。
进入getlocation函数
再跟进getform函数:
根据代码就是获取get传递的location参数值。那我们debug调试一下:(zzz_client.php被前台index.php包含调用)
在55行获取模板地址:
由于在88行之后检查登录状况,模板地址被重新赋值了:此时的模板地址:
/zzzphpV1.6.1/template/pc/cn2016/html/userlogin.html
然后我们去后台查找这个模板,发现不存在,利用失败:
当我们登录之后:
加载了userinfo.html模板。现在我们将之前测试的$content内容插入userinfo.html
成功getshell。
0x02 save.php
现在来看看save.php处,这个函数有多处都可以调用parserCommon函数,我记录一下我成功getshell的一处位置:
在925行调用了parserCommon函数,看一下如何才能调用这个create_index函数
搜索发现存在两处调用:
此处触发要求$type=“index”或者”all“
之后要调用create_index要先调用create_html,要调用create_html要使$act=createhtml
接下来先构造:http://www.zzzcms.com/admin/save.php?act=createhtml&type=index
发现最后显示模板不存在:
跟踪之后发现还要传递模板路径参数:
修改url: http://www.zzzcms.com/admin/save.php?act=createhtml&type=index&folder=pc
加载了index.html,我们还是要修改模板中index.html的内容,然后成功getshell: