FineCMS前台getshell 2016-09-30

FineCMS企业网站管理系统(简称免费版或企业版)是一款基于PHP+MySql+CI框架开发的高效简洁的中小型内容管理系统,面向多终端包括Pc端网页和移动端网页,支持自定义内容模型和会员模型,并且可以自定义字段,可面向中小型站点提供重量级网站建设解决方案,适用于小型站点、企业级网站、新闻内容网站等。

漏洞概要

finecms某处过滤不严格,导致可上传任意脚本文件。

漏洞详情

依旧是AttachmentController,当然这次不再是kindeditor_upload的上传文件然后包含文件这么简单了,而是直接上传脚本执行。

这次出现问题的是ajaxswfuploadAction方法,这个方法代码不是很多,我就直接全部贴出来了:

/**
* Swf上传
*/
public function ajaxswfuploadAction() {
   if ($this->post('submit')) {
       $_type = explode(',', $this->post('type'));
       if (empty($_type)) {
           exit('0,' . lang('att-6'));
       }
       $size = (int)$this->post('size');
       if (empty($size)) {
           exit('0,' . lang('att-5'));
       }
       $data = $this->upload('Filedata', $_type, $size, null, null, $this->post('admin'), 'swf', null, $this->post('document'));
       if ($data['result']) {
           exit('0,' . $data['result']);
       }
       //唯一ID,文件全路径,扩展名,文件名称
       exit(time() . rand(0, 999) . ',' . $data['path'] . ',' . $data['ext'] . ',' . str_replace('|', '_', $data['file']));
   } else {
       exit('0,' . lang('att-4'));
   }
}

聪明的人,一眼就能看出来,从post请求中获取了type
那么这个type是干啥用的?没错,他是设定允许上传的文件类型的,并且在第289行左右直接带入了upload函数!!!我的天哪!!

本以为这样就可以直接上传php文件进行getshell了,但是发现其实finecms也不傻~~在upload函数中进行了强制性的黑名单过滤:

$ext = $upload->fileext();
if (stripos($ext, 'php') !== FALSE
    || stripos($ext, 'asp') !== FALSE
    || stripos($ext, 'aspx') !== FALSE
    ) {
    return array('result' => '文件格式被系统禁止');

首先是获取了文件后缀,用了fileext()函数,跟进来看看:

/**
* 取得文件扩展
*
* @return 扩展名
*/
public function fileext() {
    return strtolower(trim(substr(strrchr($this->file_name['name'], '.'), 1, 10)));
}

先取出.和后面的所有字符,然后从.往后取出10个字符,最终全部转成小写。

然后我们继续看这个看似很牛逼的黑名单:

if (stripos($ext, 'php') !== FALSE
    || stripos($ext, 'asp') !== FALSE
    || stripos($ext, 'aspx') !== FALSE
    ) {
    return array('result' => '文件格式被系统禁止');

stripos函数从前往后查找phpaspaspx如果查到了就直接return了。

那好…… 我们利用phtml来进行绕过,不知道phtml是啥请自行百度。。。

先构造上传的html表单

然后上传一个带有一句话木马的phtml文件,答案是可行的:

3355820565

访问上传的文件看看:

3548661543

那么我们再用工具连接下这个一句话木马看看:

3356429280

至此,一个前台getshell,bingo!

漏洞修复

文件/controllers/AttachmentController.php第224行的判断添加phtml限制:

if (stripos($ext, 'php') !== FALSE
    || stripos($ext, 'phtml') !== FALSE
    || stripos($ext, 'asp') !== FALSE
    || stripos($ext, 'aspx') !== FALSE
    ) {
    return array('result' => '文件格式被系统禁止');
}

另外不是很推荐用黑名单,用白名单会比黑名单有效得多。(其实这个修复方式还是可以绕过的)