最直接风险是攻击者构造恶意对象链触发魔术方法实现Getshell,如Typecho 1.0.14前台Getshell、GitLab RCE等真实案例;根源在于未校验输入来源、未收敛危险类与方法、缺少运行时防护,防御需重建信任边界而非简单替换函数。

PHP反序列化漏洞防御不当,最直接的风险就是被攻击者构造恶意对象链,触发魔术方法中的危险操作,最终实现Getshell。这不是理论推演,而是真实发生过多次的攻击路径——比如Typecho 1.0.14的前台Getshell、GitLab早期RCE等案例,都源于对unserialize()调用缺乏有效约束。
输入来源未校验:把用户数据当可信对象还原
很多系统在Session、Cookie、HTTP头、URL参数甚至数据库读取中,直接将用户可控字符串传给unserialize()。例如Typecho的install.php从Typecho_Cookie::get('__typecho_config')取值后未做任何过滤就反序列化。只要攻击者能控制这段字符串,就能决定“恢复出什么类、带什么属性、执行哪些方法”。
- 常见高危入口:Cookie中的配置字段、JSONP回调名、日志回显点、缓存键值、第三方API响应体
- 关键识别点:代码中出现
unserialize($_GET[...])、unserialize($cookie_val)、unserialize(file_get_contents(...))且变量来源未明确限定为服务端生成
类与方法未收敛:危险魔术方法构成天然利用跳板
PHP中__wakeup()、__destruct()、__toString()、__get()等魔术方法会在反序列化或对象使用过程中自动触发。一旦某个可加载类中存在调用system()、file_put_contents()、call_user_func()等函数的逻辑,它就可能成为Gadget Chain的一环。
- Typecho案例中,
__toString()触发Typecho_Db拼接导致SQL注入,再结合__get()调用_applyFilter()执行任意PHP代码 - 老版本ThinkPHP、Laravel、Monolog等框架组件中也曝出过类似链路,根源都是业务类无意暴露了可被串联的危险行为
缺少运行时防护:单靠编码规范难防绕过
仅靠“不写危险类”或“开发时注意”无法兜底。攻击者可通过Composer依赖、历史遗留类、动态加载机制引入未被审计的类;也可能利用__wakeup()绕过(CVE-2016-7124)、POP链变形、或配合phar://伪协议绕过常规检测。
- 签名验证必须覆盖完整序列化内容,且密钥不可硬编码、不可泄露
- 白名单机制要严格限制反序列化类名,包括类成员中嵌套的接口、泛型类型、匿名类引用
- RASP或WAF需hook到
unserialize()底层调用,识别非常规类名、异常属性结构、高频危险函数调用模式
修复不是替换函数,而是重建信任边界
把unserialize()换成json_decode()只是规避,不是加固。真正有效的防御是明确回答三个问题:这个数据谁写的?谁读的?读完之后要做什么?
- 优先改用结构化、无执行语义的格式(如JSON、XML),并开启严格模式解析(如
json_decode($str, true, 512, JSON_THROW_ON_ERROR)) - 若必须保留对象语义,应封装统一反序列化入口,强制校验HMAC签名,并在加载前比对类名哈希白名单
- 对老系统,先禁用所有外部输入的
unserialize()调用(如重写为抛出异常),再逐个评估是否真需该功能、能否重构替代
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











