反序列化漏洞:为什么「不要反序列化不可信数据」是铁律

Web安全 · 2 分钟阅读· 188 次阅读

反序列化看起来只是「把字节变回对象」,但对象的析构、唤醒、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 里,靠人记必然漏。

发表评论

验证码

提交后需站长审核,通过后才会显示。