RMI学习

Sl0th Lv4

RMI学习

基础

组成

  • Client
  • Registry
  • Server

通信原理

  • 服务端绑定远程对象(java中定义的一个远程对象类)
  • 客户端只要传value
  • 解决端口问题:注册中心,储存远程对象value与服务端端口的映射(在远程对象创建时形成映射)

动态代码加载(JDK高版本去掉了)

如果客户端调用了服务端没有的类对象,RMI允许服务端去远程的Web Server上加载类

远程接口、对象、方法

通信的两端要实现一个相同接口:java.rmi.Remote

这个接口要抛一个异常

服务端实现远程调用的接口时,要继承UnicastRemoteObject,这样才能绑定到rmi服务里

流程

image-20221027182807035
image-20221027182807035

客户端和服务端都各自设置了一个代理 Skeleton/Stub

如果绑定端口到0,会被分配到随机端口

注册中心和服务端放在一台服务器上,防止远程调用时的安全问题

JRMP协议:RMI自定义的客户端协议

可以通过这个协议攻击stub

传输过程利用序列化,将收取到的数据反序列化,存在攻击点

DGC

静态变量dgclog,调用时会触发这个类的初始化,其静态代码块中会实例化一个DGCImpl_Stub

风险点:调用invoke,可进行反序列化攻击

攻击dgc不需要知道参数类型

Stub和Skeleton

Stub:客户端代理类

Skeleton:服务端代理类

image-20221101190521314
image-20221101190521314

实现过程

  • 客户端要调用远程主机上的方法
  • 经过Stub的代理,请求杯编码通过网络传输给Skeleton
  • Skeleton收到请求,转换成服务端可以识别的请求
  • 发送请求到服务的
  • 服务端处理后结构,发送到Skeleton进行编码
  • Stub收到后解码结果
  • 客户端获得远程方法调用的结果

注册远程对象

1
2
3
4
RemoteInterface remoteObj2 = new RemoteImpl();// 创建远程对象
Context namingContext = new InitialContext();// 初始化命名内容
LocateRegistry.createRegistry(8892);// 在本地主机上创建和导出注册表实例,并在指定的端口上接受请求
namingContext.rebind("rmi://localhost:8892/RemoteObj2", remoteObj2);// 注册对象,即把对象与一个名字绑定。

只要继承了java.rmi.Remote接口,就可以成为存在于服务器的远程对象

远程对象必须实现java.rmi.server.UniCastRemoteObject类,该类的构造函数中将生成stub和skeleton, 这样才能保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为Stub( 存根), 而服务器端本身已存在的远程对象则称之为Skeleton(骨架) 。

获取注册中心

创建时获取 createRegistry

  • -w1067
    -w1067
    • 第一种只要传port,表示和注册中心申请使用的端口,后面再绑定value上去以便客户端请求
    • 第二张传port外,还需要传递RMIClientSocketFactory以及RMIServerSocketFactory对象。
    • 两个方法最终获取到的都是RegistryImpl对象,对于攻击者的我们关系并不大

对第一种方法的分析

1
2
3
public static Registry createRegistry(int var0) throws RemoteException {
return new RegistryImpl(var0);
}

var0便储存着我们要传递的port

跟进

1
2
3
4
public RegistryImpl(int var1) throws RemoteException {
LiveRef var2 = new LiveRef(id, var1);
this.setup(new UnicastServerRef(var2));
}

LiveRef封装了ip和端口

远程获取 getRegistry

JDK高版本绕过

高版本做的防御

反序列化前判断类型

image-20221027202856361
image-20221027202856361

dgc反序列化也做了过滤

image-20221027202941346
image-20221027202941346

远程对象反序列化,需要知道具体参数类型

攻击思路

服务端发起对客户端的请求,使用dgc向客户端发起请求,通过利用链调用dgc的dirty方法来给客户端发请求

  • 标题: RMI学习
  • 作者: Sl0th
  • 创建于 : 2022-10-01 23:31:00
  • 更新于 : 2024-11-11 18:23:06
  • 链接: http://sl0th.top/2022/10/01/RMI学习/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论