Thinkphp5 文件包含漏洞

329 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

影响版本

5.0.0<=ThinkPHP5<=5.0.18 、5.1.0<=ThinkPHP<=5.1.10

环境

我这里有之前安好的5.0.12就直接用了

\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内容任意(空文件亦可),主要是作为控制器中index方法的模板

分析

payload

?cacheFile=1.php            #我在public下写了一个1.php便于文件包含

首先是进入get(),其实get()就是获取我们get传参的值,内容也比较简单所以就粗略的跟进下。

$this->get不为空,$name是字符串,所以没进入if,直接进入input()(圈出来的是各参数值)

image.png input的前两个if都绕开了,getFilter()filter多赋了个null值,之后进arraywalkrecursive()回调filterValue()(这里的filter多赋了个null值,之后进`入array_walk_recursive()`回调`filterValue()`(这里的data就是上一步的$get值)

image.png

跟进后其实也没执行啥,就执行了最后的filterExp(),对用户传参进行过滤,但这个基本上是针对sql的所以对我们的payload没影响最终返回$data的值,其实$data的值自始至终没发生过改变

在就跟进assign()了,$name就是get()方法retrun的值,也就是$data的值

protected function assign($name, $value = '')
{
    $this->view->assign($name, $value);
}

再跟进$this->view->assign($name, $value);assign()

通过array_merge(),将$this->data$name的值合并传给data,data,但`this->data默认为null,所以也就相当于把name给了它,retrun返回name`给了它,retrun返回this

image.png

回到我们自己定义的控制器$this->assign(request()->get());就执行完了,再跟进下一行的fetch()

protected function fetch($template = '', $vars = [], $replace = [], $config = [])
{
    return $this->view->fetch($template, $vars, $replace, $config);
}

又是套娃继续跟进(四个参数默认为空)

还是array_merge()合并,1和3参数为空,所以vars=vars=data;也就是我们get传参的值,method三目运算,method三目运算,`renderContent=false所以$method=fetch160行就相当于又执行了fetch()`

image.png

跟进$template默认为空,parseTemplate()获取我们模板文件的路径,之后又又进入了fetch(),可以看下三个参数的值

image.png

跟进,前边三个if只有第一个执行了,然后进入parseTemplateFile(),里边其实就执行了一个记录模板文件的更新时间的操作,不看了

下边if,对$cacheFile赋值缓存的一个路径,之后直接进入read()

image.png

跟进,进入if进行了个变量覆盖在,EXTR_OVERWRITE标记的情况下,如果有冲突,覆盖已有的变量。所以就讲原有的缓存路径替换成了1.php最后文件包含

image.png

不得不说TP非RCE的链真的很友好!!!!

image.png