PHP 8.2 反序列化漏洞识别需代码审计定位unserialize()等高危入口、运行时检测环境配置风险(如phar.readonly=Off)、工具辅助验证POP链(如PHPGGC),三者结合缺一不可。

PHP 8.2 反序列化漏洞的识别,不依赖单一“修复工具”自动发现,而是靠代码审计+运行时检测+工具辅助验证三者结合。目前没有一款通用工具能像杀毒软件那样“一键扫描出所有反序列化漏洞”,原因在于:漏洞本质是业务逻辑缺陷(如 unserialize() 被可控输入触发),而非语法错误或已知签名。
下面从实操角度讲清楚怎么识别:
一、先定位高危入口点:找 unserialize() 的调用位置
这是最直接、最有效的第一步。在项目中全局搜索以下关键词:
-
unserialize( -
__unserialize(PHP 8.2 新增的魔术方法,用于自定义反序列化逻辑) -
phar://(Phar 反序列化利用常见载体,需检查文件路径拼接是否可控) -
session_start()配合session.serialize_handler=php_serialize(旧配置可能引发 session 反序列化)
重点关注这些上下文:
立即学习“PHP免费学习笔记(深入)”;
- 输入来自
$_GET、$_POST、$_COOKIE、$_REQUEST或文件读取(如file_get_contents()) - 没有白名单限制(如未使用
allowed_classes参数) - 出现在日志、缓存、配置加载、插件机制等“看似可信”的模块中
示例脆弱代码:
$data = $_COOKIE['user_data']; unserialize($data); // ❌ 完全不可信输入 + 无防护
二、检查 PHP 运行配置与环境风险
PHP 8.2 本身不引入新反序列化漏洞,但某些配置会放大风险:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 查看
php.ini中是否启用危险扩展:phar.readonly = Off(允许 Phar 执行) - 检查
unserialize()是否被禁用(disable_functions = unserialize)——若已禁用,说明团队已有安全意识,但需确认是否被绕过(如通过Phar::webPhar()) - 确认
error_reporting和display_errors是否关闭(避免报错泄露类名/POP链线索)
三、用专业工具辅助验证 POP 链是否存在
识别漏洞 ≠ 找到 unserialize(),还要确认有没有可用的 gadget 类(即 POP 链)。这时可借助:
-
PHPGGC(推荐首选):
- 运行
php phpggc -l列出当前环境中已知框架(如 Laravel、ThinkPHP)支持的链 - 若项目用了某框架,执行
php phpggc FrameworkName/RCE1 system "id"看是否能生成有效 payload - 成功生成 ≠ 漏洞一定存在,但说明该环境具备触发条件,需回头审计对应入口
- 运行
-
静态分析工具(辅助):
- PHPStan + 自定义规则(检测
unserialize()调用+参数来源) - Psalm(配置
--find-unused-code+ 自定义 security plugin) - 注意:这些工具无法判断
$input是否可控,仍需人工补充分析数据流
- PHPStan + 自定义规则(检测
四、动态验证:构造最小 PoC 测试是否真能触发
找到疑似入口后,手动构造测试 payload 验证:
- 先尝试一个无害的 gadget(如触发
__wakeup并写日志) - 使用
O:4:"Test":0:{}(空对象)测试是否报错,确认反序列化是否真的被执行 - 若项目含自定义类,用
php --rf ClassName查看是否定义了__destruct/__toString等魔术方法
小技巧:在目标代码前加
var_dump($input); exit;,把实际传入unserialize()的字符串抓出来,再用本地环境复现分析。
不复杂但容易忽略


















