FineCMS前台getshell 2016-09-30 #php #finecms
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
函数从前往后查找php
、asp
、aspx
如果查到了就直接return了。
那好…… 我们利用phtml来进行绕过,不知道phtml是啥请自行百度。。。
先构造上传的html表单
然后上传一个带有一句话木马的phtml文件,答案是可行的:
访问上传的文件看看:
那么我们再用工具连接下这个一句话木马看看:
至此,一个前台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' => '文件格式被系统禁止');
}
另外不是很推荐用黑名单,用白名单会比黑名单有效得多。(其实这个修复方式还是可以绕过的)