PHP反序列化漏洞实战核心是打通“可控输入→unserialize→魔术方法→危险操作”链路,需快速识别入口、定位高危类、构造合法payload,并通过分层加固(如禁用unserialize、白名单类、JSON替代)防御。

PHP反序列化漏洞实战演练的核心,是把“可控输入 → unserialize调用 → 魔术方法触发 → 危险操作执行”这条链路跑通。它不依赖高深加密或0day,而取决于你能否快速识别入口、定位可利用类、构造合法且有效的序列化字符串。
找准反序列化入口点
入口点就是unserialize()函数接收用户可控数据的地方。常见位置包括:
-
GET/POST参数:如
unserialize($_GET['data'])或unserialize(base64_decode($_POST['payload'])) -
Cookie值:尤其是框架中自动反序列化的session或自定义cookie,例如
unserialize($_COOKIE['remember_token']) - 文件读取内容:比如从缓存文件、日志、上传的Phar包中读取并反序列化
-
Session反序列化:当session.save_handler配置为
php_serialize,而读取时却用php方式解析,可能造成类型混淆和绕过
快速识别危险类与魔术方法
不是所有类都危险,关键看它的魔术方法是否包含敏感操作。审计时重点关注:
- __destruct():对象生命周期结束时必触发,常用于写文件、发请求、执行命令
- __wakeup():反序列化瞬间立即调用,适合初始化或触发后续逻辑
- __toString():在echo、拼接、比较等场景下被隐式调用,容易被链入
- __invoke()、__call()、__get():虽非必触发,但在特定上下文(如数组访问、函数调用)中可成为POP链关键跳板
看到类里有file_put_contents、system、highlight_file、curl_exec、include等函数调用,且参数来自对象属性,就要立刻标记为高危候选。
手工构造Payload的关键细节
绕过长度校验和属性可见性是实战中最易卡壳的环节。记住几个硬规则:
- 公有属性格式为
s:4:"name";s:5:"value"; - 私有属性必须带前缀
\0ClassName\0property,序列化后表现为不可见字符,需用十六进制或chr()构造 - 保护属性格式为
\0*\0property - 所有长度数字(如
s:10:中的10)必须与后续实际字符串字节长度完全一致,一个字节都不能差 - 若目标有过滤(如str_replace过滤
[、]、空格),可用%00、十六进制编码属性名、或利用PHP解析器对空白符的宽松处理来绕过
防御加固的落地做法
修复不能只靠“别用unserialize”,而要分层落实:
- 首选
json_decode()替代unserialize(),JSON无魔术方法、结构清晰、天然防对象注入 - 必须用unserialize时,强制指定
allowed_classes参数(PHP 7.4+),传false禁用所有类,或只放行白名单数组 - 对输入做前置校验:检查是否以
O:、a:、C:等序列化标识开头;用正则粗筛非法字符 - 关键系统(如后台、API)禁用
unserialize函数,通过php.ini设置disable_functions = unserialize - 对敏感类加访问控制,把危险逻辑移出魔术方法,改由显式方法调用
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











