[代码审计]ThinkPHP5的文件包含漏洞
漏洞影响范围
加载模版解析变量时存在变量覆盖问题,导致文件包含漏洞的产生 漏洞影响版本:5.0.0<=ThinkPHP5<=5.0.18 、5.1.0<=ThinkPHP<=5.1.10
tp框架搭建
tp框架由两部分组成 应用项目: https://github.com/top-think/think 核心框架: https://github.com/top-think/framework 框架下载好后,需要更名为thinkphp
这里可以直接用composer来获取代码 通过以下命令获取测试环境代码:
|
|
将 composer.json 文件的 require 字段设置成如下:
|
|
然后执行 composer update ,并将 application/index/controller/Index.php 文件代码设置如下:
|
|
创建 application/index/view/index/index.html 文件
漏洞分析
payload:
|
|
这边会有一个过滤,看起来像sql的过滤,与我们这次的没啥关系
然后进入fetch方法,走完前面的缓存,就会进入一个read方法
这里进行了一个变量的赋值:extract($vars, EXTR_OVERWRITE);
,但是这里他设置了一个属性:EXTR_OVERWRITE
这个属性的存在,会照成一个变量覆盖的效果
这时候,cacheFile就会变成我们get提交的数据 下一步就是直接包含了这个文件 输出读取的文件
成功的包含到了
漏洞总结
总体来说,漏洞的思路就是:
- 先通过view的assign把get数据存在数组data中
- 然后进入view的fetch方法,通过
$vars = array_merge(self::$var, $this->data, $vars);
,将data中的数据再合并到vars的变量中去
- 再进入了Think的fetch方法,vars变量被赋进去了
- 再到template的fetch方法中去,data变量依旧继续传递下去
- 到template的fetch方法里面,里面有一个cacheFile变量,值为箭头所指的文件,到了read方法,data和cacheFile一起被赋值进去
- 可以看到,这里的extract函数由于EXTR_OVERWRITE设置了参数,所以cacheFile变量被覆盖了,导致后面的include就包含了我们vars中的值,而这个值我们是可以控制的,这就造成了一个文件包含的漏洞
漏洞的修复
官方漏洞的修复方案
他这里是用了一个$this->cacheFile
这样一来,在include的时候就不会因为变量覆盖而包含到我们data中的数据了
|
|
这里学长的文章也是提到了为啥参数不换成EXTR_SKIP
防止变量的覆盖呢,EXTR_SKIP的作用就是:如果有冲突,不覆盖已有的变量,那么这一步就会失效,万一你确实是想传这么一个$cacheFile=xxx,那么到这里就会直接实效掉,导致功能的损坏,所以利用$this->cacheFile
是更优的选择