thinkphp5文件包含漏洞分析
thinkphp5文件包含漏洞的源码审计与分析
文件包含漏洞
环境复现
直接官网下载对应版本的源码包,使用docker部署即可。
使用已有开源环境复现:
(1)执行命令 docker pull p0ison/thinkphp:5.0.18
(2)执行命令 docker run -itd -p 80:80 p0ison/thinkphp:5.0.18
(3)访问地址 :http://xx.xx.xx.xx/tp/public
版本影响: 5.0.0<=ThinkPHP5<=5.0.18 、5.1.0<=ThinkPHP<=5.1.10
漏洞利用
启动环境,请求http://x.x.x.x/public/ tp5自带的公共模块
修改application/index/controller/Index.php
内容如下:
1 |
|
在application/index/
目录下新增view
文件夹;
在view
文件夹下新增与模块名同名的文件夹index
;
在index
文件夹下新建文件index.html
,内容随意即可;
最后请求http://x.x.x.x/public/index.php/index/index/index?cacheFile=/etc/passwd,成功读取文件
漏洞分析
首先我们新建的类方法中调用模板渲染函数的assign,跟进函数assgin的源码,直接进入\thinkphp\library\think\Controller.php
发现调用view类中的assgin方法,跟进代码,进入\thinkphp\library\think\view.php
分析源码发现这里对模板变量值进行了赋值,并且存入到了数组中;
这里基本没什么问题。赋值完成后,会去调用fetch方法加载模板输出,这里如果没有指定模板名称,就会使用默认的文件作为模板当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html
进行渲染,如果没有默认文件程序就回报错。继续跟进fetch方式,进入\thinkphp\library\think\Controller.php
发现直接调用view类中fetch,直接跟进代码,进入\thinkphp\library\think\view.php
继续跟进代码内容进入\think\view\driver\Think.php
发现代码继续调用template类的fetch方法,跟进代码
我们发现在这里变量$vars直接赋值给$this->data,并且直接被带入到template类中文件引擎调用read方法,跟进read方法,\think\template\driver\File.php
卧槽,这里的read方法竟然对$vars调用了extract的函数,这样就可以直接覆盖cacheFile变量了,因为这里的$vars变量是可以用户控制的;最终达成了利用。