赞
踩
- 本次漏洞存在于 ThinkPHP 模板引擎中,在加载模版解析变量时存在变量覆盖问题,而且程序没有对数据进行很好的过滤,最终导致文件包含漏洞的产生
- 漏洞影响版本: 5.0.0<=ThinkPHP<=5.0.21 、 5.1.3<=ThinkPHP5<=5.1.25
- 获取测试环境代码
composer create-project --prefer-dist topthink/think=5.0.18 tpH3rmesk1t
- 将
composer.json
文件的require
字段设置成如下
"require": {
"php": ">=5.6.0",
"topthink/framework": "5.0.18"
},
然后执行
composer update
,并将application/index/controller/Index.php
文件代码设置如下
<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
public function index()
{
$this->assign(request()->get());
return $this->fetch(); // 当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html
}
}
创建 application/index/view/index/index.html 文件,内容随意(没有这个模板文件的话,在渲染时程序会报错)
将图片马 demo.jpg 放至 public 目录下(模拟上传图片操作),访问
http://127.0.0.1/cms/public/index.php/index/index?cacheFile=demo.jpg
首先,用户可控数据未经过滤,直接通过
Controller
类的assign
方法进行模板变量赋值,并将可控数据存在think\View
类的data
属性中
接着程序开始调用
fetch
方法加载模板输出,这里如果我们没有指定模板名称,其会使用默认的文件作为模板,模板路径位:当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html
,如果默认路径模板不存在,程序就会报错,跟进到thinkphp/library/think/View.php
我们跟进到
Template
类的fetch
方法,可以发现可控变量$vars
赋值给$this->data
并最终传入File
类的read
方法,而read
方法中在使用了extract
函数后,直接包含了$cacheFile
变量,这里就是漏洞发生的关键原因,因为extract
函数中的参数$vars
可以由用户控制,可以通过extract
函数,直接覆盖$cacheFile
变量
完整的方法调用,从下往上
官方的修复方法是:先将
$cacheFile
变量存储在$this->cacheFile
中,在使用extract
函数后,最终 include 的变量是$this->cacheFile
,这样也就避免了 include 被覆盖后的变量值
参考Mochazz师傅的审计流程
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。