finecms_5.08_前台getshell

这是六月份的一个漏洞,当时漏洞作者直接在自己的blog公布细节了,但是对于初学者来说可能理解起来还是有点吃力,所以我对这个漏洞进行了跟踪复现,希望各位能有所收获。

首先我们直接看作者的payload

1
http://your_address/index.php?c=api&m=data2&auth=0ce0d2401ce4802751739552c8e4467&param=update_avatar&file=data:image/php;base64,PD9waHAgcGhwaW5mbygpOz8+

我们直接输入payload从Index.php开始跟踪。

跟进到init.php。

可以看到通过判断uri是否存在来判断是否进行路由跳转,如果是index.php或?开头则不跳转。
(trim和strpos都是常用的php函数,三元式也非常常见,不懂的朋友们可以自行翻看php手册,如果是mac用户可以安装一个dash,配上小帽子查阅会比较方便。)我们继续往下看。


这里直接跳到了流程处理文件。CI(CodeIgniter)是一个开源的php的web开发框架。所以你们会看到很明显的finecms自己的代码注释是中文,而CI部分的代码注释是英文。我们跟进去看。

CI是一个api类的实例,api类在/finecms/dayrui/controllers/Api.php中。call_user_func_array是php内置的一个调用用户函数的函数。传入回调函数和参数,其中参数为数组形式进行调用。如果要调用类的方法,则需要传入数组。如:

1
2
3
4
5
6
7
8
9
10
11
$params = array();
class A{
public function B(){
echo '1';
echo '2';
}
}
$test = new A();
call_user_func_array(array(&$test,'B'),$params);

然后我们跟进api中的data2方法中。

auth的值会跟md5(SYS_KEY)进行比对,只有相同才能进行下一步。然后我们搜索SYS_KEY。


SYS_KEY是定义在/config/system.php中的常量,换言之,对应的auth也是固定的。那压根就没有什么验证可言。这一步绕过了,然后往下看。


首先从REQUEST获取file参数。然后将空格转换为+号。判断文件夹是否存在,不存在则创建。然后重点来了,用正则提取file参数,(\w+)提取了MIME中的subtype。然而这里对subtype却没有进行任何过滤,所以当我们构造data:image/php;base64,xxxxx这样的参数时,会直接生成一个0x0.php出来。最后,对后面的base64进行解码,写入这个生成的0x0.php当中。这是将一句话或者马进行base64编码即可直接上传。

我们按照作者的payload测试一下,成功执行后访问对应的文件名。


成功显示phpinfo。
显然,开发者对file_put_contents过滤有问题。按照这个思路,大家可以搜索这个cms当中的file_put_contents函数,然后逆向跟踪。

另外一个思路,就是这里的SYS_KEY使用常量太蠢了,验证形同虚设,大家也可以根据这个去挖掘漏洞。