首页/安全/漏洞与攻击面速查/反序列化风险原理
Web 漏洞原理与防护55 条

反序列化风险原理

反序列化把字节流还原为对象,若数据源不可信且在还原过程中触发方法调用(Java readObject、PHP unserialize、Python pickle 等),可能形成代码执行;核心原则是不要把不可信数据交给原生反序列化。

漏洞与攻击面速查安全更新于 2026-10-13

反序列化风险是什么

反序列化把字节流还原为程序对象,如果数据源不可信、且还原过程中会触发方法调用或类加载,攻击者就能借构造的字节流让程序执行非预期逻辑——从读写文件到远程命令执行。风险的关键在于「数据格式自带行为」:Java 的序列化、PHP 的序列化函数、Python 的 pickle 等在设计上允许对象图重建,而这个过程中调用的方法链会被攻击者利用。防护方向明确:把不可信数据的传输格式换成纯数据格式(JSON 等),必须使用原生序列化时则用白名单限制可还原的类。

基本信息

风险类别OWASP Top 10 2021 A08 软件与数据完整性失效;CWE-502
高危函数Java ObjectInputStream、PHP unserialize、Python pickle、Ruby Marshal
触发条件类路径中存在可被拼接利用的类,且数据可控
判断要点数据是否来自用户?是否存在危险类?两者同时出现风险显著
常见位置会话与令牌、消息队列、缓存、RPC 接口、导入导出与插件
根治方式改用纯数据格式,或对可还原类型做严格白名单
组件维度依赖库版本决定可用链的多少,需要同步升级

典型场景

  • 登录态或令牌用序列化对象存储,客户端可影响其内容
  • 消息队列把对象序列化后传递,生产者与消费者跨信任域
  • 缓存里存放序列化对象,缓存服务被写入即可注入
  • 远程调用接口接收序列化参数,服务端直接反序列化
  • 导入导出功能把序列化内容作为文件内容处理
  • 插件与规则引擎允许外部传入配置对象

安全替代示例

安全替代示例
Java:改用 JSON(Jackson/Gson)并禁用多态类型解析
PHP:改用 json_decode;必须 unserialize 时用 allowed_classes 白名单
Python:改用 json;避免 pickle.loads(用户输入)
Ruby:避免 Marshal.load;改用 JSON 解析
# 共同点:让传输格式只承载数据,不承载行为
# 迁移要覆盖所有读写该格式的端点,单点改造会留下兼容分支

三类入口与对策

入口风险来源对策
网络接口参数客户端可直接构造字节流改纯数据格式并做结构校验
缓存与队列中间组件被写入或被越权访问限制组件访问来源,校验内容
本地文件与导入文件内容来自外部解析前校验来源与格式
会话存储客户端可影响会话内容改用签名令牌或服务端存储
组件升级可减少可用链,但不能替代代码层改造:应把反序列化入口改为数据格式解析。
排查时先找「谁在解析不可信数据」而不是先看依赖清单:入口定位清楚后,改造范围与验证方式都更明确。

易错点

  • 认为『只在内网传输就安全』:横向移动阶段内网数据同样不可信
  • 只在网关过滤特征字节:序列化格式存在大量编码变体,绕过成本低
  • 白名单配置过宽:允许还原的类越多,可利用链越多
  • 改造不彻底留下兼容分支:旧格式入口若仍可访问,等于没修
  • 只升级依赖不改造代码:入口仍在解析不可信数据,风险只是变难而不是消失
  • 忽略缓存与队列:这类通道常被排除在接口清单之外,实际同样接收外部数据

数据来源与参考

  • OWASP Deserialization Cheat Sheet
  • Oracle Java 文档(ObjectInputStream 安全说明)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌