[toc]
ThinkPHP5文件包含漏洞
POC
1 | /public/index.php/index/index?cacheFile=favicon.ico |
可配合文件上传图片马,GetShell。(PHP 文件包含都讲文件当做php后缀文件进行解析,与实际文件类型无关)
漏洞概述
漏洞存在于 ThinkPHP 模板引擎中,在加载模版解析变量时存在变量覆盖问题,而且程序没有对数据进行很好的过滤,最终导致 文件包含漏洞 的产生。
- 变量覆盖漏洞
https://www.cnblogs.com/wangtanzhi/p/12748967.html
如果没有指定 flags,则被假定为 EXTR_OVERWRITE。
代码:
1 |
|
这种情况没有指定 flags,则被假定为 EXTR_OVERWRITE
假设用户构造以下链接:http://www.a.com/test1.php?auth=1
界面上会打印出private!
安全的做法是确定register_globals=OFF后,在调用extract()时使用EXTR_SKIP保证已有变量不会被覆盖。
ps:
PHP extract() 函数从数组中把变量导入到当前的符号表中。对于数组中的每个元素,键名用于变量名,键值用于变量值。
影响版本
5.0.0<=ThinkPHP5<=5.0.18 、5.1.0<=ThinkPHP<=5.1.10
漏洞分析
这里以ThinkPHP 5.0.18
进行分析。
在历史Releases
信息中,找到了 5.0.19
中,改进了 模板引擎的一处可能的安全隐患。
/library/think/template/driver/File.php
中的 File
类中的read
方法。
- 用户Get提交的数据都会通过
input
方法获取数据,然后通过filterValue
方法进行过滤和强制类型转换。 - 在修改后的代码下断点,然后看方法调用和参数传递。如下图:
在../application/index/index/controller/index.php
中,代码如下:
1 |
|
用户输入的数据被get
方法获取,然后调用了input
方法和递归调用filterValue
方法,并且该方法还会继续调用filterExp
方法对特殊字符进行过滤,然后返回给$data
然后再调用assign
方法,返回处理后的数据。
因此用户的数据输入,经过get
方法和assign
方法后,返回的内容为cacheFile=favico.ico
,然后程序继续调用fetch
方法进行处理。
fetch方法用于加载模板输出。这里如果我们没有指定模板名称,其会使用默认的文件作为模板,模板路径类似 当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html ,如果默认路径模板不存在,程序就会报错。
跟进到 Template 类的 fetch 方法,可以发现可控变量 $vars 赋值给 $this->data 并最终传入 File 类的 read 方法。而 read 方法中在使用了 extract 函数后,直接包含了 $cacheFile 变量。这里就是漏洞发生的关键原因(可以通过 extract 函数,直接覆盖 $cacheFile 变量,因为 extract 函数中的参数 $vars 可以由用户控制)。
方法调用栈: