menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right ... chevron_right 5.0.0 = Thinkphp =5.0.18 文件包含漏洞 chevron_right 5.0.0 = Thinkphp =5.0.18 文件包含漏洞.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    5.0.0 = Thinkphp =5.0.18 文件包含漏洞.md
    3.94 KB / 2021-07-15 20:06:22
        5.0.0 \<= Thinkphp \<= 5.0.18 & 5.1.0 \<= ThinkPHP \<= 5.1.10 文件包含漏洞
    ==========================================================================
    
    一、漏洞简介
    ------------
    
    本次漏洞存在于 **ThinkPHP**
    模板引擎中,在加载模版解析变量时存在变量覆盖问题,而且程序没有对数据进行很好的过滤,最终导致
    **文件包含漏洞** 的产生。
    
    二、漏洞影响
    ------------
    
    5.0.0 \<= Thinkphp \<= 5.0.18
    
    5.1.0 \<= ThinkPHP \<= 5.1.10
    
    三、复现过程
    ------------
    
    ### 漏洞环境
    
    通过以下命令获取测试环境代码:
    
        composer create-project --prefer-dist topthink/think=5.0.18 tpdemo
    
    将 **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**
    文件,内容随意(没有这个模板文件的话,在渲染时程序会报错),并将图片马
    **1.jpg** 放至 **public** 目录下(模拟上传图片操作)。
    
    ### poc
    
        http://0-sec.org:8000/index/index/index?cacheFile=demo.php
    
    接着访问链接,即可触发 **文件包含漏洞** 。
    
    ![1.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId26.png)
    
    ### 漏洞分析
    
    首先在官方发布的 **5.0.19** 版本更新说明中,发现其中提到该版本包含了一个安全更新。
    
    ![2.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId28.png)
    
    我们可以查阅其 **commit** 记录,发现其改进了模板引擎,其中存在危险函数
    **extract** ,有可能引发变量覆盖漏洞。接下来,我们直接跟进代码一探究竟。
    
    ![3.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId29.png)
    
    首先,用户可控数据未经过滤,直接通过 **Controller** 类的 **assign**
    方法进行模板变量赋值,并将可控数据存在 **think\\View** 类的 **data**
    属性中。
    
    ![4.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId30.png)
    
    接着,程序开始调用 **fetch**
    方法加载模板输出。这里如果我们没有指定模板名称,其会使用默认的文件作为模板,模板路径类似
    **当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html**
    ,如果默认路径模板不存在,程序就会报错。
    
    ![5.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId31.png)
    
    我们跟进到 **Template** 类的 **fetch** 方法,可以发现可控变量 **\$vars**
    赋值给 **\$this-\>data** 并最终传入 **File** 类的 **read** 方法。而
    **read** 方法中在使用了 **extract** 函数后,直接包含了 **\$cacheFile**
    变量。这里就是漏洞发生的关键原因(可以通过 **extract** 函数,直接覆盖
    **\$cacheFile** 变量,因为 **extract** 函数中的参数 **\$vars**
    可以由用户控制)。
    
    ![6.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId32.png)
    
    ### 漏洞修复
    
    官方的修复方法是:先将 **\$cacheFile** 变量存储在 **\$this-\>cacheFile**
    中,在使用 **extract** 函数后,最终 **include** 的变量是
    **\$this-\>cacheFile** ,这样也就避免了 **include** 被覆盖后的变量值。
    
    ![3.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId34.png)
    
    ### 攻击总结
    
    最后,再通过一张攻击流程图来回顾整个攻击过程。
    
    ![7.png](./resource/5.0.0<=Thinkphp<=5.0.18文件包含漏洞/media/rId36.png)
    
    参考链接
    --------
    
    > https://github.com/Mochazz/ThinkPHP-Vuln
    
    
    links
    file_download