java反序列化漏洞核心风险是攻击者通过可控输入流触发任意类readobject执行恶意逻辑,须在类加载前用objectinputfilter白名单过滤或重写resolveclass拦截非法类型。

Java 反序列化漏洞的核心风险在于:攻击者通过可控输入流,触发任意类的 readObject 方法,进而执行恶意逻辑(如 gadget 链、静态块、资源加载等)。防范不能只靠“事后校验”,而必须在类加载前就拦截非法类型。ObjectInputFilter 是 JDK 9+ 提供的标准化、可配置的过滤机制,是当前最推荐的基础防线。
用 ObjectInputFilter 设置白名单过滤器
ObjectInputFilter 在反序列化每个类之前调用 checkInput,检查类名、数组长度、图深度等。它不是黑名单,而是白名单式控制——只允许明确信任的类路径。
- 必须在调用
readObject()前设置,否则无效;推荐在构造ObjectInputStream后立即绑定 - 使用
ObjectInputFilter.Config.createFilter()构建规则,例如:"com.myapp.dto.**;maxdepth=5;maxarray=10000;!*"
其中**匹配子包,!*表示其余全拒 - 避免泛滥通配符(如
java.**或javax.**),尤其禁用org.apache.commons.collections、groovy.、com.sun.等高危前缀
全局与局部过滤器的配合使用
单一策略易被绕过,建议分层设防:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 应用启动时设置全局默认过滤器:
System.setProperty("jdk.serialFilter", "com.myapp.model.**;maxrefs=200;maxbytes=1000000"); - 对敏感入口(如网络请求、缓存反序列化)单独设置更严格的实例级过滤器:
ois.setObjectInputFilter(ObjectInputFilter.Config.createFilter("com.myapp.request.User;!*")); - 全局过滤器可被实例级覆盖,但实例级未设置时会 fallback 到全局策略,因此两者互补
重写 resolveClass 实现动态校验(兼容老版本或增强控制)
当需要租户隔离、运行时策略变更,或运行在 JDK 8 及以下环境时,继承 ObjectInputStream 并重写 resolveClass 是最底层、不可绕过的防护手段。
- 校验逻辑必须基于
desc.getName(),禁止调用Class.forName()(会提前触发类加载) - 严格拒绝:
— 空/空白类名
— 数组表示(如[Ljava.lang.String;)
— 内部类(含$)、匿名类
— 危险包名(如org.springframework.core.env.MapPropertySource) - 非法类必须抛出
ClassNotFoundException,不能静默调用super.resolveClass(),否则等于放行
补充校验:防止基本类型默认值滥用
ObjectInputFilter 不拦截基本类型(int、boolean 等),但它们的默认值(0、false)可能被业务逻辑误用。需结合设计层面加固:
- 将关键字段改为包装类型(
Integer、Boolean),并在readObject中显式判null - 在
readObject末尾调用ois.registerValidation(this, 0),实现ObjectInputValidation接口,在反序列化完成后统一校验字段完整性 - 避免业务代码依赖“未赋值即为 false”逻辑,例如不要写
if (!user.isAdmin) deny();,而应明确判断user.isAdmin == null并报错
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










