漫谈 JEP 290
字数 2820 2025-08-04 00:46:02

JEP 290 深入解析与教学文档

1. JEP 290 概述

JEP 290(JDK Enhancement Proposal 290)是Java平台提供的一个安全增强功能,全称为"Filter Incoming Serialization Data"(过滤传入的序列化数据)。其主要目的是为Java反序列化操作提供安全防护机制。

1.1 主要功能

  1. 类过滤机制:提供黑白名单方式限制可反序列化的类
  2. 图形复杂度控制:限制反序列化深度和复杂度
  3. RMI验证机制:为RMI导出的对象设置验证机制
  4. 全局配置:支持通过属性或配置文件配置全局过滤器

1.2 支持版本

  • JDK 9 原生支持
  • 向后移植到:
    • JDK 8u121
    • JDK 7u131
    • JDK 6u141

2. 核心类与架构

2.1 核心类结构

ObjectInputStream
├── serialFilter (ObjectInputFilter)
│   ├── checkInput() 方法
│   ├── Config (静态类)
│   │   ├── configuredFilter
│   │   ├── serialFilter
│   │   ├── createFilter()
│   │   └── getSerialFilter()
│   └── Global (静态类,Config的内部类)
│       ├── filters (函数列表)
│       └── checkInput() 方法
└── filterCheck() 方法

2.2 ObjectInputStream 类

JEP 290 在 ObjectInputStream 中增加了两个关键部分:

  1. serialFilter 属性ObjectInputFilter 类型,实际过滤器实现
  2. filterCheck 方法:执行过滤检查逻辑

构造函数行为

  • 两个构造函数都会将 serialFilter 初始化为 ObjectInputFilter.Config.getSerialFilter()

filterCheck 方法逻辑

  1. 检查 serialFilter 是否为空
  2. 封装检查信息为 FilterValues 对象
  3. 调用 serialFilter.checkInput() 进行检查
  4. 根据返回状态决定是否抛出异常

2.3 ObjectInputFilter 接口

函数式接口,核心方法是 checkInput(),包含以下组件:

  1. Config 静态类:管理全局过滤器配置
  2. FilterInfo 接口:提供过滤检查的上下文信息
  3. Status 枚举:表示过滤结果状态(ALLOWED, REJECTED, UNDECIDED)

2.4 Config 静态类

关键字段与方法

  1. configuredFilter:静态字段,初始化时从以下位置读取配置:

    • JVM 参数 jdk.serialFilter
    • 配置文件 %JAVA_HOME%/conf/security/java.security
  2. createFilter():将规则字符串解析为 Global 对象

  3. serialFilter:静态字段,初始化为 configuredFilter 的值

  4. getSerialFilter():返回 serialFilter 字段值

2.5 Global 静态类

实现 ObjectInputFilter 接口,关键特性:

  1. filters 字段:函数列表,存储解析后的过滤规则
  2. checkInput() 方法:遍历 filters 执行检查
  3. 构造函数:解析 JEP 290 规则字符串为 lambda 表达式

JEP 290 规则格式

pattern=setting[,pattern=setting...]

其中 pattern 支持:

  • 完整类名
  • 包名后跟 ".*"
  • 模块名后跟 "/"
  • 通配符 "**"

3. 过滤器类型与配置

3.1 全局过滤器

通过设置 Config.serialFilter 静态字段实现,影响所有 ObjectInputStream 实例。

配置方式

  1. JVM 参数:-Djdk.serialFilter=规则字符串
  2. 配置文件:在 java.security 中添加 jdk.serialFilter=规则字符串

WebLogic 示例
WebLogic 启动时会设置全局过滤器:

  1. 创建 WebLogicObjectInputFilterWrapper 对象
  2. 通过反射设置 Config.serialFilter
  3. 包含 WebLogic 的黑名单规则

3.2 局部过滤器

针对单个 ObjectInputStream 实例的过滤设置。

设置方式

  1. 直接调用:
    • JDK 9+:setObjectInputFilter()
    • JDK 8u121-8u201:setInternalObjectInputFilter()
  2. 通过 Config.setObjectInputFilter() 设置

4. RMI 中的 JEP 290 实现

4.1 RegistryImpl 的特殊处理

  1. Target 对象特征

    • ID 固定为 0 (ObjID.REGISTRY_ID)
    • disp 的 filter 为 RegistryImpl::registryFilter
    • skel 为 RegistryImpl_skel
  2. 过滤器初始化

    • sun.rmi.registry.registryFilter 读取规则
    • 默认白名单包含 RMI 相关类
  3. 请求处理流程

    • unmarshalCustomCallData 中设置局部过滤器
    • 先检查自定义规则,再检查默认白名单

4.2 DGCImpl 的特殊处理

  1. Target 对象特征

    • ID 固定为 2 (ObjID.DGC_ID)
    • disp 的 filter 为 DGCImpl::DGCFilter
    • skel 为 DGCImpl_skel
  2. 过滤器初始化

    • sun.rmi.transport.dgcFilter 读取规则
    • 默认白名单包含 DGC 相关类

5. 绕过与防御

5.1 绕过 JEP 290 的条件

当服务端导出以下对象时可能绕过防护:

  1. 普通远程对象(非 RegistryImpl/DGCImpl)
  2. 对象方法参数类型为 Object
  3. Target 对象的 disp.filter 为 null

原因:缺少局部过滤器设置,全局过滤器可能被绕过

5.2 反制措施

恶意服务端可反制攻击客户端:

  1. 针对 RegistryImpl_Stub.lookup/list:直接返回恶意对象
  2. 针对枚举工具(如 RmiTaste):利用客户端自动反序列化特性

6. 最佳实践

  1. 全局配置

    • 在生产环境中配置 jdk.serialFilter
    • 使用严格的白名单策略
  2. RMI 安全

    • 为自定义远程对象设置过滤器
    • 限制可绑定的对象类型
  3. 防御绕过

    • 监控和限制 Object 类型参数的方法
    • 定期更新黑名单规则
  4. 版本管理

    • 使用已包含 JEP 290 的 JDK 版本
    • 及时应用安全补丁

7. 总结

JEP 290 通过多层次的过滤机制增强了 Java 反序列化的安全性:

  1. 全局与局部过滤器相结合
  2. RMI 核心组件内置防护
  3. 灵活的规则配置方式
  4. 图形复杂度控制

正确理解和配置 JEP 290 是防御反序列化攻击的关键,但也需要注意其局限性,结合其他安全措施构建纵深防御体系。

JEP 290 深入解析与教学文档 1. JEP 290 概述 JEP 290(JDK Enhancement Proposal 290)是Java平台提供的一个安全增强功能,全称为"Filter Incoming Serialization Data"(过滤传入的序列化数据)。其主要目的是为Java反序列化操作提供安全防护机制。 1.1 主要功能 类过滤机制 :提供黑白名单方式限制可反序列化的类 图形复杂度控制 :限制反序列化深度和复杂度 RMI验证机制 :为RMI导出的对象设置验证机制 全局配置 :支持通过属性或配置文件配置全局过滤器 1.2 支持版本 JDK 9 原生支持 向后移植到: JDK 8u121 JDK 7u131 JDK 6u141 2. 核心类与架构 2.1 核心类结构 2.2 ObjectInputStream 类 JEP 290 在 ObjectInputStream 中增加了两个关键部分: serialFilter 属性 : ObjectInputFilter 类型,实际过滤器实现 filterCheck 方法 :执行过滤检查逻辑 构造函数行为 : 两个构造函数都会将 serialFilter 初始化为 ObjectInputFilter.Config.getSerialFilter() filterCheck 方法逻辑 : 检查 serialFilter 是否为空 封装检查信息为 FilterValues 对象 调用 serialFilter.checkInput() 进行检查 根据返回状态决定是否抛出异常 2.3 ObjectInputFilter 接口 函数式接口,核心方法是 checkInput() ,包含以下组件: Config 静态类 :管理全局过滤器配置 FilterInfo 接口 :提供过滤检查的上下文信息 Status 枚举 :表示过滤结果状态(ALLOWED, REJECTED, UNDECIDED) 2.4 Config 静态类 关键字段与方法 : configuredFilter :静态字段,初始化时从以下位置读取配置: JVM 参数 jdk.serialFilter 配置文件 %JAVA_HOME%/conf/security/java.security createFilter() :将规则字符串解析为 Global 对象 serialFilter :静态字段,初始化为 configuredFilter 的值 getSerialFilter() :返回 serialFilter 字段值 2.5 Global 静态类 实现 ObjectInputFilter 接口,关键特性: filters 字段 :函数列表,存储解析后的过滤规则 checkInput() 方法 :遍历 filters 执行检查 构造函数 :解析 JEP 290 规则字符串为 lambda 表达式 JEP 290 规则格式 : 其中 pattern 支持: 完整类名 包名后跟 ".* " 模块名后跟 "/" 通配符 "** " 3. 过滤器类型与配置 3.1 全局过滤器 通过设置 Config.serialFilter 静态字段实现,影响所有 ObjectInputStream 实例。 配置方式 : JVM 参数: -Djdk.serialFilter=规则字符串 配置文件:在 java.security 中添加 jdk.serialFilter=规则字符串 WebLogic 示例 : WebLogic 启动时会设置全局过滤器: 创建 WebLogicObjectInputFilterWrapper 对象 通过反射设置 Config.serialFilter 包含 WebLogic 的黑名单规则 3.2 局部过滤器 针对单个 ObjectInputStream 实例的过滤设置。 设置方式 : 直接调用: JDK 9+: setObjectInputFilter() JDK 8u121-8u201: setInternalObjectInputFilter() 通过 Config.setObjectInputFilter() 设置 4. RMI 中的 JEP 290 实现 4.1 RegistryImpl 的特殊处理 Target 对象特征 : ID 固定为 0 ( ObjID.REGISTRY_ID ) disp 的 filter 为 RegistryImpl::registryFilter skel 为 RegistryImpl_skel 过滤器初始化 : 从 sun.rmi.registry.registryFilter 读取规则 默认白名单包含 RMI 相关类 请求处理流程 : 在 unmarshalCustomCallData 中设置局部过滤器 先检查自定义规则,再检查默认白名单 4.2 DGCImpl 的特殊处理 Target 对象特征 : ID 固定为 2 ( ObjID.DGC_ID ) disp 的 filter 为 DGCImpl::DGCFilter skel 为 DGCImpl_skel 过滤器初始化 : 从 sun.rmi.transport.dgcFilter 读取规则 默认白名单包含 DGC 相关类 5. 绕过与防御 5.1 绕过 JEP 290 的条件 当服务端导出以下对象时可能绕过防护: 普通远程对象(非 RegistryImpl/DGCImpl) 对象方法参数类型为 Object Target 对象的 disp.filter 为 null 原因 :缺少局部过滤器设置,全局过滤器可能被绕过 5.2 反制措施 恶意服务端可反制攻击客户端: 针对 RegistryImpl_Stub.lookup/list :直接返回恶意对象 针对枚举工具(如 RmiTaste):利用客户端自动反序列化特性 6. 最佳实践 全局配置 : 在生产环境中配置 jdk.serialFilter 使用严格的白名单策略 RMI 安全 : 为自定义远程对象设置过滤器 限制可绑定的对象类型 防御绕过 : 监控和限制 Object 类型参数的方法 定期更新黑名单规则 版本管理 : 使用已包含 JEP 290 的 JDK 版本 及时应用安全补丁 7. 总结 JEP 290 通过多层次的过滤机制增强了 Java 反序列化的安全性: 全局与局部过滤器相结合 RMI 核心组件内置防护 灵活的规则配置方式 图形复杂度控制 正确理解和配置 JEP 290 是防御反序列化攻击的关键,但也需要注意其局限性,结合其他安全措施构建纵深防御体系。