反序列化总纲
之前学过的RMI已经丢了,现在重新做笔记找回,如有不当之处,还请指明。
0x01 RPC首先看一下最基础的解释,Java RMI是实现了RPC的Java API。那么看RMI之前,想先看看RPC
1.基础解释RPC,Remote Procedure Call 远程过程调用。就是通过一种方式去远程的调用另外一个服务上的方法或者功能。
2.RPC需要解决的问题- 解决分布式系统中,服务之间的调用
- 远程调用像本地调用一样方便
1、A调用远程B
2、将调用的信息以序列化的方式进行发送
3、B接受信息,然后反序列化
4、将内容执行,然后以序列化的方式返回结果
5、A反序列化拿到结果
RMI就是Java中对RPC的一种实现,对其进行了封装
在RMI中使用的是jrmp协议:JRMP是的Java技术协议的具体对象为希望和远程引用。JRMP只能是一个Java特有的,基于流的协议。相对于的RMI - IIOP的 ,该协议JRMP只能是一个对象的Java到Java的远程调用,这使得它依赖语言,意思是客户端和服务器必须使用Java。
1.Demo首先创建一个远程调用目标的接口:
package server;
import java.io.IOException;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface HelloRegistryFacade extends Remote {
String helloWorld(String name) throws IOException;
}
实现这个接口:
package server;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class HelloRegistryFacadeImpl extends UnicastRemoteObject implements HelloRegistryFacade{
public HelloRegistryFacadeImpl() throws RemoteException {
super();
}
@Override
public String helloWorld(String name) throws IOException {
Runtime.getRuntime().exec("calc");
return name;
}
}
客户端:
package server;
import java.io.IOException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RegistryClient {
public static void main(String[] args) {
try {
Registry registry = LocateRegistry.getRegistry(1099);
HelloRegistryFacade hello = (HelloRegistryFacade) registry.lookup("HelloRegistry");
String response = hello.helloWorld("zhangsan");
System.out.println("=======> " + response + " <=======");
} catch (NotBoundException | RemoteException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务端:
package server;
import java.rmi.AccessException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RegistryService {
public static void main(String[] args) {
try {
// 本地主机上的远程对象注册表Registry的实例,默认端口1099
Registry registry = LocateRegistry.createRegistry(1099);
// 创建一个远程对象
HelloRegistryFacade hello = new HelloRegistryFacadeImpl();
// 把远程对象注册到RMI注册服务器上,并命名为HelloRegistry
registry.rebind("HelloRegistry", hello);
System.out.println("======= 启动RMI服务成功! =======");
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
先运行客户端,然后再运行服务端:
- Java SecurityManager的限制,默认是不允许远程加载的
- 属性 java.rmi.server.useCodebaseonly 的值必需为false。但是从JDK 6u45、7u21开始,java.rmi.server.useCodebaseonly 的默认值就是true
在限制下的时候,需要开启配置:demo如下
package server1;
import javax.naming.InitialContext;
public class RMIClient1 {
public static void main(String[] args) throws Exception {
System.setProperty("java.rmi.server.useCodebaseOnly", "false");
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
String url = "rmi://127.0.0.1:666/Exploit";
InitialContext initialContext = new InitialContext();
initialContext.lookup(url);
}
}
测试结果:
- https://paper.seebug.org/1091/#rmi
- https://baike.baidu.com/item/jrmp/6099442?fr=aladdin
- https://www.jianshu.com/p/de85fad05dcb



