RMI简介
Java RMI,即 远程方法调用(Remote Method Invocation),一种用于实现远程过程调用(RPC)(Remote procedure call)的Java API, 能直接传输序列化后的Java对象和分布式垃圾收集。它的实现依赖于Java虚拟机(JVM),因此它仅支持从一个JVM到另一个JVM的调用。
Rmi的调用
服务端
import java.rmi.Naming;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
public class RmiRegistry {
public interface IRemoteHello extends Remote{
public String hello() throws RemoteException;
}
public class RemoteHelloWorld extends UnicastRemoteObject implements
IRemoteHello {
protected RemoteHelloWorld() throws RemoteException {
super();
}
public String hello() throws RemoteException {
System.out.println("call from");
return "Hello world";
}
}
private void start() throws Exception {
RemoteHelloWorld h = new RemoteHelloWorld();
LocateRegistry.createRegistry(1099);
Naming.rebind("rmi://127.0.0.1:1099/Hello", h);
}
public static void main(String[] args) throws Exception{
new RmiRegistry().start();
}
}
客户端
import java.rmi.Naming;
public class TrainMain {
public static void main(String[] args) throws Exception {
RmiRegistry.IRemoteHello hello = (RmiRegistry.IRemoteHello)
Naming.lookup("rmi://127.0.0.1:1099/Hello");
String ret = hello.hello();
System.out.println( ret);
}
}
成功从服务端取回hello world。
整个实现流程如下,客户端连接Registry,并在其中寻找Name是Hello的对象,这个对应数据 流中的Call消息;然后Registry返回⼀个序列化的数据,这个就是找到的Name=Hello的对象,这个对应 数据流中的ReturnData消息;客户端反序列化该对象,发现该对象是⼀个远程对象,地址在10.91.214.135:7532 ,于是再与这个地址建⽴TCP连接;在这个新的连接中,才执⾏真正远程⽅法调⽤,也就是 hello() 。
RMI的参与者
RMI Registry
RMI Server
RMI Client
攻击RMI Registry
RMI Registry是一个远程对象管理的地方,可以理解为一个远程对象的“后台”。我们可以尝试直
接访问“后台”功能。
注:远程访问RMI Registry时,只能通过list和lookup方法访问。rebind、bind、unbind方法只有来源地址是localhost时才能调用
只要目标服务器上存在一些危险方法,我们通过RMI就可以对其进行调用。
RMI动态类加载
当本地CLASSPATH中无法找到相应的类时,会在指定的codebase里加载class。codebase可以在系统属性java.rmi.server.codebase设置其URL。如果codebase的URL可控,那么我们就可以载入任意的class或jar文件。
RMI利用codebase执行任意代码
需要满足条件:
1.安装并配置了SecurityManager
2.Java版本低于7u21、6u45,或者设置了 java.rmi.server.useCodebaseOnly=false
注:在 java.rmi.server.useCodebaseOnly 配置为 true 的情况下,Java虚拟机将只信任预先配置好的
codebase ,不再支持从RMI请求中获取。
链接:https://www.jianshu.com/p/de85fad05dcb
https://www.anquanke.com/post/id/199481