0%

ThinkPHP3.2.x RCE复现

ThinkPHP3.2.x RCE复现

漏洞描述

该漏洞是在受影响的版本中,业务代码中如果模板赋值方法assign的第一个参数可控,则可导致模板文件路径变量被覆盖为携带攻击代码的文件路径,造成任意文件包含,执行任意代码。个人感觉这个漏洞虽然不如thinkphp本体的一些RCE漏洞影响范围大,但也算是提供了一个思路,对基于某些框架二次开发的系统,寻找其不规范的方法调用的思路还是值得学习的。

环境搭建

ThinkPHP3.2.3 Phpstudy8.1.1 PHP-5.6.9 Apache Windows10(tp3手册)

如果是linux可以用composer拉取环境( composer create-project topthink/thinkphp=3.2.3 tp3)

先访问http://xxx.xx/index.php 生成项目文件

image-20210714130932384

然后在\Application\Home\Controller\IndexController.class.php写入demo代码

1
2
3
4
5
6
7
8
9
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
public function index($value=''){
$this->assign($value);
$this->display();
}
}

因为该漏洞利用的assign函数需要模板渲染,所以需要对应的模板文件,与demo相对应的文件路径:

1
2
3
4
\Application\Home\View\Index\index.html
/*此处的Index目录和index.html文件需自己创建
index.html的内容任意
*/

漏洞分析

借用玄甲安全实验室的一张图,整体看一下程序的执行流程

image-20210909094308482

接下来分析具体的代码:

Application/Home/Controller/IndexController.class.php

assign方法中第一个变量可控

image-20210714144552762

跟进assign函数

ThinkPHP/Library/Think/Controller.class.php

image-20210714145223478

调用的是ThinkPHP/Library/Think/View.class.php中的assign函数,此时进入else分支,我们传进去的$value被赋值给$this->tVar

image-20210714145158360

返回后进入display函数,注意这是一个无参调用

image-20210714145819669

调用的是ThinkPHP/Library/Think/View.class.php的display函数,开始解析并获取模板文件内容,此时模板文件路径和内容为空

image-20210714150822344

进入ThinkPHP/Library/Think/View.class.php的fetch函数后,会先判断模板存不存在,这也是为什么我们要创建模板文件的原因

image-20210714151415868

接着判断是不是php类型模板,不是进入else分支。接着$params 被赋值,var即为为我们传进去的日志路径,file为模板文件的路径。

image-20210714151836840

接着进入ThinkPHP/Library/Think/Hook.class.php的listen函数,经过一些判断,进入exec函数

image-20210714152708275

接着exec函数把$params带进ThinkPHP/Library/Behavior/ParseTemplateBehavior.class.php的run函数处理

image-20210714153315655

进入ThinkPHP/Library/Think/Template.class.php的fetch函数

image-20210714153522998

进入最后的load函数,$var不为空则使用extract方法的EXTR_OVERWRITE默认描述对变量值进行覆盖,之后include该日志文件路径,造成文件包含。

image-20210714153704479

漏洞利用

  • 日志包含

    image-20210714154206984

    日志在Application/Runtime/Logs/Home目录下

    image-20210714154445495

    开启debug

    1
    2
    请求不报错 日志文件在 Application/Runtime/Logs/Home下
    请求会报错 日志文件在 Application/Runtime/Logs/Common下

    关闭debug

    1
    2
    请求不会报错 不会记录日志
    请求会报错 日志文件在 Application/Runtime/Logs/Common
  • 上传入口

    利用系统自带的上传功能,上传包含shell的文件

1
http://x.x.x.x/index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Common/21_07_14.log

image-20210716163001792

参考文章

ThinkPHP3.2.x RCE漏洞通报

-------------本文结束感谢您的阅读-------------