Java 反序列化漏洞原理-漏洞解析7
前言
在 Java 安全领域,反序列化漏洞是绕不开的核心高危漏洞,它不依赖前端参数、不局限于业务接口,广泛存在于框架、中间件、第三方依赖和自定义代码中。对于 Java 后端开发、安全开发工程师来说,吃透反序列化漏洞的底层原理、成因、利用逻辑、加固方案,既是面试必考题,也是企业代码安全审计、护网排查的核心能力。
本文从基础概念→漏洞原理→核心成因→风险场景→企业级加固代码→面试考点全维度拆解,完全贴合 Java 安全开发实战与面试需求。
一、核心基础:序列化与反序列化
1. 定义
- 序列化:将Java 对象转换为二进制字节流的过程,用于对象存储、网络传输、缓存持久化;
- 反序列化:将二进制字节流重新还原为Java 对象的过程,是序列化的逆操作。
2. 核心规则
- 只有实现了
java.io.Serializable接口的对象,才能被序列化 / 反序列化; - 序列化 / 反序列化由 JVM 自动完成,开发者可重写
readObject()自定义逻辑; - 序列化数据可被人为构造、篡改。
3. 基础代码示例
import java.io.Serializable;
// 实现Serializable接口,标记为可序列化
public class User implements Serializable {
private String username;
private String password;
// 重写readObject方法(漏洞核心入口)
private void readObject(java.io.ObjectInputStream s) throws Exception {
s.defaultReadObject();
// 危险逻辑:若此处写入命令执行代码,反序列化时会自动触发
Runtime.getRuntime().exec("calc");
}
}
二、Java 反序列化漏洞核心原理
1. 漏洞本质
服务端信任并直接反序列化「用户可控的恶意二进制数据」,触发重写的 readObject() 方法或第三方依赖中的恶意利用链,最终实现远程代码执行(RCE)。
2. 完整攻击链路
- 攻击者构造恶意序列化字节流(包含命令执行、代码执行逻辑);
- 通过接口、Cookie、请求参数将恶意数据发送给 Java 服务端;
- 服务端调用原生反序列化 API,将恶意数据还原为对象;
- 自动执行
readObject()方法,触发恶意代码; - 服务器执行命令,攻击者完全控制主机。
3. 本章总结
反序列化本身不是漏洞,「反序列化用户可控的不可信数据」才是漏洞。
三、漏洞核心成因
1. 最核心原因:直接反序列化用户可控数据
服务端直接读取前端传入的参数、Cookie、HTTP Body 中的字节流,不做任何校验就执行反序列化。
// 错误写法:直接反序列化前端传入的不可信数据(高危漏洞)
ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
User user = (User) ois.readObject(); // 恶意数据直接触发漏洞
2. 自定义类重写 readObject() 包含危险操作
开发者在重写方法时,写入了 Runtime、ProcessBuilder 等命令执行 API,反序列化时自动触发。
3. 第三方依赖存在「反序列化利用链」
这是企业项目最常见的风险点:经典的 Apache Commons Collections(CC 链) 工具包,存在可被利用的反序列化链,几乎所有老 Java 项目都会引入该依赖,攻击者无需自定义恶意类,直接构造链即可触发 RCE。
4. 框架 / 中间件默认开启反序列化功能
主流 Java 框架存在原生反序列化风险:
- Shiro:RememberMe 功能会自动反序列化 Cookie 中的用户数据;
- RMI/JNDI:远程调用服务默认支持反序列化;
- Fastjson/Jackson:历史版本存在自动反序列化漏洞;
- Weblogic/JBoss/Tomcat:中间件自带反序列化风险点。
5. 无白名单校验,允许任意类反序列化
Java 原生反序列化默认不限制可加载的类,攻击者可构造任意恶意类被 JVM 加载执行。
四、高危风险场景
- Shiro 权限框架:RememberMe Cookie 反序列化;
- 远程调用服务:RMI、JNDI、Hessian 接口;
- 自定义数据传输接口:使用 Java 序列化做接口通信;
- 缓存 / 会话持久化:Redis、Session 存储序列化对象;
- 老旧第三方组件:Commons Collections、BeanUtils 等漏洞依赖。
五、企业级安全加固方案
1. 根本方案:禁止反序列化用户可控数据
核心原则:永远不要反序列化前端传入的任何不可信数据这是最彻底、最安全的修复方式,从源头杜绝漏洞。
2. 替代方案:放弃 Java 原生序列化
Java 原生序列化是不安全、冗余、低效的,企业项目推荐替换为安全的序列化格式:
- 文本格式:JSON(Fastjson/Jackson 升级最新版)
- 二进制格式:Protobuf、Thrift
- 禁用 Java 原生
ObjectInputStream做数据传输
3. 强制白名单校验
若必须使用 Java 反序列化,重写 ObjectInputStream,仅允许合法白名单类反序列化,拦截所有恶意类。
4. 升级第三方依赖,修复利用链
- 升级
commons-collections到无漏洞版本; - Shiro 升级到最新版,开启强随机密钥,关闭非必要 RememberMe 功能;
- Fastjson/Jackson 升级到最新安全版,开启安全模式;
- 卸载老旧、无用的第三方组件。
5. 中间件 / 框架加固
- Tomcat/Weblogic:禁用 RMI/JNDI 匿名访问;
- Shiro:RememberMe Cookie 加密,密钥长度≥32 位,定期更换;
- 禁止在反序列化流程中调用
Runtime、ProcessBuilder等危险函数。
6. 代码审计 + 安全扫描
- 全局搜索代码:
ObjectInputStream、readObject()、Serializable; - 使用漏洞扫描工具排查反序列化风险;
- 护网 / 上线前做专项渗透测试。
六、Java 安全面试高频考点
1. 什么是 Java 反序列化漏洞?
答:Java 反序列化漏洞是指服务端直接反序列化用户可控的恶意二进制数据,触发 readObject() 方法或第三方利用链,最终实现远程代码执行(RCE) 的超高危漏洞。
2. 漏洞的核心触发点是什么?
答:反序列化时,JVM 会自动执行类中的 readObject() 方法,若该方法存在危险逻辑,或存在可利用的第三方依赖链,就会触发漏洞。
3. 为什么 Apache Commons Collections 会导致反序列化漏洞?
答:Commons Collections 中存在恶意反序列化利用链(CC 链),攻击者可构造字节流触发链中的代码执行逻辑,无需自定义恶意类,即可实现 RCE。
4. Java 反序列化漏洞的加固方案有哪些?
答:按优先级排序:
- 禁止反序列化用户可控数据(根本方案);
- 替换为 JSON、Protobuf 等安全序列化格式;
- 重写反序列化流,添加类白名单校验;
- 升级第三方依赖,修复 CC 链、Shiro 等漏洞;
- 中间件加固,禁用危险远程调用服务。
5. Shiro RememberMe 反序列化漏洞原理?
答:Shiro 的 RememberMe 功能会自动反序列化 Cookie 中的用户数据,且默认密钥简单易破解,攻击者构造恶意序列化数据写入 Cookie,服务端反序列化时触发 RCE。
七、总结
Java 反序列化漏洞是 Java 生态的顶级高危漏洞,核心风险源于信任不可信数据,攻击链路简单、危害极大,是护网行动、代码审计的必查项。
对于 Java 开发者:
- 牢记核心原则:永远不要反序列化前端传入的不可信数据;
- 优先放弃 Java 原生序列化,使用 JSON 等安全格式;
- 必须使用时,强制添加类白名单校验;
- 定期升级第三方依赖,修复已知利用链。
对于安全工程师:
- 重点排查 Shiro、RMI、Commons Collections 等经典风险点;
- 代码审计聚焦
ObjectInputStream和readObject()方法。
更多推荐

所有评论(0)