反序列化漏洞:为什么「不要反序列化不可信数据」是铁律
反序列化看起来只是「把字节变回对象」,但对象的析构、唤醒、toString 等魔术方法会在特定时机自动执行。
一旦这些方法里存在危险操作(写文件、执行命令、发起请求), attacker 就能把数据变成执行流。
先说结论
不可信数据一律不用原生反序列化,改用 JSON;必须用时加类白名单。
- 优先 JSON/Protobuf 等纯数据格式
- 必须反序列化时限制可实例化类
- 升级有已知 gadget 的依赖库
- 对反序列化入口做签名校验
漏洞是怎么产生的
反序列化利用需要三个条件:可控的输入、可用的 gadget 链、以及一条能把链串起来的魔术方法。
这三者缺一不可,所以防御也有三个着力点:入口、gadget、以及根本不用原生反序列化。
修复与验证
修复不是改一行代码,而是四件事一起做:
- 盘点所有反序列化入口:缓存、Cookie、消息队列、RPC
- 能换格式的都换成 JSON,并做 schema 校验
- 无法替换的加签名(HMAC)与类白名单
- 升级依赖,清理含危险魔术方法的库
- 对入口做监控:异常长的序列化串值得告警
攻击面与检测点
按影响面排序,先修影响最大的:
| 语言 | 常用入口 | 防御手段 |
|---|---|---|
| Java | ObjectInputStream | 类白名单/ObjectInputFilter |
| PHP | unserialize | allowed_classes 参数 |
| Python | pickle | 禁用,改 JSON |
| Node | node-serialize | 避免使用 |

几个容易踩的坑
下面这些是最常见的错误做法:
- Base64 编码就认为安全:解码成本为零
- 只过滤关键字:链可以用反射构造
- 信任内部服务传来的序列化数据:内网也可能被攻陷
- 忽略依赖库的 gadget:漏洞常来自第三方
写在最后
这条铁律值得反复强调:永远不要反序列化不可信来源的数据。没有例外。
安全不是一次加固,是持续的假设:假设输入不可信、假设边界会破、假设有人会看错。
评论 (3)
修复清单比漏洞描述有用多了,很多文章只讲怎么打不讲怎么防。
白名单那条永远是最有效的,正则黑名单迟早绕过。
建议再补一条:把这类检查加到 CI 里,靠人记必然漏。
发表评论