From c4dd959069f2c920b1a4cdf65659f8ec137fc0e3 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Fri, 29 Sep 2023 18:37:48 +0200 Subject: [PATCH 01/60] Add support for dynamic socket factory classes remote-method-guesser now attempts to create missing socket factory classes dynamically. --- .../qtc/rmg/internal/CodebaseCollector.java | 44 +++++++++++++---- src/de/qtc/rmg/internal/RMGOption.java | 4 +- .../rmg/networking/RMIRegistryEndpoint.java | 47 ++++++++++++++----- src/de/qtc/rmg/operations/Operation.java | 8 ++++ src/de/qtc/rmg/utils/RMGUtils.java | 39 +++++++++++++++ 5 files changed, 119 insertions(+), 23 deletions(-) diff --git a/src/de/qtc/rmg/internal/CodebaseCollector.java b/src/de/qtc/rmg/internal/CodebaseCollector.java index e3806a0..f5fc1dc 100644 --- a/src/de/qtc/rmg/internal/CodebaseCollector.java +++ b/src/de/qtc/rmg/internal/CodebaseCollector.java @@ -49,6 +49,15 @@ * serialVersionUID. Since changing the serialVersionUID of an already existing class is not possible, we instead * create a new class where the full qualified class name is prefixed with an underscore. * + * From remote-method-guesser v4.5.0, this class has another purpose of handling custom socket factories. When the + * server exposes RMI objects with custom socket factory classes, this usually causes a ClassNotFound error, as + * we do not have the associated implementations on the client side. In this case, remote-method-guesser now attempts + * to create the socket factory class dynamically. Since the implementation is still unknown, it simply clones the + * default socket factory class TrustAllSocketFactory. This works surprisingly often, as most custom socket factory + * classes use simple socket implementations under the hood. This dynamic class creation is done for all classes that + * are unknown and contain "SocketFactory" within their class name or end with "Factory" or "SF". The user can also + * specify other patterns using the --socket-factory option. + * * Summarized: * * 1. Extract server specified codebases and store them within a HashMap for later use @@ -78,31 +87,48 @@ public class CodebaseCollector extends RMIClassLoaderSpi { public Class loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException { Class resolvedClass = null; + long serialVersionUID = RMGOption.SERIAL_VERSION_UID.getValue(); addCodebase(codebase, name); codebase = null; + if (serialVersionUIDMap.containsKey(name)) + { + serialVersionUID = serialVersionUIDMap.get(name); + name = "_" + name; + } + try { if (name.endsWith("_Stub")) { - long serialVersionUID = RMGOption.SERIAL_VERSION_UID.getValue(); + RMGUtils.makeLegacyStub(name, serialVersionUID); + } + + else if (name.equals("sun.rmi.server.ActivatableRef")) + { + RMGUtils.makeActivatableRef(); + } - if (serialVersionUIDMap.containsKey(name)) + else if (!RMGOption.SOCKET_FACTORY.isNull()) + { + if (name.contains(RMGOption.SOCKET_FACTORY.getValue())) { - serialVersionUID = serialVersionUIDMap.get(name); - name = "_" + name; + RMGUtils.makeSocketFactory(name, serialVersionUID); } - - RMGUtils.makeLegacyStub(name, serialVersionUID); } - if (name.equals("sun.rmi.server.ActivatableRef")) - RMGUtils.makeActivatableRef(); + else if (name.contains("SocketFactory") || name.endsWith("Factory") || name.endsWith("SF")) + { + RMGUtils.makeSocketFactory(name, serialVersionUID); + } resolvedClass = originalLoader.loadClass(codebase, name, defaultLoader); - } catch (CannotCompileException | NotFoundException e) { + } + + catch (CannotCompileException | NotFoundException e) + { ExceptionHandler.internalError("loadClass", "Unable to compile unknown stub class."); } diff --git a/src/de/qtc/rmg/internal/RMGOption.java b/src/de/qtc/rmg/internal/RMGOption.java index 811032e..70a911b 100644 --- a/src/de/qtc/rmg/internal/RMGOption.java +++ b/src/de/qtc/rmg/internal/RMGOption.java @@ -104,8 +104,8 @@ public enum RMGOption { DGC_METHOD("--dgc-method", "method to use for dgc operations", Arguments.store(), RMGOptionGroup.ACTION, "method"), REG_METHOD("--registry-method", "method to use for registry operations", Arguments.store(), RMGOptionGroup.ACTION, "method"), SERIAL_VERSION_UID("--serial-version-uid", "serialVersionUID to use for RMI stubs", Arguments.store(), RMGOptionGroup.ACTION, "uid"), - PAYLOAD_SERIAL_VERSION_UID("--payload-serial-version-uid", "serialVersionUID to use for payload classes", Arguments.store(), RMGOptionGroup.ACTION, "uid"); - + PAYLOAD_SERIAL_VERSION_UID("--payload-serial-version-uid", "serialVersionUID to use for payload classes", Arguments.store(), RMGOptionGroup.ACTION, "uid"), + SOCKET_FACTORY("--socket-factory", "dynamically create a socket factory class with the specified name", Arguments.store(), RMGOptionGroup.ACTION, "classname"); public final String name; public final String description; diff --git a/src/de/qtc/rmg/networking/RMIRegistryEndpoint.java b/src/de/qtc/rmg/networking/RMIRegistryEndpoint.java index 96dbd59..0934d40 100644 --- a/src/de/qtc/rmg/networking/RMIRegistryEndpoint.java +++ b/src/de/qtc/rmg/networking/RMIRegistryEndpoint.java @@ -159,39 +159,54 @@ public RemoteObjectWrapper lookup(String boundName) throws IllegalArgumentExcept { Remote remoteObject = remoteObjectCache.get(boundName); - if( remoteObject == null ) { - - try { + if (remoteObject == null) + { + try + { remoteObject = rmiRegistry.lookup(boundName); remoteObjectCache.put(boundName, remoteObject); + } - } catch( java.rmi.ConnectIOException e ) { + catch (java.rmi.ConnectIOException e) + { ExceptionHandler.connectIOException(e, "lookup"); + } - } catch( java.rmi.ConnectException e ) { + catch (java.rmi.ConnectException e) + { ExceptionHandler.connectException(e, "lookup"); + } - } catch( java.rmi.UnknownHostException e ) { + catch (java.rmi.UnknownHostException e) + { ExceptionHandler.unknownHost(e, host, true); + } - } catch( java.rmi.NoSuchObjectException e ) { + catch (java.rmi.NoSuchObjectException e) + { ExceptionHandler.noSuchObjectException(e, "registry", true); + } - } catch( java.rmi.NotBoundException e ) { + catch (java.rmi.NotBoundException e) + { ExceptionHandler.notBoundException(e, boundName); + } - } catch( Exception e ) { - + catch( Exception e ) + { Throwable cause = ExceptionHandler.getCause(e); if (e instanceof UnmarshalException && cause instanceof InvalidClassException) { InvalidClassException invalidClassException = (InvalidClassException)cause; - if (stopLookupLoop || ! cause.getMessage().contains("serialVersionUID")) + if (stopLookupLoop || !cause.getMessage().contains("serialVersionUID")) + { ExceptionHandler.invalidClassException(invalidClassException); + } - try { + try + { String className = RMGUtils.getClass(invalidClassException); long serialVersionUID = RMGUtils.getSerialVersionUID(invalidClassException); @@ -208,16 +223,24 @@ public RemoteObjectWrapper lookup(String boundName) throws IllegalArgumentExcept } else if (e instanceof UnmarshalException && e.getMessage().contains("Transport return code invalid")) + { throw (UnmarshalException)e; + } if( cause instanceof ClassNotFoundException ) + { ExceptionHandler.lookupClassNotFoundException(e, cause.getMessage()); + } else if( cause instanceof SSRFException ) + { SSRFSocket.printContent(host, port); + } else + { ExceptionHandler.unexpectedException(e, "lookup", "call", true); + } } } diff --git a/src/de/qtc/rmg/operations/Operation.java b/src/de/qtc/rmg/operations/Operation.java index 9a1f510..c7f0b78 100644 --- a/src/de/qtc/rmg/operations/Operation.java +++ b/src/de/qtc/rmg/operations/Operation.java @@ -44,6 +44,7 @@ public enum Operation { RMGOption.BIND_GADGET_NAME, RMGOption.BIND_GADGET_CMD, RMGOption.YSO, + RMGOption.SOCKET_FACTORY, }), CALL("dispatchCall", "", "Regularly calls a method with the specified arguments", new RMGOption[] { @@ -69,6 +70,7 @@ public enum Operation { RMGOption.CALL_ARGUMENTS, RMGOption.FORCE_ACTIVATION, RMGOption.SERIAL_VERSION_UID, + RMGOption.SOCKET_FACTORY, }), CODEBASE("dispatchCodebase", " ", "Perform remote class loading attacks", new RMGOption[] { @@ -96,6 +98,7 @@ public enum Operation { RMGOption.FORCE_ACTIVATION, RMGOption.SERIAL_VERSION_UID, RMGOption.PAYLOAD_SERIAL_VERSION_UID, + RMGOption.SOCKET_FACTORY, }), ENUM("dispatchEnum", "[scan-action ...]", "Enumerate common vulnerabilities on Java RMI endpoints", new RMGOption[] { @@ -121,6 +124,7 @@ public enum Operation { RMGOption.ACTIVATION, RMGOption.FORCE_ACTIVATION, RMGOption.SERIAL_VERSION_UID, + RMGOption.SOCKET_FACTORY, }), GUESS("dispatchGuess", "", "Guess methods on bound names", new RMGOption[] { @@ -150,6 +154,7 @@ public enum Operation { RMGOption.NO_PROGRESS, RMGOption.FORCE_ACTIVATION, RMGOption.SERIAL_VERSION_UID, + RMGOption.SOCKET_FACTORY, }), KNOWN("dispatchKnown", "", "Display details of known remote objects", new RMGOption[] { @@ -201,6 +206,7 @@ public enum Operation { RMGOption.BIND_GADGET_NAME, RMGOption.BIND_GADGET_CMD, RMGOption.YSO, + RMGOption.SOCKET_FACTORY, }), ROGUEJMX("dispatchRogueJMX", "[forward-host]", "Creates a rogue JMX listener (collect credentials)", new RMGOption[] { @@ -258,6 +264,7 @@ public enum Operation { RMGOption.YSO, RMGOption.FORCE_ACTIVATION, RMGOption.SERIAL_VERSION_UID, + RMGOption.SOCKET_FACTORY, }), UNBIND("dispatchUnbind", "", "Removes the specified bound name from the registry", new RMGOption[] { @@ -276,6 +283,7 @@ public enum Operation { RMGOption.SSRF_STREAM_PROTOCOL, RMGOption.BIND_BOUND_NAME, RMGOption.BIND_BYPASS, + RMGOption.SOCKET_FACTORY, }); private Method method; diff --git a/src/de/qtc/rmg/utils/RMGUtils.java b/src/de/qtc/rmg/utils/RMGUtils.java index 453eb78..8f107b9 100644 --- a/src/de/qtc/rmg/utils/RMGUtils.java +++ b/src/de/qtc/rmg/utils/RMGUtils.java @@ -27,6 +27,7 @@ import de.qtc.rmg.internal.ExceptionHandler; import de.qtc.rmg.internal.MethodArguments; import de.qtc.rmg.internal.MethodCandidate; +import de.qtc.rmg.internal.RMGOption; import de.qtc.rmg.internal.RMIComponent; import de.qtc.rmg.io.Logger; import de.qtc.rmg.io.MaliciousOutputStream; @@ -212,6 +213,44 @@ public static Class makeActivatableRef() throws CannotCompileException return null; } + /** + * Dynamically create a socket factory class that implements RMIClientSocketFactory. This function is used when + * the RMI server uses a custom socket factory class. In this case, rmg attempts to connect with it's default + * TrustAllSocketFactory, which works if the custom socket factory provided by the server is not too different. + * + * To achieve this, rmg just clones TrustAllSocketFactory and assigns it a new name. As in the case of Stub + * classes with unusual serialVersionUIDs, the serialVersionUID is determined error based. The factory is first + * created using a default serialVersionUID. This should cause an exception revealing the actual serialVersionUID. + * This is then used to recreate the class. + * + * Check the CodebaseCollector class documentation for more information. + * + * @return socket factory class that implements RMIClientSocketFactory + * @throws CannotCompileException + */ + public static Class makeSocketFactory(String className, long serialVersionUID) throws CannotCompileException + { + try + { + return Class.forName(className); + } + + catch (ClassNotFoundException e) {} + + CtClass ctClass = null; + + try + { + ctClass = pool.getAndRename("de.qtc.rmg.networking.TrustAllSocketFactory", className); + ctClass.addInterface(serializable); + addSerialVersionUID(ctClass, serialVersionUID); + } + + catch (NotFoundException e) {} + + return ctClass.toClass(); + } + /** * Creates a method from a signature string. Methods need to be assigned to a class, therefore the static * dummyClass is used that is created during the initialization of RMGUtils. The class relationship of the From ab7f099ae27525d88b2e2e2375f3888ee3f29c05 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Fri, 29 Sep 2023 18:40:59 +0200 Subject: [PATCH 02/60] Add author to manifest --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index 709569f..eb12982 100644 --- a/pom.xml +++ b/pom.xml @@ -85,6 +85,9 @@ true + + Tobias Neitzel (@qtc_de) + java.base/java.io java.base/java.lang From 01da3beca6e7339c39be31aa00fab58467f0b083 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Fri, 29 Sep 2023 19:00:42 +0200 Subject: [PATCH 03/60] Add documentation for dynamic socket factories --- CHANGELOG.md | 7 ++++ docs/rmg/README.md | 1 + docs/rmg/dynamic-socket-factories.md | 60 ++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 docs/rmg/dynamic-socket-factories.md diff --git a/CHANGELOG.md b/CHANGELOG.md index e6bd220..4790346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.5.0] - MMM DD, 2023 + +### Added + +* Add support for dynamically created socket factory classes ([docs](/docs/rmg/dynamic-socket-factories.md)) + + ## [4.4.1] - Jun 22, 2023 ### Added diff --git a/docs/rmg/README.md b/docs/rmg/README.md index 6e14b09..87b0a01 100644 --- a/docs/rmg/README.md +++ b/docs/rmg/README.md @@ -6,6 +6,7 @@ In this folder you can find more detailed documentation on *remote-method-guesse * [Actions](./actions.md) * [Activation System](./activation-system.md) +* [Dynamic Socket Factory Creation](./dynamic-socket-factories.md) * [Media](./media.md) * [Method-Guessing](./method-guessing.md) * [Plugin System](./plugin-system.md) diff --git a/docs/rmg/dynamic-socket-factories.md b/docs/rmg/dynamic-socket-factories.md new file mode 100644 index 0000000..d692a57 --- /dev/null +++ b/docs/rmg/dynamic-socket-factories.md @@ -0,0 +1,60 @@ +### Dynamic Socket Factories + +---- + +With version *v4.5.0* support for dynamically created socket factories +were added to *remote-method-guesser*. This basically means the following: + +*RMI* servers can register a custom socket factory that has to be used +to connect to their exposed remote objects. If this is done by an *RMI* +server, you usually see an error message like the following when you +attempt to connect with *remote-method-guesser*: + +> The class custom.socket.Factory could not be resolved within your class path + +With this error message, *Java* simply complains that it can't find the +implementation of `custom.socket.Factory`, which is required to establish +a connection to the *RMI* server. + +In some cases, this means that you cannot further enumerate the *RMI* +service, but often times it is possible anyways. Custom socket factory +classes often still rely on the default socket implementations. This means +that at the end of the day, the socket factory still outputs a regular +socket, as it can also be obtained from *Java's* default socket *APIs*. + +From version *v4.5.0* on, *remote-method-guesser* attempts to detect +errors caused by missing socket factory classes. In these cases, *rmg* +attempts to create the class dynamically. Since the actual implementation +is unknown, the dynamically created socket factory is simply the default +socket factory used by *remote-method-guesser*. Surprisingly often, this +is sufficient to connect. + +But why people implement custom socket factories when you can also connect +to them with the default one? Well, most of the time developers only add some +small behavior changes for their sockets, like e.g. a specific socket timeout +or trust for a self signed certificate. As these changes do not matter for an +successful connection (as *remote-method-guesser* trusts all certificates anyway) +dynamic socket factory creation works in these cases. + +However, some developers like it special. You could for example create a socket +factory that applies *XOR* encoding to all bytes before they are transmitted. +In such a case, dynamic socket factory creation will not work, as the default +sockets created by *remote-method-guesser* will not apply the *XOR* encoding +and the server side socket will not understand our data. + + +### User Options + +---- + +By default, *remote-method-guesser* attempts to create a socket factory +for classes that contain the string `SocketFactory` or end with `Factory` +or `SF`. If you want to dynamically create a socket factory for a different +class, you can specify the class name using the `--socket-factory` option. +Each class that cannot be found locally will then be checked whether it contains +the specified pattern and a socket factory will be created if this is the case. + +You can also use the `--socket-factory` option to prevent the dynamic creation +of socket factories. When a pattern was specified, the default patterns are not +checked. Therefore, using something like `--socket-factory nobody.uses.a.class.name.like.this` +will prevent socket factory creation. From d3970059dd95748b781acc28a2a8556248bb86a3 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 3 Oct 2023 08:09:29 +0200 Subject: [PATCH 04/60] Improve dynamic socket factory creation --- .../qtc/rmg/internal/CodebaseCollector.java | 15 ++-- src/de/qtc/rmg/internal/RMGOption.java | 5 +- .../rmg/networking/LoopbackSocketFactory.java | 78 ++++++++++-------- .../networking/LoopbackSslSocketFactory.java | 81 ++++++++++++------- src/de/qtc/rmg/operations/Operation.java | 16 ++++ src/de/qtc/rmg/plugin/DefaultProvider.java | 18 ++--- src/de/qtc/rmg/utils/RMGUtils.java | 40 ++++++--- 7 files changed, 161 insertions(+), 92 deletions(-) diff --git a/src/de/qtc/rmg/internal/CodebaseCollector.java b/src/de/qtc/rmg/internal/CodebaseCollector.java index f5fc1dc..c02b9a1 100644 --- a/src/de/qtc/rmg/internal/CodebaseCollector.java +++ b/src/de/qtc/rmg/internal/CodebaseCollector.java @@ -53,9 +53,10 @@ * server exposes RMI objects with custom socket factory classes, this usually causes a ClassNotFound error, as * we do not have the associated implementations on the client side. In this case, remote-method-guesser now attempts * to create the socket factory class dynamically. Since the implementation is still unknown, it simply clones the - * default socket factory class TrustAllSocketFactory. This works surprisingly often, as most custom socket factory - * classes use simple socket implementations under the hood. This dynamic class creation is done for all classes that - * are unknown and contain "SocketFactory" within their class name or end with "Factory" or "SF". The user can also + * default socket factory class LoopbackSslSocketFactory or LoopbackSocketFactory depending on the values for the + * --ssl, --socket-factory-ssl and --socket-factory-plain options. This works surprisingly often, as most custom socket + * factory classes use simple socket implementations under the hood. This dynamic class creation is done for all classes + * that are unknown and contain "SocketFactory" within their class name or end with "Factory" or "SF". The user can also * specify other patterns using the --socket-factory option. * * Summarized: @@ -67,8 +68,8 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class CodebaseCollector extends RMIClassLoaderSpi { - +public class CodebaseCollector extends RMIClassLoaderSpi +{ private static HashMap serialVersionUIDMap = new HashMap(); private static HashMap> codebases = new HashMap>(); private static RMIClassLoaderSpi originalLoader = RMIClassLoader.getDefaultProviderInstance(); @@ -98,8 +99,8 @@ public Class loadClass(String codebase, String name, ClassLoader defaultLoade name = "_" + name; } - try { - + try + { if (name.endsWith("_Stub")) { RMGUtils.makeLegacyStub(name, serialVersionUID); diff --git a/src/de/qtc/rmg/internal/RMGOption.java b/src/de/qtc/rmg/internal/RMGOption.java index 70a911b..9a5e33b 100644 --- a/src/de/qtc/rmg/internal/RMGOption.java +++ b/src/de/qtc/rmg/internal/RMGOption.java @@ -105,7 +105,10 @@ public enum RMGOption { REG_METHOD("--registry-method", "method to use for registry operations", Arguments.store(), RMGOptionGroup.ACTION, "method"), SERIAL_VERSION_UID("--serial-version-uid", "serialVersionUID to use for RMI stubs", Arguments.store(), RMGOptionGroup.ACTION, "uid"), PAYLOAD_SERIAL_VERSION_UID("--payload-serial-version-uid", "serialVersionUID to use for payload classes", Arguments.store(), RMGOptionGroup.ACTION, "uid"), - SOCKET_FACTORY("--socket-factory", "dynamically create a socket factory class with the specified name", Arguments.store(), RMGOptionGroup.ACTION, "classname"); + + SOCKET_FACTORY_PLAIN("--socket-factory-plain", "enforce plaintext connections from dynamically created socket factories", Arguments.storeTrue(), RMGOptionGroup.CONNECTION), + SOCKET_FACTORY_SSL("--socket-factory-ssl", "enforce SSL connections from dynamically created socket factories", Arguments.storeTrue(), RMGOptionGroup.CONNECTION), + SOCKET_FACTORY("--socket-factory", "dynamically create a socket factory class with the specified name", Arguments.store(), RMGOptionGroup.CONNECTION, "classname"); public final String name; public final String description; diff --git a/src/de/qtc/rmg/networking/LoopbackSocketFactory.java b/src/de/qtc/rmg/networking/LoopbackSocketFactory.java index 7c6c8f1..f59496b 100644 --- a/src/de/qtc/rmg/networking/LoopbackSocketFactory.java +++ b/src/de/qtc/rmg/networking/LoopbackSocketFactory.java @@ -19,7 +19,7 @@ * objects are open, it is still possible to communicate with them. * * The LoopbackSocketFactory class extends the default RMISocketFactory and can be set - * as a replacement. Within its constructor, it requires to specify a host that is the + * as a replacement. The class uses remote-method-guessers global option access to obtain * actual target of the RMI communication (usually the registry host). All other RMI * connections are then expected to target the same host. This is implemented by overwriting * the createSocket function. If the specified host value does not match the expected value, @@ -32,30 +32,15 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class LoopbackSocketFactory extends RMISocketFactory { - - private String host; - private RMISocketFactory fac; - private boolean printInfo = true; - private boolean followRedirect = false; - - /** - * Creates a new LoopbackSocketFactory. - * - * @param host remote host that is expected to get all further RMI connections - * @param fac original socket factory to create sockets from - * @param followRedirect if true, connections are not redirected to the expected host - */ - public LoopbackSocketFactory(String host, RMISocketFactory fac, boolean followRedirect) - { - this.host = host; - this.fac = fac; - this.followRedirect= followRedirect; - } +public class LoopbackSocketFactory extends RMISocketFactory +{ + private transient RMISocketFactory fax; + private transient boolean printInfo = true; + @Override public ServerSocket createServerSocket(int port) throws IOException { - return fac.createServerSocket(port); + return getFax().createServerSocket(port); } /** @@ -67,41 +52,64 @@ public Socket createSocket(String host, int port) throws IOException { Socket sock = null; - if(!this.host.equals(host)) { - - if( printInfo && RMGOption.GLOBAL_VERBOSE.getBool() ) { + if (!RMGOption.TARGET_HOST.getValue().equals(host)) + { + if (printInfo && RMGOption.GLOBAL_VERBOSE.getBool()) + { Logger.printInfoBox(); Logger.printlnMixedBlue("RMI object tries to connect to different remote host:", host); } - if( this.followRedirect ) { - if( printInfo && RMGOption.GLOBAL_VERBOSE.getBool() ) + if (RMGOption.CONN_FOLLOW.getBool()) + { + if ( printInfo && RMGOption.GLOBAL_VERBOSE.getBool()) + { Logger.println("Following redirect to new target..."); + } + } - } else { - - host = this.host; + else + { + host = RMGOption.TARGET_HOST.getValue(); - if( printInfo && RMGOption.GLOBAL_VERBOSE.getBool() ) { + if (printInfo && RMGOption.GLOBAL_VERBOSE.getBool()) + { Logger.printlnMixedBlue("Redirecting the connection back to", host); Logger.printlnMixedYellow("You can use", "--follow", "to prevent this."); } } - if( printInfo && RMGOption.GLOBAL_VERBOSE.getBool() ) { + if (printInfo && RMGOption.GLOBAL_VERBOSE.getBool()) + { Logger.decreaseIndent(); } this.printInfo = false; } - try { - sock = fac.createSocket(host, port); + try + { + sock = getFax().createSocket(host, port); + } - } catch( UnknownHostException e ) { + catch( UnknownHostException e ) + { ExceptionHandler.unknownHost(e, host, true); } return sock; } + + /** + * Obtain the RMISocketFactory to create sockets from. This is always the default RMISocketFactory. + */ + private RMISocketFactory getFax() + { + if (fax == null) + { + fax = RMISocketFactory.getDefaultSocketFactory(); + } + + return fax; + } } diff --git a/src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java b/src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java index 94fb397..8e75468 100644 --- a/src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java +++ b/src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java @@ -4,6 +4,7 @@ import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; +import java.rmi.server.RMIClientSocketFactory; import javax.net.ssl.SSLSocketFactory; @@ -20,7 +21,7 @@ * objects are open, it is still possible to communicate with them. * * The LoopbackSslSocketFactory class extends the default SSLSocketFactory and can be set - * as a replacement. The class uses static variables to define configuration parameters and + * as a replacement. The class uses remote-method-guessers global option access to obtain * the actual target of the RMI communication (usually the registry host). All other RMI * connections are then expected to target the same host. This is implemented by overwriting * the createSocket function. If the specified host value does not match the expected value, @@ -28,17 +29,15 @@ * * During a redirect, the class prints a warning to the user to inform about the * redirection. If redirection is a desired behavior, the user can use the --follow option - * with rmg, which sets the followRedirect attribute to true. In these cases, a warning - * is still printed, but the connection goes to the specified target. + * with remote-method-guesser, which sets the followRedirect attribute to true. In these + * cases, a warning is still printed, but the connection goes to the specified target. * * @author Tobias Neitzel (@qtc_de) */ -public class LoopbackSslSocketFactory extends SSLSocketFactory { - - public static String host = ""; - public static SSLSocketFactory fac = null; - public static boolean printInfo = true; - public static boolean followRedirect = false; +public class LoopbackSslSocketFactory extends SSLSocketFactory implements RMIClientSocketFactory +{ + public transient SSLSocketFactory fax; + public transient boolean printInfo = true; /** * Overwrites the default implementation of createSocket. Checks whether host matches the expected @@ -50,39 +49,49 @@ public Socket createSocket(String target, int port) throws IOException { Socket sock = null; - if(!host.equals(target)) { + if(!RMGOption.TARGET_HOST.getValue().equals(target)) { - if( printInfo && RMGOption.GLOBAL_VERBOSE.getBool() ) { + if (printInfo && RMGOption.GLOBAL_VERBOSE.getBool()) + { Logger.printInfoBox(); Logger.printlnMixedBlue("RMI object tries to connect to different remote host:", target); } - if( followRedirect ) { - if( printInfo && RMGOption.GLOBAL_VERBOSE.getBool() ) + if (RMGOption.CONN_FOLLOW.getBool()) + { + if (printInfo && RMGOption.GLOBAL_VERBOSE.getBool()) + { Logger.println("Following SSL redirect to new target..."); + } + } - } else { - - target = host; + else + { + target = RMGOption.TARGET_HOST.getValue(); - if( printInfo && RMGOption.GLOBAL_VERBOSE.getBool() ) { - Logger.printlnMixedBlue("Redirecting the SSL connection back to", host); + if (printInfo && RMGOption.GLOBAL_VERBOSE.getBool()) + { + Logger.printlnMixedBlue("Redirecting the SSL connection back to", target); Logger.printlnMixedYellow("You can use", "--follow", "to prevent this."); } } - if( printInfo && RMGOption.GLOBAL_VERBOSE.getBool() ) { + if (printInfo && RMGOption.GLOBAL_VERBOSE.getBool()) + { Logger.decreaseIndent(); } printInfo = false; } - try { - sock = fac.createSocket(host, port); + try + { + sock = getFax().createSocket(target, port); + } - } catch( UnknownHostException e ) { - ExceptionHandler.unknownHost(e, host, true); + catch (UnknownHostException e) + { + ExceptionHandler.unknownHost(e, target, true); } return sock; @@ -91,36 +100,50 @@ public Socket createSocket(String target, int port) throws IOException @Override public Socket createSocket(Socket arg0, String arg1, int arg2, boolean arg3) throws IOException { - return fac.createSocket(arg0, arg1, arg2, arg3); + return getFax().createSocket(arg0, arg1, arg2, arg3); } @Override public String[] getDefaultCipherSuites() { - return fac.getDefaultCipherSuites(); + return getFax().getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { - return fac.getSupportedCipherSuites(); + return getFax().getSupportedCipherSuites(); } @Override public Socket createSocket(InetAddress arg0, int arg1) throws IOException { - return fac.createSocket(arg0, arg1); + return getFax().createSocket(arg0, arg1); } @Override public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException, UnknownHostException { - return fac.createSocket(arg0, arg1, arg2, arg3); + return getFax().createSocket(arg0, arg1, arg2, arg3); } @Override public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException { - return fac.createSocket(arg0, arg1, arg2, arg3); + return getFax().createSocket(arg0, arg1, arg2, arg3); + } + + /** + * Obtain the SSLSocketFactory to create sockets from. This is always the underlying SSLSocketFactory + * from the TrustAllSocketFactory. + */ + private SSLSocketFactory getFax() + { + if (fax == null) + { + fax = new TrustAllSocketFactory().getSSLSocketFactory(); + } + + return fax; } } diff --git a/src/de/qtc/rmg/operations/Operation.java b/src/de/qtc/rmg/operations/Operation.java index c7f0b78..6fe043d 100644 --- a/src/de/qtc/rmg/operations/Operation.java +++ b/src/de/qtc/rmg/operations/Operation.java @@ -45,6 +45,8 @@ public enum Operation { RMGOption.BIND_GADGET_CMD, RMGOption.YSO, RMGOption.SOCKET_FACTORY, + RMGOption.SOCKET_FACTORY_SSL, + RMGOption.SOCKET_FACTORY_PLAIN, }), CALL("dispatchCall", "", "Regularly calls a method with the specified arguments", new RMGOption[] { @@ -71,6 +73,8 @@ public enum Operation { RMGOption.FORCE_ACTIVATION, RMGOption.SERIAL_VERSION_UID, RMGOption.SOCKET_FACTORY, + RMGOption.SOCKET_FACTORY_SSL, + RMGOption.SOCKET_FACTORY_PLAIN, }), CODEBASE("dispatchCodebase", " ", "Perform remote class loading attacks", new RMGOption[] { @@ -99,6 +103,8 @@ public enum Operation { RMGOption.SERIAL_VERSION_UID, RMGOption.PAYLOAD_SERIAL_VERSION_UID, RMGOption.SOCKET_FACTORY, + RMGOption.SOCKET_FACTORY_SSL, + RMGOption.SOCKET_FACTORY_PLAIN, }), ENUM("dispatchEnum", "[scan-action ...]", "Enumerate common vulnerabilities on Java RMI endpoints", new RMGOption[] { @@ -125,6 +131,8 @@ public enum Operation { RMGOption.FORCE_ACTIVATION, RMGOption.SERIAL_VERSION_UID, RMGOption.SOCKET_FACTORY, + RMGOption.SOCKET_FACTORY_SSL, + RMGOption.SOCKET_FACTORY_PLAIN, }), GUESS("dispatchGuess", "", "Guess methods on bound names", new RMGOption[] { @@ -155,6 +163,8 @@ public enum Operation { RMGOption.FORCE_ACTIVATION, RMGOption.SERIAL_VERSION_UID, RMGOption.SOCKET_FACTORY, + RMGOption.SOCKET_FACTORY_SSL, + RMGOption.SOCKET_FACTORY_PLAIN, }), KNOWN("dispatchKnown", "", "Display details of known remote objects", new RMGOption[] { @@ -207,6 +217,8 @@ public enum Operation { RMGOption.BIND_GADGET_CMD, RMGOption.YSO, RMGOption.SOCKET_FACTORY, + RMGOption.SOCKET_FACTORY_SSL, + RMGOption.SOCKET_FACTORY_PLAIN, }), ROGUEJMX("dispatchRogueJMX", "[forward-host]", "Creates a rogue JMX listener (collect credentials)", new RMGOption[] { @@ -265,6 +277,8 @@ public enum Operation { RMGOption.FORCE_ACTIVATION, RMGOption.SERIAL_VERSION_UID, RMGOption.SOCKET_FACTORY, + RMGOption.SOCKET_FACTORY_SSL, + RMGOption.SOCKET_FACTORY_PLAIN, }), UNBIND("dispatchUnbind", "", "Removes the specified bound name from the registry", new RMGOption[] { @@ -284,6 +298,8 @@ public enum Operation { RMGOption.BIND_BOUND_NAME, RMGOption.BIND_BYPASS, RMGOption.SOCKET_FACTORY, + RMGOption.SOCKET_FACTORY_SSL, + RMGOption.SOCKET_FACTORY_PLAIN, }); private Method method; diff --git a/src/de/qtc/rmg/plugin/DefaultProvider.java b/src/de/qtc/rmg/plugin/DefaultProvider.java index ba8fd53..1549452 100644 --- a/src/de/qtc/rmg/plugin/DefaultProvider.java +++ b/src/de/qtc/rmg/plugin/DefaultProvider.java @@ -9,7 +9,6 @@ import de.qtc.rmg.io.Logger; import de.qtc.rmg.networking.DGCClientSocketFactory; import de.qtc.rmg.networking.LoopbackSocketFactory; -import de.qtc.rmg.networking.LoopbackSslSocketFactory; import de.qtc.rmg.networking.SSRFResponseSocketFactory; import de.qtc.rmg.networking.SSRFSocketFactory; import de.qtc.rmg.networking.TrustAllSocketFactory; @@ -172,11 +171,12 @@ public RMIClientSocketFactory getClientSocketFactory(String host, int port) @Override public RMISocketFactory getDefaultSocketFactory(String host, int port) { - if( RMGOption.SSRFRESPONSE.notNull() ) + if (RMGOption.SSRFRESPONSE.notNull()) + { return new DGCClientSocketFactory(); + } - RMISocketFactory fac = RMISocketFactory.getDefaultSocketFactory(); - return new LoopbackSocketFactory(host, fac, RMGOption.CONN_FOLLOW.getBool()); + return new LoopbackSocketFactory(); } /** @@ -193,14 +193,10 @@ public RMISocketFactory getDefaultSocketFactory(String host, int port) @Override public String getDefaultSSLSocketFactory(String host, int port) { - if( RMGOption.SSRFRESPONSE.notNull() ) + if (RMGOption.SSRFRESPONSE.notNull()) + { return "de.qtc.rmg.networking.DGCClientSslSocketFactory"; - - TrustAllSocketFactory trustAllFax = new TrustAllSocketFactory(); - - LoopbackSslSocketFactory.host = host; - LoopbackSslSocketFactory.fac = trustAllFax.getSSLSocketFactory(); - LoopbackSslSocketFactory.followRedirect = RMGOption.CONN_FOLLOW.getBool(); + } return "de.qtc.rmg.networking.LoopbackSslSocketFactory"; } diff --git a/src/de/qtc/rmg/utils/RMGUtils.java b/src/de/qtc/rmg/utils/RMGUtils.java index 8f107b9..ac27a2b 100644 --- a/src/de/qtc/rmg/utils/RMGUtils.java +++ b/src/de/qtc/rmg/utils/RMGUtils.java @@ -74,11 +74,15 @@ public static void init() { pool = ClassPool.getDefault(); - try { + try + { remoteClass = pool.getCtClass(Remote.class.getName()); serializable = pool.getCtClass("java.io.Serializable"); remoteStubClass = pool.getCtClass(RemoteStub.class.getName()); - } catch (NotFoundException e) { + } + + catch (NotFoundException e) + { ExceptionHandler.internalError("RMGUtils.init", "Caught unexpected NotFoundException."); } @@ -215,13 +219,15 @@ public static Class makeActivatableRef() throws CannotCompileException /** * Dynamically create a socket factory class that implements RMIClientSocketFactory. This function is used when - * the RMI server uses a custom socket factory class. In this case, rmg attempts to connect with it's default - * TrustAllSocketFactory, which works if the custom socket factory provided by the server is not too different. + * the RMI server uses a custom socket factory class. In this case, remote-method-guesser attempts to connect + * with it's default LoopbackSslSocketFactory or LoopbackSocketFactory (depending on the value of the settings + * --ssl, --socket-factory-ssl and --socket-factory-plain) which works if the custom socket factory provided by + * the server is not too different. * - * To achieve this, rmg just clones TrustAllSocketFactory and assigns it a new name. As in the case of Stub - * classes with unusual serialVersionUIDs, the serialVersionUID is determined error based. The factory is first - * created using a default serialVersionUID. This should cause an exception revealing the actual serialVersionUID. - * This is then used to recreate the class. + * To achieve this, remote-method-guesser just clones LoopbackSslSocketFactory or LoopbackSocketFactory and assigns + * it a new name. As in the case of Stub classes with unusual serialVersionUIDs, the serialVersionUID is determined + * error based. The factory is first created using a default serialVersionUID. This should cause an exception revealing + * the actual serialVersionUID. This is then used to recreate the class. * * Check the CodebaseCollector class documentation for more information. * @@ -241,7 +247,23 @@ public static Class makeSocketFactory(String className, long serialVersionUID) t try { - ctClass = pool.getAndRename("de.qtc.rmg.networking.TrustAllSocketFactory", className); + + if (!RMGOption.SOCKET_FACTORY_PLAIN.getBool() && (RMGOption.CONN_SSL.getBool() || RMGOption.SOCKET_FACTORY_SSL.getBool())) + { + ctClass = pool.getAndRename("de.qtc.rmg.networking.LoopbackSslSocketFactory", className); + } + + else if (!RMGOption.SOCKET_FACTORY_SSL.getBool() && (!RMGOption.CONN_SSL.getBool() || RMGOption.SOCKET_FACTORY_PLAIN.getBool())) + { + ctClass = pool.getAndRename("de.qtc.rmg.networking.LoopbackSocketFactory", className); + } + + else + { + Logger.eprintlnYellow("Invalid combination of SSL related options."); + exit(); + } + ctClass.addInterface(serializable); addSerialVersionUID(ctClass, serialVersionUID); } From aa9637a6b2ed575967cccfafc0feeab4c767c4f5 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 3 Oct 2023 08:22:07 +0200 Subject: [PATCH 05/60] Small formatting changes --- src/de/qtc/rmg/Starter.java | 8 +- src/de/qtc/rmg/endpoints/KnownEndpoint.java | 8 +- .../rmg/endpoints/KnownEndpointHolder.java | 24 ++-- src/de/qtc/rmg/endpoints/Vulnerability.java | 4 +- .../exceptions/MalformedPluginException.java | 7 +- src/de/qtc/rmg/exceptions/SSRFException.java | 6 +- .../UnexpectedCharacterException.java | 8 +- src/de/qtc/rmg/internal/ArgumentHandler.java | 122 ++++++++++++------ 8 files changed, 121 insertions(+), 66 deletions(-) diff --git a/src/de/qtc/rmg/Starter.java b/src/de/qtc/rmg/Starter.java index 47e40a5..e030896 100644 --- a/src/de/qtc/rmg/Starter.java +++ b/src/de/qtc/rmg/Starter.java @@ -11,10 +11,10 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class Starter { - - public static void main(String[] argv) { - +public class Starter +{ + public static void main(String[] argv) + { ArgumentHandler handler = new ArgumentHandler(argv); Operation operation = handler.getAction(); diff --git a/src/de/qtc/rmg/endpoints/KnownEndpoint.java b/src/de/qtc/rmg/endpoints/KnownEndpoint.java index 6972bc7..ea90264 100644 --- a/src/de/qtc/rmg/endpoints/KnownEndpoint.java +++ b/src/de/qtc/rmg/endpoints/KnownEndpoint.java @@ -16,8 +16,8 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class KnownEndpoint { - +public class KnownEndpoint +{ private String name; private String description; @@ -96,9 +96,13 @@ public void printEnum() String format = String.format("(known class: %s)", name); if( vulnerabilities.size() == 0 ) + { Logger.printlnPlainGreen(format); + } else + { Logger.printlnPlainYellow(format); + } } } diff --git a/src/de/qtc/rmg/endpoints/KnownEndpointHolder.java b/src/de/qtc/rmg/endpoints/KnownEndpointHolder.java index 6d6aca9..5f7c8b9 100644 --- a/src/de/qtc/rmg/endpoints/KnownEndpointHolder.java +++ b/src/de/qtc/rmg/endpoints/KnownEndpointHolder.java @@ -15,8 +15,8 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class KnownEndpointHolder { - +public class KnownEndpointHolder +{ private List knownEndpoints = null; private static KnownEndpointHolder instance = null; @@ -53,13 +53,18 @@ public void setKnownEndpoints(List knownEndpoints) */ public KnownEndpoint lookup(String className) { - if( knownEndpoints == null ) + if (knownEndpoints == null) + { return null; + } - for( KnownEndpoint endpoint : knownEndpoints ) - - if( endpoint.getClassName().contains(className) ) + for (KnownEndpoint endpoint : knownEndpoints) + { + if (endpoint.getClassName().contains(className)) + { return endpoint; + } + } return null; } @@ -73,8 +78,10 @@ public KnownEndpoint lookup(String className) */ public boolean isKnown(String className) { - if( lookup(className) == null ) + if (lookup(className) == null) + { return false; + } return true; } @@ -92,7 +99,8 @@ public boolean isKnown(String className) */ public static KnownEndpointHolder getHolder() { - if( instance == null ) { + if (instance == null) + { Yaml yaml = new Yaml(new Constructor(KnownEndpointHolder.class)); InputStream stream = KnownEndpoint.class.getResourceAsStream(resource); diff --git a/src/de/qtc/rmg/endpoints/Vulnerability.java b/src/de/qtc/rmg/endpoints/Vulnerability.java index 0b34a23..8a205fc 100644 --- a/src/de/qtc/rmg/endpoints/Vulnerability.java +++ b/src/de/qtc/rmg/endpoints/Vulnerability.java @@ -10,8 +10,8 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class Vulnerability { - +public class Vulnerability +{ private String name; private String description; diff --git a/src/de/qtc/rmg/exceptions/MalformedPluginException.java b/src/de/qtc/rmg/exceptions/MalformedPluginException.java index 8e978e6..f9b12ba 100644 --- a/src/de/qtc/rmg/exceptions/MalformedPluginException.java +++ b/src/de/qtc/rmg/exceptions/MalformedPluginException.java @@ -8,13 +8,14 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class MalformedPluginException extends Exception { - +public class MalformedPluginException extends Exception +{ private static final long serialVersionUID = 1L; public MalformedPluginException() {} - public MalformedPluginException(String message) { + public MalformedPluginException(String message) + { super(message); } } diff --git a/src/de/qtc/rmg/exceptions/SSRFException.java b/src/de/qtc/rmg/exceptions/SSRFException.java index 3ed7b26..97f6c2b 100644 --- a/src/de/qtc/rmg/exceptions/SSRFException.java +++ b/src/de/qtc/rmg/exceptions/SSRFException.java @@ -2,7 +2,7 @@ import java.io.Serializable; -public class SSRFException extends Exception implements Serializable { - +public class SSRFException extends Exception implements Serializable +{ private static final long serialVersionUID = 1L; -} +} \ No newline at end of file diff --git a/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java b/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java index c573ac8..4461234 100644 --- a/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java +++ b/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java @@ -14,10 +14,12 @@ * @author Tobias Neitzel (@qtc_de) */ @SuppressWarnings("serial") -public class UnexpectedCharacterException extends Exception { +public class UnexpectedCharacterException extends Exception +{ public UnexpectedCharacterException() {} - public UnexpectedCharacterException(String message) { + public UnexpectedCharacterException(String message) + { super(message); } -} +} \ No newline at end of file diff --git a/src/de/qtc/rmg/internal/ArgumentHandler.java b/src/de/qtc/rmg/internal/ArgumentHandler.java index 7592278..15cf98d 100644 --- a/src/de/qtc/rmg/internal/ArgumentHandler.java +++ b/src/de/qtc/rmg/internal/ArgumentHandler.java @@ -56,10 +56,13 @@ public ArgumentHandler(String[] argv) Subparsers subparsers = parser.addSubparsers().help(" ").metavar("action").dest("action"); Operation.addSubparsers(subparsers); - try { + try + { args = parser.parseArgs(argv); + } - } catch (ArgumentParserException e) { + catch (ArgumentParserException e) + { parser.handleError(e); System.exit(1); } @@ -78,27 +81,30 @@ private Properties loadConfig(String filename) { Properties config = new Properties(); - try { + try + { InputStream configStream = null; configStream = ArgumentParser.class.getResourceAsStream(defaultConfiguration); config.load(configStream); configStream.close(); - if( filename != null ) { + if (filename != null) + { configStream = new FileInputStream(filename); config.load(configStream); configStream.close(); } + } - } catch( IOException e ) { + catch (IOException e) + { ExceptionHandler.unexpectedException(e, "loading", ".properties file", true); } return config; } - /** * Initializes the RMGOption enum and sets some static variables depending on the specified options. */ @@ -107,14 +113,17 @@ private void initialize() config = loadConfig(args.get(RMGOption.GLOBAL_CONFIG.name)); RMGOption.prepareOptions(args, config); - if( RMGOption.GLOBAL_NO_COLOR.getBool() ) + if (RMGOption.GLOBAL_NO_COLOR.getBool()) + { Logger.disableColor(); + } - if( RMGOption.SSRF_RAW.getBool() ) + if (RMGOption.SSRF_RAW.getBool()) + { Logger.disableStdout(); + } checkPortRange(); - PluginSystem.init(RMGOption.GLOBAL_PLUGIN.getValue()); } @@ -124,12 +133,15 @@ private void initialize() */ private void checkPortRange() { - if( RMGOption.TARGET_PORT.isNull() ) + if (RMGOption.TARGET_PORT.isNull()) + { return; + } int port = RMGOption.TARGET_PORT.getValue(); - if( port < 1 || port > 65535 ) { + if (port < 1 || port > 65535) + { Logger.eprintlnMixedYellow("The specified port number", String.valueOf(port), "is out of range."); RMGUtils.exit(); } @@ -144,8 +156,10 @@ public Operation getAction() { this.action = Operation.getByName(args.getString("action")); - if( action == null ) + if (action == null) + { ExceptionHandler.internalError("ArgumentHandler.getAction", "Invalid action was specified"); + } return action; } @@ -161,20 +175,24 @@ public Operation getAction() */ public String getRegMethod() { - if( regMethod != null ) + if (regMethod != null) + { return regMethod; + } String signature = RMGOption.REG_METHOD.getValue(); String[] supported = new String[]{"lookup", "unbind", "rebind", "bind"}; - if( signature == null ) { + if (signature == null) + { regMethod = "lookup"; return regMethod; } - for(String methodName : supported ) { - - if( signature.contains(methodName) ) { + for (String methodName : supported) + { + if (signature.contains(methodName)) + { regMethod = methodName; return methodName; } @@ -198,19 +216,23 @@ public String getRegMethod() */ public String getDgcMethod() { - if( dgcMethod != null ) + if (dgcMethod != null) + { return dgcMethod; + } String signature = RMGOption.DGC_METHOD.getValue(); - if( signature == null ) { + if (signature == null) + { dgcMethod = "clean"; return dgcMethod; } - for(String methodName : new String[]{"clean", "dirty"} ) { - - if( signature.contains(methodName) ) { + for (String methodName : new String[]{"clean", "dirty"}) + { + if (signature.contains(methodName)) + { dgcMethod = methodName; return methodName; } @@ -232,16 +254,20 @@ public String getDgcMethod() */ public RMIComponent getComponent() { - if( component != null ) + if (component != null) + { return component; + } RMIComponent targetComponent = RMIComponent.getByShortName(RMGOption.TARGET_COMPONENT.getValue()); - if( targetComponent == null ) + if (targetComponent == null) + { return null; + } - switch( targetComponent ) { - + switch (targetComponent) + { case REGISTRY: case DGC: case ACTIVATOR: @@ -255,7 +281,6 @@ public RMIComponent getComponent() } component = targetComponent; - return targetComponent; } @@ -270,15 +295,17 @@ public Object getGadget() String gadget = null; String command = null; - if( this.getAction() == Operation.BIND || this.getAction() == Operation.REBIND ) { - + if (this.getAction() == Operation.BIND || this.getAction() == Operation.REBIND) + { boolean customGadget = RMGOption.BIND_GADGET_NAME.notNull(); boolean customCommand = RMGOption.BIND_GADGET_CMD.notNull(); gadget = customGadget ? RMGOption.BIND_GADGET_NAME.getValue() : "jmx"; command = customCommand ? RMGOption.BIND_GADGET_CMD.getValue() : RMGOption.require(RMGOption.BIND_ADDRESS); + } - } else { + else + { gadget = (String) RMGOption.require(RMGOption.GADGET_NAME); command = RMGOption.require(RMGOption.GADGET_CMD); } @@ -310,8 +337,10 @@ public EnumSet getScanActions() { List scanActions = (List) RMGOption.ENUM_ACTION.value; - if( scanActions == null ) + if (scanActions == null) + { return EnumSet.allOf(ScanAction.class); + } return ScanAction.parseScanActions(scanActions); } @@ -333,18 +362,23 @@ public int[] getRmiPorts() String defaultPorts = config.getProperty("rmi_ports"); List portStrings = (List)RMGOption.SCAN_PORTS.value; - if( portStrings == null ) { + if (portStrings == null) + { portStrings = new ArrayList(); portStrings.add("-"); } - for(String portString : portStrings) { - - if( portString.equals("-") ) + for (String portString : portStrings) + { + if (portString.equals("-")) + { addPorts(defaultPorts, rmiPorts); + } else + { addPorts(portString, rmiPorts); + } } return rmiPorts.stream().mapToInt(i->i).toArray(); @@ -360,7 +394,8 @@ public void addPorts(String portString, Set portList) { String[] ports = portString.split(","); - for(String port: ports) { + for (String port: ports) + { addRange(port, portList); } } @@ -373,9 +408,10 @@ public void addPorts(String portString, Set portList) */ public void addRange(String portRange, Set portList) { - try { - - if(!portRange.contains("-")) { + try + { + if (!portRange.contains("-")) + { portList.add(Integer.valueOf(portRange)); return; } @@ -384,10 +420,14 @@ public void addRange(String portRange, Set portList) int start = Integer.valueOf(split[0]); int end = Integer.valueOf(split[1]); - for(int ctr = start; ctr <= end; ctr++) + for (int ctr = start; ctr <= end; ctr++) + { portList.add(ctr); + } + } - } catch( java.lang.NumberFormatException | java.lang.ArrayIndexOutOfBoundsException e ) { + catch (java.lang.NumberFormatException | java.lang.ArrayIndexOutOfBoundsException e) + { Logger.eprintlnMixedYellow("Caught unexpected", e.getClass().getSimpleName(), "while parsing RMI ports."); Logger.eprintlnMixedBlue("The specified value", portRange, "is invalid."); RMGUtils.exit(); From 5bb676167c8a654e02c7eb21f59e290ae5a30f2e Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 8 Oct 2023 08:49:33 +0200 Subject: [PATCH 06/60] Add spring remoting server Added a spring remoting server. --- docker/spring-remoting/Dockerfile | 35 +++++ .../resources/scripts/start.sh | 14 ++ .../spring-remoting/resources/server/pom.xml | 55 ++++++++ .../rmg/springremoting/ServerOperations.java | 10 ++ .../springremoting/SpringRemotingService.java | 122 ++++++++++++++++++ .../de/qtc/rmg/springremoting/Starter.java | 11 ++ 6 files changed, 247 insertions(+) create mode 100644 docker/spring-remoting/Dockerfile create mode 100755 docker/spring-remoting/resources/scripts/start.sh create mode 100644 docker/spring-remoting/resources/server/pom.xml create mode 100644 docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java create mode 100644 docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java create mode 100644 docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java diff --git a/docker/spring-remoting/Dockerfile b/docker/spring-remoting/Dockerfile new file mode 100644 index 0000000..73d791c --- /dev/null +++ b/docker/spring-remoting/Dockerfile @@ -0,0 +1,35 @@ +########################################### +### Build Stage 1 ### +########################################### +FROM maven:3.8.6-openjdk-8-slim AS maven-builder +COPY ./resources/server /usr/src/app +WORKDIR /usr/src/app +RUN mvn clean package + +########################################### +### Build Stage 2 ### +########################################### +FROM alpine:latest AS jdk-builder +RUN set -ex \ + && apk add --no-cache openjdk11 \ + && /usr/lib/jvm/java-11-openjdk/bin/jlink --add-modules java.rmi,java.management.rmi,jdk.unsupported --verbose --strip-debug --compress 2 \ + --no-header-files --no-man-pages --output /jdk + +########################################### +### Container Stage ### +########################################### +FROM alpine:latest + +COPY ./resources/scripts/start.sh /opt/start.sh +COPY --from=maven-builder /usr/src/app/target/rmg-spring-remoting-server-*-jar-with-dependencies.jar /opt/remoting-server.jar +COPY --from=jdk-builder /jdk /usr/lib/jvm/java-11-openjdk + +RUN set -ex \ + && ln -s /usr/lib/jvm/java-11-openjdk/bin/java /usr/bin/java \ + && chmod +x /opt/start.sh + +ENV _JAVA_OPTIONS -Djava.rmi.server.hostname=iinsecure.example + +EXPOSE 1099/tcp + +CMD ["/opt/start.sh"] diff --git a/docker/spring-remoting/resources/scripts/start.sh b/docker/spring-remoting/resources/scripts/start.sh new file mode 100755 index 0000000..705846f --- /dev/null +++ b/docker/spring-remoting/resources/scripts/start.sh @@ -0,0 +1,14 @@ +#!/bin/ash + +IP=$(ip a | grep inet | grep -v 127.0.0.1 | grep -o "\([0-9]\{1,3\}\.\?\)\{4\}" | head -n 1) +echo "[+] IP address of the container: ${IP}" + +echo "[+] Adding gateway address to /etc/hosts file..." +GATEWAY=$(ip r | grep "default via" | cut -d" " -f 3) +echo "$GATEWAY prevent.reverse.dns" >> /etc/hosts + +echo "[+] Adding RMI hostname to /etc/hosts file..." +echo "127.0.0.1 iinsecure.example" >> /etc/hosts + +echo "[+] Starting rmi server..." +exec /usr/bin/java -jar /opt/remoting-server.jar diff --git a/docker/spring-remoting/resources/server/pom.xml b/docker/spring-remoting/resources/server/pom.xml new file mode 100644 index 0000000..b587eff --- /dev/null +++ b/docker/spring-remoting/resources/server/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + de.qtc.rmg + spring-remoting + 1.0.0 + + + UTF-8 + 1.8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + 2.7.16 + + + + + + + maven-assembly-plugin + + + package + + single + + + + + rmg-spring-remoting-server-${project.version} + + + de.qtc.rmg.springremoting.Starter + true + + + + jar-with-dependencies + + + + + + + diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java new file mode 100644 index 0000000..670552d --- /dev/null +++ b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java @@ -0,0 +1,10 @@ +package de.qtc.rmg.springremoting; + +public interface ServerOperations +{ + String notRelevant(); + String execute(String cmd); + String system(String cmd, String[] args); + String upload(int size, int id, byte[] content); + int math(int num1, int num2); +} \ No newline at end of file diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java new file mode 100644 index 0000000..212eb49 --- /dev/null +++ b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java @@ -0,0 +1,122 @@ +package de.qtc.rmg.springremoting; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.remoting.rmi.RmiServiceExporter; + +@SuppressWarnings("deprecation") +public class SpringRemotingService implements ServerOperations +{ + Logger logger = LoggerFactory.getLogger(SpringRemotingService.class); + + SpringRemotingService springRemotingService() + { + return new SpringRemotingService(); + } + + @Bean + RmiServiceExporter exporter(SpringRemotingService impl) + { + Class serverInterface = ServerOperations.class; + RmiServiceExporter exporter = new RmiServiceExporter(); + + exporter.setServiceInterface(serverInterface); + exporter.setService(impl); + exporter.setServiceName("spring-remoting"); + exporter.setRegistryPort(1099); + + return exporter; + } + + public String notRelevant() + { + logger.info("Method", "notRelevant", "was called."); + return "Hello World :D"; + } + + public String execute(String command) + { + logger.info("Processing call for", "String execute(String command)"); + String result = ""; + + try + { + Process p = java.lang.Runtime.getRuntime().exec(command); + p.waitFor(); + result = readFromProcess(p); + } + + catch (IOException | InterruptedException e) + { + result = "Exception: " + e.getMessage(); + } + + return result; + } + + public String system(String command, String[] args) + { + logger.info("Processing call for", "String system(String command, String[] args)"); + String result = ""; + + String[] commandArray = new String[args.length + 1]; + commandArray[0] = command; + System.arraycopy(args, 0, commandArray, 1, args.length); + + try + { + Process p = java.lang.Runtime.getRuntime().exec(commandArray); + p.waitFor(); + result = readFromProcess(p); + } + + catch (IOException | InterruptedException e) + { + result = "Exception: " + e.getMessage(); + } + + return result; + } + + public String upload(int size, int id, byte[] content) + { + logger.info("Processing call for", "String upload(int size, int id, byte[] content)"); + return "Upload of size " + size + " was saved as user_uploads_" + id + "."; + } + + public int math(int num1, int num2) + { + logger.info("Processing call for", "int math(int num1, int num2)"); + return num1 / num2; + } + + private static String readFromProcess(Process p) throws IOException + { + StringBuilder result = new StringBuilder(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line = reader.readLine(); + + while (line != null) + { + result.append(line); + line = reader.readLine(); + } + + reader = new BufferedReader(new InputStreamReader(p.getErrorStream())); + line = reader.readLine(); + + while (line != null) + { + result.append(line); + line = reader.readLine(); + } + + return result.toString(); + } +} \ No newline at end of file diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java new file mode 100644 index 0000000..0d82a4e --- /dev/null +++ b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java @@ -0,0 +1,11 @@ +package de.qtc.rmg.springremoting; + +import org.springframework.boot.SpringApplication; + +public class Starter +{ + public static void main(String[] args) + { + SpringApplication.run(SpringRemotingService.class, args); + } +} From f9b96b57f87f63360b75aca7aa0c51d4484b719d Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 8 Oct 2023 09:06:35 +0200 Subject: [PATCH 07/60] Add spring remoting to known endpoints --- docs/rmi/known-endpoints.md | 61 ++++++++++++++++--- resources/known-endpoints/known-endpoints.yml | 53 +++++++++++++--- 2 files changed, 94 insertions(+), 20 deletions(-) diff --git a/docs/rmi/known-endpoints.md b/docs/rmi/known-endpoints.md index 77773cb..73e6358 100644 --- a/docs/rmi/known-endpoints.md +++ b/docs/rmi/known-endpoints.md @@ -34,7 +34,7 @@ > attacks. With JEP290, deserialization filters were introduced. The deserialization filters of DGC > endpoints are more restrictive than for the RMI registry and there a no known bypasses. * References: - * [https://github.com/qtc-de/remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) + * [https://github.com/qtc-de/remote-method-guesser#serial](https://github.com/qtc-de/remote-method-guesser#serial) ### JMX Connection @@ -93,7 +93,7 @@ > other MBeans dynamically from user specified codebase locations (URLs). Access to the MLet MBean > is therefore most of the time equivalent to remote code execution. * References: - * [https://github.com/qtc-de/beanshooter](https://github.com/qtc-de/beanshooter) + * [https://github.com/qtc-de/beanshooter#generic-deploy](https://github.com/qtc-de/beanshooter#generic-deploy) * Deserialization * Description: @@ -101,7 +101,7 @@ > All communication to JMX that is dispatched over this remote object is not filtered for deserialization > attacks. Therefore, each suitable method can be used to pass a deserialization payload to the server. * References: - * [https://github.com/qtc-de/beanshooter](https://github.com/qtc-de/beanshooter) + * [https://github.com/qtc-de/beanshooter#serial](https://github.com/qtc-de/beanshooter#serial) ### JMX Server @@ -138,7 +138,7 @@ > other MBeans dynamically from user specified codebase locations (URLs). Access to the MLet MBean > is therefore most of the time equivalent to remote code execution. * References: - * [https://github.com/qtc-de/beanshooter](https://github.com/qtc-de/beanshooter) + * [https://github.com/qtc-de/beanshooter#generic-deploy](https://github.com/qtc-de/beanshooter#generic-deploy) * Deserialization * Description: @@ -148,7 +148,7 @@ > actual JMX communication using the RMIConnection object is not filtered. Therefore, if you can > establish a working JMX connection, you can also perform deserialization attacks. * References: - * [https://github.com/qtc-de/beanshooter](https://github.com/qtc-de/beanshooter) + * [https://github.com/qtc-de/beanshooter#serial](https://github.com/qtc-de/beanshooter#serial) ### RMI Activation Group @@ -180,7 +180,7 @@ > ActivationGroup remote objects do not use a deserialization filter. * References: - * [https://github.com/qtc-de/remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) + * [https://github.com/qtc-de/remote-method-guesser#serial](https://github.com/qtc-de/remote-method-guesser#serial) ### RMI Activation System @@ -224,7 +224,7 @@ > When accessed from localhost, the ActivationSystem is vulnerable to deserialization attacks. * References: - * [https://github.com/qtc-de/remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) + * [https://github.com/qtc-de/remote-method-guesser#serial](https://github.com/qtc-de/remote-method-guesser#serial) ### RMI Activator @@ -255,7 +255,7 @@ > Deserialization filters were never applied to the activation system and the Activator can be used > for deserialization attacks. * References: - * [https://github.com/qtc-de/remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) + * [https://github.com/qtc-de/remote-method-guesser#serial](https://github.com/qtc-de/remote-method-guesser#serial) ### RMI Registry @@ -292,7 +292,7 @@ > JEP290, deserialization filters were introduced. Depending on the patch level of the corresponding > Java instance, the filters may be bypassed. * References: - * [https://github.com/qtc-de/remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) + * [https://github.com/qtc-de/remote-method-guesser#serial](https://github.com/qtc-de/remote-method-guesser#serial) * Localhost Bypass * Description: @@ -301,7 +301,7 @@ > RMI registry instance. In 2019, a bypass for this localhost restriction was identified, that may allows > an attacker to bind, rebind or unbind names from remote. * References: - * [https://github.com/qtc-de/remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) + * [https://github.com/qtc-de/remote-method-guesser#bind-rebind-and-unbind](https://github.com/qtc-de/remote-method-guesser#bind-rebind-and-unbind) * UnicastRemoteObject * Description: @@ -311,3 +311,44 @@ > existing remote objects that are listening on an user specified TCP port. * References: * [https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmi/unicast-remote-object.md](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmi/unicast-remote-object.md) + + +### Spring RmiInvocationHandler + +--- + +* Name: `Spring RmiInvocationHandler` +* Class Names: + * `org.springframework.remoting.rmi.RmiInvocationHandler` +* Description: + + > RmiInvocationHandler is basically a wrapper around the actual RMI services that are implemented by the server. The + > interface supports an invoke method that forwards the call to the actual RMI service. Moreover, the getTargetInterfaceName + > method can be used to retrieve the interface that is implemented by the actual RMI service. + +* Remote Methods: + + ```java + java.lang.String getTargetInterfaceName() + java.lang.Object invoke(org.springframework.remoting.support RemoteInvocation) + ``` +* References: + * [https://docs.spring.io/spring-framework/docs/5.3.0/javadoc-api/org/springframework/remoting/rmi/RmiInvocationHandler.html](https://docs.spring.io/spring-framework/docs/5.3.0/javadoc-api/org/springframework/remoting/rmi/RmiInvocationHandler.html) + * [https://docs.spring.io/spring-framework/docs/5.3.0/javadoc-api/org/springframework/remoting/support/RemoteInvocation.html](https://docs.spring.io/spring-framework/docs/5.3.0/javadoc-api/org/springframework/remoting/support/RemoteInvocation.html) +* Known Vulnerabilities: + + * Deserialization + * Description: + + > The invoke method uses a method parameter with non trivial type and is therefore vulnerable to arbitrary deserialization. + * References: + * [https://github.com/qtc-de/remote-method-guesser#serial](https://github.com/qtc-de/remote-method-guesser#serial) + + * Vulnerable Methods + * Description: + + > The actual RMI services behind the wrapper may expose other methods that contain vulnerabilities. Obtaining the interface name + > by calling getTargetInterfaceName may allow to obtain the interface definition using online resources. If this is not possible, + > remote-method-guesser can be used to guess remote methods. + * References: + * [https://github.com/qtc-de/remote-method-guesser#guess](https://github.com/qtc-de/remote-method-guesser#guess) diff --git a/resources/known-endpoints/known-endpoints.yml b/resources/known-endpoints/known-endpoints.yml index eac952c..6501a47 100644 --- a/resources/known-endpoints/known-endpoints.yml +++ b/resources/known-endpoints/known-endpoints.yml @@ -27,7 +27,7 @@ knownEndpoints: other MBeans dynamically from user specified codebase locations (URLs). Access to the MLet MBean is therefore most of the time equivalent to remote code execution. references: - - https://github.com/qtc-de/beanshooter + - https://github.com/qtc-de/beanshooter#generic-deploy - name: Deserialization description: | @@ -36,7 +36,7 @@ knownEndpoints: actual JMX communication using the RMIConnection object is not filtered. Therefore, if you can establish a working JMX connection, you can also perform deserialization attacks. references: - - https://github.com/qtc-de/beanshooter + - https://github.com/qtc-de/beanshooter#serial - name: JMX Connection @@ -88,14 +88,14 @@ knownEndpoints: other MBeans dynamically from user specified codebase locations (URLs). Access to the MLet MBean is therefore most of the time equivalent to remote code execution. references: - - https://github.com/qtc-de/beanshooter + - https://github.com/qtc-de/beanshooter#generic-deploy - name: Deserialization description: | All communication to JMX that is dispatched over this remote object is not filtered for deserialization attacks. Therefore, each suitable method can be used to pass a deserialization payload to the server. references: - - https://github.com/qtc-de/beanshooter + - https://github.com/qtc-de/beanshooter#serial - name: RMI Registry @@ -125,7 +125,7 @@ knownEndpoints: JEP290, deserialization filters were introduced. Depending on the patch level of the corresponding Java instance, the filters may be bypassed. references: - - https://github.com/qtc-de/remote-method-guesser + - https://github.com/qtc-de/remote-method-guesser#serial - name: Localhost Bypass description: | @@ -133,7 +133,7 @@ knownEndpoints: RMI registry instance. In 2019, a bypass for this localhost restriction was identified, that may allows an attacker to bind, rebind or unbind names from remote. references: - - https://github.com/qtc-de/remote-method-guesser + - https://github.com/qtc-de/remote-method-guesser#bind-rebind-and-unbind - name: UnicastRemoteObject description: | @@ -173,7 +173,7 @@ knownEndpoints: attacks. With JEP290, deserialization filters were introduced. The deserialization filters of DGC endpoints are more restrictive than for the RMI registry and there a no known bypasses. references: - - https://github.com/qtc-de/remote-method-guesser + - https://github.com/qtc-de/remote-method-guesser#serial - name: RMI Activation System @@ -210,7 +210,7 @@ knownEndpoints: description: | When accessed from localhost, the ActivationSystem is vulnerable to deserialization attacks. references: - - https://github.com/qtc-de/remote-method-guesser + - https://github.com/qtc-de/remote-method-guesser#serial - name: RMI Activation Group @@ -235,7 +235,7 @@ knownEndpoints: description: | ActivationGroup remote objects do not use a deserialization filter. references: - - https://github.com/qtc-de/remote-method-guesser + - https://github.com/qtc-de/remote-method-guesser#serial - name: RMI Activator @@ -259,4 +259,37 @@ knownEndpoints: Deserialization filters were never applied to the activation system and the Activator can be used for deserialization attacks. references: - - https://github.com/qtc-de/remote-method-guesser + - https://github.com/qtc-de/remote-method-guesser#serial + + +- name: Spring RmiInvocationHandler + className: + - org.springframework.remoting.rmi.RmiInvocationHandler + + description: | + RmiInvocationHandler is basically a wrapper around the actual RMI services that are implemented by the server. The + interface supports an invoke method that forwards the call to the actual RMI service. Moreover, the getTargetInterfaceName + method can be used to retrieve the interface that is implemented by the actual RMI service. + + remoteMethods: + - java.lang.String getTargetInterfaceName() + - java.lang.Object invoke(org.springframework.remoting.support RemoteInvocation) + + references: + - https://docs.spring.io/spring-framework/docs/5.3.0/javadoc-api/org/springframework/remoting/rmi/RmiInvocationHandler.html + - https://docs.spring.io/spring-framework/docs/5.3.0/javadoc-api/org/springframework/remoting/support/RemoteInvocation.html + + vulnerabilities: + - name: Deserialization + description: | + The invoke method uses a method parameter with non trivial type and is therefore vulnerable to arbitrary deserialization. + references: + - https://github.com/qtc-de/remote-method-guesser#serial + + - name: Vulnerable Methods + description: | + The actual RMI services behind the wrapper may expose other methods that contain vulnerabilities. Obtaining the interface name + by calling getTargetInterfaceName may allow to obtain the interface definition using online resources. If this is not possible, + remote-method-guesser can be used to guess remote methods. + references: + - https://github.com/qtc-de/remote-method-guesser#guess From c7d1dc9c37253b2adf58860e7f304a6cc6c58ea1 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 8 Oct 2023 09:20:17 +0200 Subject: [PATCH 08/60] Update pom.xml --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index eb12982..8dcd936 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ - + 4.0.0 From b02e388ac2713cef3ff5bbddaefc2fc097352e2d Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 8 Oct 2023 09:25:31 +0200 Subject: [PATCH 09/60] Reformat MethodGuesser --- src/de/qtc/rmg/operations/MethodGuesser.java | 112 ++++++++++++------- 1 file changed, 72 insertions(+), 40 deletions(-) diff --git a/src/de/qtc/rmg/operations/MethodGuesser.java b/src/de/qtc/rmg/operations/MethodGuesser.java index 37ea493..a6b6281 100644 --- a/src/de/qtc/rmg/operations/MethodGuesser.java +++ b/src/de/qtc/rmg/operations/MethodGuesser.java @@ -63,8 +63,10 @@ public MethodGuesser(UnicastWrapper[] remoteObjects, Set candid this.knownClientList = new ArrayList(); this.candidateSets = RMGUtils.splitSet(candidates, RMGOption.THREADS.getValue()); - if( !RMGOption.GUESS_FORCE_GUESSING.getBool() ) + if (!RMGOption.GUESS_FORCE_GUESSING.getBool()) + { remoteObjects = handleKnownMethods(remoteObjects); + } this.clientList = initClientList(remoteObjects); this.progressBar = new ProgressBar(candidates.size() * clientList.size(), 37); @@ -87,17 +89,21 @@ private List initClientList(UnicastWrapper[] remoteObjects) List remoteObjectClients = new ArrayList(); setPadding(remoteObjects); - if( !RMGOption.GUESS_DUPLICATES.getBool() ) + if (!RMGOption.GUESS_DUPLICATES.getBool()) + { remoteObjects = UnicastWrapper.handleDuplicates(remoteObjects); + } - for( UnicastWrapper o : remoteObjects ) { - + for (UnicastWrapper o : remoteObjects) + { RemoteObjectClient client = new RemoteObjectClient(o); remoteObjectClients.add(client); } - if( UnicastWrapper.hasDuplicates(remoteObjects) ) + if (UnicastWrapper.hasDuplicates(remoteObjects)) + { printDuplicates(remoteObjects); + } return remoteObjectClients; } @@ -110,10 +116,12 @@ private List initClientList(UnicastWrapper[] remoteObjects) */ private void setPadding(UnicastWrapper[] remoteObjects) { - for(UnicastWrapper o : remoteObjects) { - - if( padding < o.boundName.length() ) + for (UnicastWrapper o : remoteObjects) + { + if (padding < o.boundName.length()) + { padding = o.boundName.length(); + } } } @@ -133,17 +141,20 @@ private void printDuplicates(UnicastWrapper[] remoteObjects) Logger.lineBreak(); Logger.increaseIndent(); - for( UnicastWrapper remoteObject : remoteObjects ) { - + for (UnicastWrapper remoteObject : remoteObjects) + { String[] duplicates = remoteObject.getDuplicateBoundNames(); - if( duplicates.length == 0 ) + if (duplicates.length == 0) + { continue; + } Logger.printlnMixedBlue("-", remoteObject.boundName); Logger.increaseIndent(); - for(String dup : duplicates ) { + for (String dup : duplicates) + { Logger.printlnMixedYellow("-->", dup); } @@ -170,12 +181,15 @@ private UnicastWrapper[] handleKnownMethods(UnicastWrapper[] remoteObjects) { ArrayList unknown = new ArrayList(); - for(UnicastWrapper o : remoteObjects) { - - if(!o.isKnown()) + for (UnicastWrapper o : remoteObjects) + { + if (!o.isKnown()) + { unknown.add(o); + } - else { + else + { RemoteObjectClient knownClient = new RemoteObjectClient(o); knownClient.addRemoteMethods(RMGUtils.getKnownMethods(o.className)); @@ -183,8 +197,8 @@ private UnicastWrapper[] handleKnownMethods(UnicastWrapper[] remoteObjects) } } - if(knownClientList.size() != 0) { - + if (knownClientList.size() != 0) + { Logger.disableIfNotVerbose(); Logger.printInfoBox(); @@ -192,8 +206,10 @@ private UnicastWrapper[] handleKnownMethods(UnicastWrapper[] remoteObjects) Logger.lineBreak(); Logger.increaseIndent(); - for(RemoteObjectClient o : knownClientList) + for (RemoteObjectClient o : knownClientList) + { Logger.printlnMixedBlue("-", o.getBoundName() + " (" + o.getBoundName() + ")"); + } Logger.decreaseIndent(); Logger.lineBreak(); @@ -215,19 +231,23 @@ public void printGuessingIntro() { int count = candidates.size(); - if(count == 0) { + if (count == 0) + { Logger.eprintlnMixedYellow("List of candidate methods contains", "0", "elements."); Logger.eprintln("Please use a valid and non empty wordlist file."); RMGUtils.exit(); + } - } else if( clientList.size() == 0 ) { + else if (clientList.size() == 0) + { return; } Logger.lineBreak(); Logger.printlnMixedYellow("Starting Method Guessing on", String.valueOf(count), "method signature(s)."); - if( count == 1 ) { + if (count == 1) + { Logger.printlnMixedBlue("Method signature:", ((MethodCandidate)candidates.toArray()[0]).getSignature() + "."); } } @@ -243,7 +263,8 @@ public List guessMethods() { Logger.lineBreak(); - if( clientList.size() == 0 ) { + if (clientList.size() == 0) + { clientList.addAll(knownClientList); return clientList; } @@ -255,18 +276,23 @@ public List guessMethods() ExecutorService pool = Executors.newFixedThreadPool(RMGOption.THREADS.getValue()); - for( RemoteObjectClient client : clientList ) { - for( Set candidates : candidateSets ) { + for (RemoteObjectClient client : clientList) + { + for (Set candidates : candidateSets) + { Runnable r = new GuessingWorker(client, candidates); pool.execute(r); } } - try { + try + { pool.shutdown(); pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + } - } catch (InterruptedException e) { + catch (InterruptedException e) + { Logger.eprintln("Interrupted!"); } @@ -289,8 +315,8 @@ public List guessMethods() * * @author Tobias Neitzel (@qtc_de) */ - private class GuessingWorker implements Runnable { - + private class GuessingWorker implements Runnable + { private String boundName; private Set candidates; private RemoteObjectClient client; @@ -327,16 +353,18 @@ private void logHit(MethodCandidate candidate) * simultaneously preventing corruption of the underlying TCP stream. This allows to reuse the TCP connection * during method guessing which makes the process much faster, especially on TLS protected connections. */ - public void run() { - - for( MethodCandidate candidate : candidates ) { - - try { + public void run() + { + for (MethodCandidate candidate : candidates) + { + try + { client.guessingCall(candidate); logHit(candidate); // If there was no exception, the method exists (zero arg / valid call) + } - } catch(java.rmi.ServerException e) { - + catch (java.rmi.ServerException e) + { Throwable cause = ExceptionHandler.getCause(e); /* @@ -345,12 +373,14 @@ public void run() { * One could also attempt to catch the 'unrecognized method hash' exception from the server to match non * existing methods, but this requires an additional string compare that might be slower. */ - if( cause instanceof java.io.OptionalDataException || cause instanceof java.io.StreamCorruptedException) { + if (cause instanceof java.io.OptionalDataException || cause instanceof java.io.StreamCorruptedException) + { logHit(candidate); } + } - } catch(Exception e) { - + catch(Exception e) + { /* * If we end up here, an unexpected exception was raised that indicates a general error. */ @@ -363,8 +393,10 @@ public void run() { +writer.toString(); Logger.println(info); + } - } finally { + finally + { progressBar.taskDone(); } } From 11a30b3a52d60a84a718fc130e5f757da3688cd7 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 10 Oct 2023 08:02:42 +0200 Subject: [PATCH 10/60] Reformat RemoteObjectClient --- .../rmg/operations/RemoteObjectClient.java | 168 ++++++++++++------ 1 file changed, 118 insertions(+), 50 deletions(-) diff --git a/src/de/qtc/rmg/operations/RemoteObjectClient.java b/src/de/qtc/rmg/operations/RemoteObjectClient.java index 1ceb269..0badc22 100644 --- a/src/de/qtc/rmg/operations/RemoteObjectClient.java +++ b/src/de/qtc/rmg/operations/RemoteObjectClient.java @@ -31,8 +31,8 @@ * @author Tobias Neitzel (@qtc_de) */ @SuppressWarnings("restriction") -public class RemoteObjectClient { - +public class RemoteObjectClient +{ private ObjID objID; private UnicastRef remoteRef; @@ -110,11 +110,14 @@ public UnicastWrapper assignInterface(Class intf) { UnicastWrapper remoteObject = null; - try { + try + { remoteObject = UnicastWrapper.fromRef(remoteRef, intf); this.remoteObject = remoteObject; + } - } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { + catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) + { ExceptionHandler.internalError("RemoteObjectClient.assignInterface", "Caught unexpected exception: " + e.getClass().getName()); } @@ -164,7 +167,8 @@ public String[] getBoundNames() String[] boundNames = new String[boundNamesSize + 1]; boundNames[0] = this.boundName; - for(int ctr = 0; ctr < boundNamesSize; ctr++) { + for(int ctr = 0; ctr < boundNamesSize; ctr++) + { boundNames[ctr + 1] = remoteObject.duplicates.get(ctr).boundName; } @@ -190,21 +194,26 @@ public void gadgetCall(MethodCandidate targetMethod, Object gadget, int argument MethodArguments argumentArray = prepareArgumentArray(targetMethod, gadget, attackArgument); - try { + try + { rmi.genericCall(null, -1, targetMethod.getHash(), argumentArray, false, getMethodName(targetMethod), remoteRef); Logger.eprintln("Remote method invocation didn't cause any exception."); Logger.eprintln("This is unusual and the attack probably didn't work."); + } - } catch (Exception e) { - + catch (Exception e) + { Throwable cause = ExceptionHandler.getCause(e); - if( cause instanceof java.rmi.UnmarshalException && cause.getMessage().contains("unrecognized method hash")) { + if (cause instanceof java.rmi.UnmarshalException && cause.getMessage().contains("unrecognized method hash")) + { Logger.eprintlnMixedYellow("Method", targetMethod.getSignature(), "does not exist on this remote object."); ExceptionHandler.showStackTrace(e); + } - } else { + else + { ExceptionHandler.handleGadgetCallException(e, RMIComponent.CUSTOM, "method", randomClassName); } } @@ -230,21 +239,26 @@ public void codebaseCall(MethodCandidate targetMethod, Object gadget, int argume MethodArguments argumentArray = prepareArgumentArray(targetMethod, gadget, attackArgument); - try { + try + { rmi.genericCall(null, -1, targetMethod.getHash(), argumentArray, true, methodName, remoteRef); Logger.eprintln("Remote method invocation didn't cause any exception."); Logger.eprintln("This is unusual and the attack probably didn't work."); + } - } catch (Exception e) { - + catch (Exception e) + { Throwable cause = ExceptionHandler.getCause(e); - if( cause instanceof java.rmi.UnmarshalException && cause.getMessage().contains("unrecognized method hash")) { + if (cause instanceof java.rmi.UnmarshalException && cause.getMessage().contains("unrecognized method hash")) + { Logger.eprintlnMixedYellow("Method", targetMethod.getSignature(), "does not exist on this remote object."); ExceptionHandler.showStackTrace(e); + } - } else { + else + { ExceptionHandler.handleCodebaseException(e, gadget.getClass().getName(), RMIComponent.CUSTOM, "method", randomClassName); } } @@ -264,38 +278,54 @@ public void genericCall(MethodCandidate targetMethod, Object[] argumentArray) CtClass rtype = null; MethodArguments callArguemnts = null; - try { + try + { rtype = targetMethod.getMethod().getReturnType(); callArguemnts = RMGUtils.applyParameterTypes(targetMethod.getMethod(), argumentArray); + } - } catch(Exception e) { + catch (Exception e) + { ExceptionHandler.unexpectedException(e, "preparation", "of remote method call", true); } - try { + try + { rmi.genericCall(null, -1, targetMethod.getHash(), callArguemnts, false, getMethodName(targetMethod), remoteRef, rtype); + } - } catch( java.rmi.ServerException e ) { - + catch (java.rmi.ServerException e) + { Throwable cause = ExceptionHandler.getCause(e); - if( cause instanceof java.rmi.UnmarshalException && e.getMessage().contains("unrecognized method hash")) { + if (cause instanceof java.rmi.UnmarshalException && e.getMessage().contains("unrecognized method hash")) + { ExceptionHandler.unrecognizedMethodHash(e, "call", targetMethod.getSignature()); + } - } else if( cause instanceof java.io.InvalidClassException ) { + else if (cause instanceof java.io.InvalidClassException) + { ExceptionHandler.invalidClass(e, "RMI endpoint"); + } - } else if( cause instanceof java.lang.UnsupportedOperationException ) { + else if (cause instanceof java.lang.UnsupportedOperationException) + { ExceptionHandler.unsupportedOperationException(e, "method"); + } - } else { + else + { ExceptionHandler.unexpectedException(e, "generic call", "operation", false); } + } - } catch( java.rmi.NoSuchObjectException e ) { + catch (java.rmi.NoSuchObjectException e) + { ExceptionHandler.noSuchObjectException(e, this.objID, true); + } - } catch( Exception e ) { + catch (Exception e) + { ExceptionHandler.genericCall(e); } } @@ -322,10 +352,12 @@ public void guessingCall(MethodCandidate targetMethod) throws Exception public static List filterEmpty(List clientList) { Iterator it = clientList.iterator(); - while(it.hasNext()) { - - if( it.next().remoteMethods.isEmpty() ) + while (it.hasNext()) + { + if (it.next().remoteMethods.isEmpty()) + { it.remove(); + } } return clientList; @@ -354,8 +386,10 @@ private void printGadgetIntro(MethodCandidate targetMethod, int attackArgument) */ private UnicastRef getRemoteRefByObjID() { - if(objID == null) + if (objID == null) + { ExceptionHandler.internalError("getRemoteRefByObjID", "Function was called with missing objID."); + } return rmi.getRemoteRef(objID); } @@ -369,15 +403,20 @@ private UnicastRef getRemoteRefByObjID() */ private UnicastRef getRemoteRefByName() { - if(boundName == null || !(rmi instanceof RMIRegistryEndpoint)) + if (boundName == null || !(rmi instanceof RMIRegistryEndpoint)) + { ExceptionHandler.internalError("getRemoteRefByName", "Function was called without the required fields."); + } RMIRegistryEndpoint rmiReg = (RMIRegistryEndpoint)rmi; - try { + try + { remoteObject = rmiReg.lookup(boundName).getUnicastWrapper(); + } - } catch(Exception e) { + catch (Exception e) + { ExceptionHandler.unexpectedException(e, "remote reference lookup", "operation", true); } @@ -397,17 +436,22 @@ private int findNonPrimitiveArgument(MethodCandidate targetMethod, int position) { int attackArgument = 0; - try { + try + { attackArgument = targetMethod.getPrimitive(position); + } - } catch (CannotCompileException | NotFoundException e) { + catch (CannotCompileException | NotFoundException e) + { ExceptionHandler.unexpectedException(e, "search", "for primitive types", true); } - if( attackArgument == -1 ) { - - if( position == -1 ) + if (attackArgument == -1) + { + if (position == -1) + { Logger.eprintlnMixedYellow("No non primitive arguments were found for method signature", targetMethod.getSignature()); + } RMGUtils.exit(); } @@ -434,25 +478,34 @@ private MethodArguments prepareArgumentArray(MethodCandidate targetMethod, Objec { Object[] methodArguments = null; - try { + try + { methodArguments = RMGUtils.getArgumentArray(targetMethod.getMethod()); - } catch (Exception e) { + } + + catch (Exception e) + { ExceptionHandler.unexpectedException(e, "argument array", "construction", true); } - if( RMGOption.NO_CANARY.getBool() ) + if (RMGOption.NO_CANARY.getBool()) + { methodArguments[attackArgument] = gadget; + } - else { - + else + { Object[] payloadArray = new Object[2]; Object randomInstance = null; - try { + try + { Class randomClass = RMGUtils.makeRandomClass(); randomInstance = randomClass.newInstance(); + } - } catch (Exception e) { + catch (Exception e) + { randomInstance = new DefinitelyNonExistingClass(); } @@ -465,10 +518,13 @@ private MethodArguments prepareArgumentArray(MethodCandidate targetMethod, Objec MethodArguments callArguments = null; - try { + try + { callArguments = RMGUtils.applyParameterTypes(targetMethod.getMethod(), methodArguments); + } - } catch(Exception e) { + catch (Exception e) + { ExceptionHandler.unexpectedException(e, "parameter types", "mapping", true); } @@ -487,21 +543,33 @@ private String getMethodName(MethodCandidate targetMethod) { String methodName = ""; - try { + try + { methodName = targetMethod.getName(); - } catch (CannotCompileException | NotFoundException e) { + } + + catch (CannotCompileException | NotFoundException e) + { ExceptionHandler.unexpectedException(e, "compilation", "process", true); } return methodName; } + /** + * Returns the string representation of an RemoteObjectClient. The format is host:port:identifier, + * where the identifier is either the bound name or the ObjID associated with the RemoteObjectClient. + * + * @return String representation of the RemoteObjectClient + */ public String toString() { String identifier = this.objID == null ? this.boundName : this.objID.toString(); - if( identifier == null ) + if (identifier == null) + { identifier = ""; + } return String.format("%s:%d:%s", rmi.host, rmi.port, identifier); } From d1604c43a6d77c45cf828dba821996739a247625 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 10 Oct 2023 08:48:08 +0200 Subject: [PATCH 11/60] Add missing java.desktop dependency for spring --- docker/spring-remoting/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/spring-remoting/Dockerfile b/docker/spring-remoting/Dockerfile index 73d791c..9b8d9bf 100644 --- a/docker/spring-remoting/Dockerfile +++ b/docker/spring-remoting/Dockerfile @@ -12,7 +12,7 @@ RUN mvn clean package FROM alpine:latest AS jdk-builder RUN set -ex \ && apk add --no-cache openjdk11 \ - && /usr/lib/jvm/java-11-openjdk/bin/jlink --add-modules java.rmi,java.management.rmi,jdk.unsupported --verbose --strip-debug --compress 2 \ + && /usr/lib/jvm/java-11-openjdk/bin/jlink --add-modules java.rmi,java.management.rmi,jdk.unsupported,java.desktop --verbose --strip-debug --compress 2 \ --no-header-files --no-man-pages --output /jdk ########################################### From 92c63c30d1d98a106a1ed9dd33ccb64a33890c9d Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 10 Oct 2023 09:45:52 +0200 Subject: [PATCH 12/60] Fix method parameters for spring remoting --- docs/rmi/known-endpoints.md | 2 +- resources/known-endpoints/known-endpoints.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/rmi/known-endpoints.md b/docs/rmi/known-endpoints.md index 73e6358..a06fcca 100644 --- a/docs/rmi/known-endpoints.md +++ b/docs/rmi/known-endpoints.md @@ -330,7 +330,7 @@ ```java java.lang.String getTargetInterfaceName() - java.lang.Object invoke(org.springframework.remoting.support RemoteInvocation) + java.lang.Object invoke(org.springframework.remoting.support.RemoteInvocation invo) ``` * References: * [https://docs.spring.io/spring-framework/docs/5.3.0/javadoc-api/org/springframework/remoting/rmi/RmiInvocationHandler.html](https://docs.spring.io/spring-framework/docs/5.3.0/javadoc-api/org/springframework/remoting/rmi/RmiInvocationHandler.html) diff --git a/resources/known-endpoints/known-endpoints.yml b/resources/known-endpoints/known-endpoints.yml index 6501a47..6ba83a9 100644 --- a/resources/known-endpoints/known-endpoints.yml +++ b/resources/known-endpoints/known-endpoints.yml @@ -273,7 +273,7 @@ knownEndpoints: remoteMethods: - java.lang.String getTargetInterfaceName() - - java.lang.Object invoke(org.springframework.remoting.support RemoteInvocation) + - java.lang.Object invoke(org.springframework.remoting.support.RemoteInvocation invo) references: - https://docs.spring.io/spring-framework/docs/5.3.0/javadoc-api/org/springframework/remoting/rmi/RmiInvocationHandler.html From ff187a7f9ec971bf723d4b8a1399a039d7084a1f Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 10 Oct 2023 09:49:01 +0200 Subject: [PATCH 13/60] Update logging of SpringRemotingService --- .../rmg/springremoting/SpringRemotingService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java index 212eb49..b7da479 100644 --- a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java +++ b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java @@ -35,13 +35,13 @@ RmiServiceExporter exporter(SpringRemotingService impl) public String notRelevant() { - logger.info("Method", "notRelevant", "was called."); + logger.info("Processing call for: notRelevant()"); return "Hello World :D"; } public String execute(String command) { - logger.info("Processing call for", "String execute(String command)"); + logger.info("Processing call for: String execute(String command)"); String result = ""; try @@ -61,7 +61,7 @@ public String execute(String command) public String system(String command, String[] args) { - logger.info("Processing call for", "String system(String command, String[] args)"); + logger.info("Processing call for: String system(String command, String[] args)"); String result = ""; String[] commandArray = new String[args.length + 1]; @@ -85,13 +85,13 @@ public String system(String command, String[] args) public String upload(int size, int id, byte[] content) { - logger.info("Processing call for", "String upload(int size, int id, byte[] content)"); + logger.info("Processing call for: String upload(int size, int id, byte[] content)"); return "Upload of size " + size + " was saved as user_uploads_" + id + "."; } public int math(int num1, int num2) { - logger.info("Processing call for", "int math(int num1, int num2)"); + logger.info("Processing call for: int math(int num1, int num2)"); return num1 / num2; } @@ -119,4 +119,4 @@ private static String readFromProcess(Process p) throws IOException return result.toString(); } -} \ No newline at end of file +} From e3ca60a2bb2cf5773a7ea43c95c6b223ddfecd69 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 10 Oct 2023 09:49:33 +0200 Subject: [PATCH 14/60] Add spring-remoting as dependency --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index 8dcd936..c593c46 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,12 @@ 1.33 + + org.springframework + spring-remoting + 2.0.8 + + From 5d2ddf8ad91a360da8fc9f54054cb09aba12aced Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 10 Oct 2023 09:50:14 +0200 Subject: [PATCH 15/60] Reformat MethodCandidate --- src/de/qtc/rmg/internal/MethodCandidate.java | 96 +++++++++++++------- 1 file changed, 65 insertions(+), 31 deletions(-) diff --git a/src/de/qtc/rmg/internal/MethodCandidate.java b/src/de/qtc/rmg/internal/MethodCandidate.java index f3a7686..b344374 100644 --- a/src/de/qtc/rmg/internal/MethodCandidate.java +++ b/src/de/qtc/rmg/internal/MethodCandidate.java @@ -24,8 +24,8 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class MethodCandidate { - +public class MethodCandidate +{ private long hash; private CtMethod method; @@ -100,13 +100,14 @@ private void initialize(CtMethod method) throws NotFoundException this.argumentCount = types.length; this.hash = getCtMethodHash(method); - if( argumentCount == 0 ) { - + if (argumentCount == 0) + { this.isVoid = true; this.primitiveSize = -99; + } - } else { - + else + { this.isVoid = false; this.primitiveSize = RMGUtils.getPrimitiveSize(types); } @@ -132,10 +133,13 @@ private static long getCtMethodHash(CtMethod method) * @param methodSignature signature to compute the hash on * @return RMI method hash */ - private static long computeMethodHash(String methodSignature) { + private static long computeMethodHash(String methodSignature) + { long hash = 0; ByteArrayOutputStream sink = new ByteArrayOutputStream(127); - try { + + try + { MessageDigest md = MessageDigest.getInstance("SHA"); DataOutputStream out = new DataOutputStream(new DigestOutputStream(sink, md)); @@ -144,15 +148,24 @@ private static long computeMethodHash(String methodSignature) { // use only the first 64 bits of the digest for the hash out.flush(); byte hasharray[] = md.digest(); - for (int i = 0; i < Math.min(8, hasharray.length); i++) { + + for (int i = 0; i < Math.min(8, hasharray.length); i++) + { hash += ((long) (hasharray[i] & 0xFF)) << (i * 8); } - } catch (IOException ignore) { + } + + catch (IOException ignore) + { /* can't happen, but be deterministic anyway. */ hash = -1; - } catch (NoSuchAlgorithmException complain) { + } + + catch (NoSuchAlgorithmException complain) + { throw new SecurityException(complain.getMessage()); } + return hash; } @@ -170,17 +183,20 @@ private static long computeMethodHash(String methodSignature) { @SuppressWarnings("restriction") public void sendArguments(ObjectOutputStream oo) throws IOException { - if( this.primitiveSize == -99 ) { - + if (this.primitiveSize == -99) + { oo.flush(); + } - } else if( this.primitiveSize == -1 ) { - + else if (this.primitiveSize == -1) + { oo.flush(); RawObjectOutputStream rout = new RawObjectOutputStream(oo); rout.writeRaw(sun.rmi.transport.TransportConstants.Ping); + } - } else { + else + { oo.write(new byte[this.primitiveSize]); oo.writeByte(1); } @@ -208,11 +224,15 @@ public CtClass[] getParameterTypes() throws CannotCompileException, NotFoundExce */ public String getName() throws CannotCompileException, NotFoundException { - if(this.method != null) + if (this.method != null) + { return this.getMethod().getName(); + } else + { return "method"; + } } /** @@ -244,14 +264,16 @@ public int getPrimitive(int selected) throws NotFoundException, CannotCompileExc { CtClass[] types = this.getParameterTypes(); - if(selected != -1) { - - if( selected >= types.length ) { + if (selected != -1) + { + if (selected >= types.length) + { Logger.eprintlnMixedYellow("Specified argument position", String.valueOf(selected), "is out of bounds."); return -1; } - if( types[selected].isPrimitive() ) { + if (types[selected].isPrimitive()) + { Logger.eprintlnMixedYellow("Specified argument position", String.valueOf(selected), "is a primitive type."); return -1; } @@ -260,17 +282,22 @@ public int getPrimitive(int selected) throws NotFoundException, CannotCompileExc } int result = -1; - for(int ctr = 0; ctr < types.length; ctr++) { - - if(!types[ctr].isPrimitive()) { - - if( types[ctr].getName().equals("java.lang.String") ) + for (int ctr = 0; ctr < types.length; ctr++) + { + if (!types[ctr].isPrimitive()) + { + if (types[ctr].getName().equals("java.lang.String")) + { result = ctr; + } else + { return ctr; + } } } + return result; } @@ -323,7 +350,8 @@ public boolean isVoid() */ public CtMethod getMethod() throws CannotCompileException, NotFoundException { - if( this.method == null ) { + if (this.method == null) + { MethodCandidate tmp = new MethodCandidate(this.getSignature()); this.method = tmp.getMethod(); } @@ -349,10 +377,13 @@ public String getArgumentTypeName(int position) { String typeName = "None"; - try { + try + { typeName = this.method.getParameterTypes()[position].getName(); + } - } catch( Exception e ) { + catch (Exception e) + { ExceptionHandler.unexpectedException(e, "parameter type", "determination", true); } @@ -365,8 +396,10 @@ public String getArgumentTypeName(int position) @Override public boolean equals(Object o) { - if(!(o instanceof MethodCandidate)) + if (!(o instanceof MethodCandidate)) + { return false; + } MethodCandidate other = (MethodCandidate)o; return this.hash == other.getHash(); @@ -376,7 +409,8 @@ public boolean equals(Object o) * MethodCandidates are hashed according to their method hash. */ @Override - public int hashCode(){ + public int hashCode() + { return Long.hashCode(this.hash); } } From 677957152fd8fe670778dbc56ad3cd831ce57c8f Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 10 Oct 2023 09:51:12 +0200 Subject: [PATCH 16/60] Start to add spring-remoting support --- src/de/qtc/rmg/internal/RMGOption.java | 4 +- .../rmg/operations/RemoteObjectClient.java | 7 + src/de/qtc/rmg/utils/SpringRemoting.java | 135 ++++++++++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/de/qtc/rmg/utils/SpringRemoting.java diff --git a/src/de/qtc/rmg/internal/RMGOption.java b/src/de/qtc/rmg/internal/RMGOption.java index 9a5e33b..269ae62 100644 --- a/src/de/qtc/rmg/internal/RMGOption.java +++ b/src/de/qtc/rmg/internal/RMGOption.java @@ -108,7 +108,9 @@ public enum RMGOption { SOCKET_FACTORY_PLAIN("--socket-factory-plain", "enforce plaintext connections from dynamically created socket factories", Arguments.storeTrue(), RMGOptionGroup.CONNECTION), SOCKET_FACTORY_SSL("--socket-factory-ssl", "enforce SSL connections from dynamically created socket factories", Arguments.storeTrue(), RMGOptionGroup.CONNECTION), - SOCKET_FACTORY("--socket-factory", "dynamically create a socket factory class with the specified name", Arguments.store(), RMGOptionGroup.CONNECTION, "classname"); + SOCKET_FACTORY("--socket-factory", "dynamically create a socket factory class with the specified name", Arguments.store(), RMGOptionGroup.CONNECTION, "classname"), + + SPRING_REMOTING("--spring-remoting", "enforce method calls to be dispatched via spring remoting", Arguments.storeTrue(), RMGOptionGroup.CONNECTION); public final String name; public final String description; diff --git a/src/de/qtc/rmg/operations/RemoteObjectClient.java b/src/de/qtc/rmg/operations/RemoteObjectClient.java index 0badc22..5f68c94 100644 --- a/src/de/qtc/rmg/operations/RemoteObjectClient.java +++ b/src/de/qtc/rmg/operations/RemoteObjectClient.java @@ -16,6 +16,7 @@ import de.qtc.rmg.networking.RMIRegistryEndpoint; import de.qtc.rmg.utils.DefinitelyNonExistingClass; import de.qtc.rmg.utils.RMGUtils; +import de.qtc.rmg.utils.SpringRemoting; import de.qtc.rmg.utils.UnicastWrapper; import javassist.CannotCompileException; import javassist.CtClass; @@ -275,6 +276,12 @@ public void codebaseCall(MethodCandidate targetMethod, Object gadget, int argume */ public void genericCall(MethodCandidate targetMethod, Object[] argumentArray) { + if (SpringRemoting.isRemotingCall(remoteObject, targetMethod)) + { + argumentArray = new Object[] { SpringRemoting.buildRemoteInvocation(targetMethod, argumentArray) }; + targetMethod = SpringRemoting.getInvokeMethod(); + } + CtClass rtype = null; MethodArguments callArguemnts = null; diff --git a/src/de/qtc/rmg/utils/SpringRemoting.java b/src/de/qtc/rmg/utils/SpringRemoting.java new file mode 100644 index 0000000..ad391b0 --- /dev/null +++ b/src/de/qtc/rmg/utils/SpringRemoting.java @@ -0,0 +1,135 @@ +package de.qtc.rmg.utils; + +import org.springframework.remoting.support.RemoteInvocation; + +import de.qtc.rmg.internal.ExceptionHandler; +import de.qtc.rmg.internal.MethodCandidate; +import de.qtc.rmg.internal.RMGOption; +import javassist.CannotCompileException; +import javassist.CtClass; +import javassist.NotFoundException; + +/** + * SpringRemoting represents a wrapper around regular Java RMI. Exposed methods are not directly available via + * RemoteObjects, but are invoked using a dispatcher object that supports an invoke method. This class contains + * functions to convert an ordinary RMI method call into a SpringRemoting call. + * + * @author Tobias Neitzel (@qtc_de) + */ +public class SpringRemoting +{ + public final static String invocationHandlerClass = "org.springframework.remoting.rmi.RmiInvocationHandler"; + public final static String methodGetStr = "java.lang.String getTargetInterfaceName()"; + public final static String methodInvokeStr = "java.lang.Object invoke(org.springframework.remoting.support.RemoteInvocation invo)"; + + private static MethodCandidate methodGet; + private static MethodCandidate methodInvoke; + + /** + * Return a MethodCandidate for the getTargetInterfaceName method that is exposed by the RmiInvocationHandler + * remote object. + * + * @return method candidate for the getTargetInterfaceName method + */ + public static MethodCandidate getInterfaceNameMethod() + { + if (methodGet == null) + { + try + { + methodGet = new MethodCandidate(methodGetStr); + } + + catch (CannotCompileException | NotFoundException e) + { + ExceptionHandler.internalError("SpringRemoting.getInterfaceMethod", e.getMessage()); + } + } + + return methodGet; + } + + /** + * Return a MethodCandidate for the invoke method that is exposed by the RmiInvocationHandler + * remote object. + * + * @return method candidate for the invoke method + */ + public static MethodCandidate getInvokeMethod() + { + if (methodInvoke == null) + { + try + { + methodInvoke = new MethodCandidate(methodInvokeStr); + } + + catch (CannotCompileException | NotFoundException e) + { + ExceptionHandler.internalError("SpringRemoting.getInterfaceMethod", e.getMessage()); + } + } + + return methodInvoke; + } + + public static boolean isRemotingCall(RemoteObjectWrapper remoteObject, MethodCandidate targetMethod) + { + if (RMGOption.SPRING_REMOTING.getBool()) + { + return true; + } + + if (remoteObject == null || !remoteObject.className.equals(invocationHandlerClass)) + { + return false; + } + + long targetHash = targetMethod.getHash(); + + if (targetHash == getInvokeMethod().getHash() || targetHash == getInterfaceNameMethod().getHash()) + { + return false; + } + + return true; + } + + public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMethod, Object[] args) + { + RemoteInvocation invo = new RemoteInvocation(); + + try + { + String methodName = targetMethod.getName(); + CtClass[] argTypes = targetMethod.getParameterTypes(); + + invo.setMethodName(methodName); + Class[] parameterTypes = new Class[args.length]; + + try + { + for (int ctr = 0; ctr < args.length; ctr++) + { + Class cls = Class.forName(argTypes[ctr].getName()); + parameterTypes[ctr] = cls; + } + } + + catch (ClassNotFoundException e) + { + ExceptionHandler.internalError("SpringRemoting.buildRemoteInvocation", e.getMessage()); + } + + invo.setArguments(args); + invo.setParameterTypes(parameterTypes); + } + + catch (CannotCompileException | NotFoundException e) + { + ExceptionHandler.cannotCompile(e, "while building", "Spring RemoteInvocation", true); + } + + return invo; + } +} From e6ec810215c4a87bdc7e418a97aba9ac68c81fce Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 15 Oct 2023 08:16:08 +0200 Subject: [PATCH 17/60] Refactor Spring Remoting implementation --- src/de/qtc/rmg/io/Formatter.java | 32 +++++++++++++- .../rmg/operations/RemoteObjectClient.java | 9 ++-- .../qtc/rmg/plugin/ReturnValueProvider.java | 16 +++++++ src/de/qtc/rmg/utils/RemoteObjectWrapper.java | 28 +++++++++++-- ...moting.java => SpringRemotingWrapper.java} | 42 +++++++++++++------ 5 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 src/de/qtc/rmg/plugin/ReturnValueProvider.java rename src/de/qtc/rmg/utils/{SpringRemoting.java => SpringRemotingWrapper.java} (78%) diff --git a/src/de/qtc/rmg/io/Formatter.java b/src/de/qtc/rmg/io/Formatter.java index b690111..b1755cc 100644 --- a/src/de/qtc/rmg/io/Formatter.java +++ b/src/de/qtc/rmg/io/Formatter.java @@ -13,6 +13,7 @@ import de.qtc.rmg.operations.RemoteObjectClient; import de.qtc.rmg.utils.ActivatableWrapper; import de.qtc.rmg.utils.RemoteObjectWrapper; +import de.qtc.rmg.utils.SpringRemotingWrapper; import de.qtc.rmg.utils.UnicastWrapper; /** @@ -245,11 +246,40 @@ private void listVulnerabilities(List vulns) */ private void printRemoteRef(RemoteObjectWrapper wrapper) { - if (wrapper instanceof UnicastWrapper) + if (wrapper instanceof SpringRemotingWrapper) + { + printSpringRemoting((SpringRemotingWrapper)wrapper); + } + + else if (wrapper instanceof UnicastWrapper) + { printUnicastRef((UnicastWrapper)wrapper); + } else + { printActivatableRef((ActivatableWrapper)wrapper); + } + } + + /** + * Print information on a SpringRemotingWrapper. This information includes the real + * interface name that can be accessed via the spring remoting wrapper and all information + * that is printed by the printUnicastRef method. + * + * @param ref SpringRemotingWrapper containing the wrapper + */ + private void printSpringRemoting(SpringRemotingWrapper ref) + { + String interfaceName = ref.getInterfaceName(); + + if (interfaceName != null) + { + Logger.print(" "); + Logger.printlnPlainMixedPurple("Spring Remoting Interface:", interfaceName); + } + + printUnicastRef((UnicastWrapper)ref); } /** diff --git a/src/de/qtc/rmg/operations/RemoteObjectClient.java b/src/de/qtc/rmg/operations/RemoteObjectClient.java index 5f68c94..bd72f68 100644 --- a/src/de/qtc/rmg/operations/RemoteObjectClient.java +++ b/src/de/qtc/rmg/operations/RemoteObjectClient.java @@ -16,7 +16,7 @@ import de.qtc.rmg.networking.RMIRegistryEndpoint; import de.qtc.rmg.utils.DefinitelyNonExistingClass; import de.qtc.rmg.utils.RMGUtils; -import de.qtc.rmg.utils.SpringRemoting; +import de.qtc.rmg.utils.SpringRemotingWrapper; import de.qtc.rmg.utils.UnicastWrapper; import javassist.CannotCompileException; import javassist.CtClass; @@ -276,10 +276,10 @@ public void codebaseCall(MethodCandidate targetMethod, Object gadget, int argume */ public void genericCall(MethodCandidate targetMethod, Object[] argumentArray) { - if (SpringRemoting.isRemotingCall(remoteObject, targetMethod)) + if (remoteObject instanceof SpringRemotingWrapper && ((SpringRemotingWrapper)remoteObject).isRemotingCall(targetMethod)) { - argumentArray = new Object[] { SpringRemoting.buildRemoteInvocation(targetMethod, argumentArray) }; - targetMethod = SpringRemoting.getInvokeMethod(); + argumentArray = new Object[] { SpringRemotingWrapper.buildRemoteInvocation(targetMethod, argumentArray) }; + targetMethod = SpringRemotingWrapper.getInvokeMethod(); } CtClass rtype = null; @@ -359,6 +359,7 @@ public void guessingCall(MethodCandidate targetMethod) throws Exception public static List filterEmpty(List clientList) { Iterator it = clientList.iterator(); + while (it.hasNext()) { if (it.next().remoteMethods.isEmpty()) diff --git a/src/de/qtc/rmg/plugin/ReturnValueProvider.java b/src/de/qtc/rmg/plugin/ReturnValueProvider.java new file mode 100644 index 0000000..eb6c846 --- /dev/null +++ b/src/de/qtc/rmg/plugin/ReturnValueProvider.java @@ -0,0 +1,16 @@ +package de.qtc.rmg.plugin; + +public class ReturnValueProvider implements IResponseHandler +{ + private Object value = null; + + public void handleResponse(Object responseObject) + { + value = responseObject; + } + + public Object getValue() + { + return value; + } +} diff --git a/src/de/qtc/rmg/utils/RemoteObjectWrapper.java b/src/de/qtc/rmg/utils/RemoteObjectWrapper.java index d3b63ab..d41d2b3 100644 --- a/src/de/qtc/rmg/utils/RemoteObjectWrapper.java +++ b/src/de/qtc/rmg/utils/RemoteObjectWrapper.java @@ -84,16 +84,32 @@ public static RemoteObjectWrapper getInstance(Remote remote) throws IllegalArgum public static RemoteObjectWrapper getInstance(Remote remote, String boundName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { RemoteObjectWrapper wrapper = null; + RemoteRef ref = RMGUtils.extractRef(remote); + String className = RMGUtils.getClassName(remote); if (ref instanceof UnicastRef) - wrapper = new UnicastWrapper(remote, boundName, (UnicastRef)ref); + { + if (className.equals(SpringRemotingWrapper.invocationHandlerClass)) + { + wrapper = new SpringRemotingWrapper(remote, boundName, (UnicastRef)ref); + } + + else + { + wrapper = new UnicastWrapper(remote, boundName, (UnicastRef)ref); + } + } else if (ref.getClass().getName().contains("ActivatableRef")) + { wrapper = new ActivatableWrapper(remote, boundName, ref); + } else + { ExceptionHandler.internalError("RemoteObjectWrapper.getInstance", "Unexpected reference type"); + } return wrapper; } @@ -188,14 +204,18 @@ public static UnicastWrapper[] getUnicastWrappers(RemoteObjectWrapper[] wrappers { if (wrappers[ctr] instanceof UnicastWrapper) { - unicastWrappers[ctr] = (UnicastWrapper) wrappers[ctr]; + unicastWrappers[ctr] = (UnicastWrapper)wrappers[ctr]; } else { - try { + try + { unicastWrappers[ctr] = ((ActivatableWrapper)wrappers[ctr]).activate(); - } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { + } + + catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) + { ExceptionHandler.unexpectedException(e, "activate", "call", true); } } diff --git a/src/de/qtc/rmg/utils/SpringRemoting.java b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java similarity index 78% rename from src/de/qtc/rmg/utils/SpringRemoting.java rename to src/de/qtc/rmg/utils/SpringRemotingWrapper.java index ad391b0..fec0e4f 100644 --- a/src/de/qtc/rmg/utils/SpringRemoting.java +++ b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java @@ -1,13 +1,18 @@ package de.qtc.rmg.utils; +import java.rmi.Remote; + import org.springframework.remoting.support.RemoteInvocation; import de.qtc.rmg.internal.ExceptionHandler; import de.qtc.rmg.internal.MethodCandidate; -import de.qtc.rmg.internal.RMGOption; +import de.qtc.rmg.operations.RemoteObjectClient; +import de.qtc.rmg.plugin.PluginSystem; +import de.qtc.rmg.plugin.ReturnValueProvider; import javassist.CannotCompileException; import javassist.CtClass; import javassist.NotFoundException; +import sun.rmi.server.UnicastRef; /** * SpringRemoting represents a wrapper around regular Java RMI. Exposed methods are not directly available via @@ -16,7 +21,8 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class SpringRemoting +@SuppressWarnings("restriction") +public class SpringRemotingWrapper extends UnicastWrapper { public final static String invocationHandlerClass = "org.springframework.remoting.rmi.RmiInvocationHandler"; public final static String methodGetStr = "java.lang.String getTargetInterfaceName()"; @@ -25,6 +31,26 @@ public class SpringRemoting private static MethodCandidate methodGet; private static MethodCandidate methodInvoke; + private static String interfaceName; + + public SpringRemotingWrapper(Remote remoteObject, String boundName, UnicastRef ref) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException + { + super(remoteObject, boundName, ref); + + ReturnValueProvider respHandler = new ReturnValueProvider(); + PluginSystem.setResponeHandler(respHandler); + + RemoteObjectClient client = new RemoteObjectClient(this); + client.genericCall(getInterfaceNameMethod(), new Object[] {}); + + interfaceName = (String)respHandler.getValue(); + } + + public String getInterfaceName() + { + return interfaceName; + } + /** * Return a MethodCandidate for the getTargetInterfaceName method that is exposed by the RmiInvocationHandler * remote object. @@ -73,18 +99,8 @@ public static MethodCandidate getInvokeMethod() return methodInvoke; } - public static boolean isRemotingCall(RemoteObjectWrapper remoteObject, MethodCandidate targetMethod) + public boolean isRemotingCall(MethodCandidate targetMethod) { - if (RMGOption.SPRING_REMOTING.getBool()) - { - return true; - } - - if (remoteObject == null || !remoteObject.className.equals(invocationHandlerClass)) - { - return false; - } - long targetHash = targetMethod.getHash(); if (targetHash == getInvokeMethod().getHash() || targetHash == getInterfaceNameMethod().getHash()) From abe28924704531ddcb8575f2612ef2fb63128c29 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Mon, 16 Oct 2023 09:48:05 +0200 Subject: [PATCH 18/60] Start to implement spring-remoting guessing --- src/de/qtc/rmg/internal/MethodArguments.java | 26 +- src/de/qtc/rmg/io/Formatter.java | 92 ++++--- src/de/qtc/rmg/operations/Dispatcher.java | 224 ++++++++++++------ src/de/qtc/rmg/operations/MethodGuesser.java | 92 ++++++- .../rmg/operations/RemoteObjectClient.java | 13 + src/de/qtc/rmg/utils/RMGUtils.java | 6 +- src/de/qtc/rmg/utils/RemoteObjectWrapper.java | 42 +++- .../qtc/rmg/utils/SpringRemotingWrapper.java | 66 +++++- src/de/qtc/rmg/utils/UnicastWrapper.java | 2 +- 9 files changed, 418 insertions(+), 145 deletions(-) diff --git a/src/de/qtc/rmg/internal/MethodArguments.java b/src/de/qtc/rmg/internal/MethodArguments.java index d4d86de..40ed33d 100644 --- a/src/de/qtc/rmg/internal/MethodArguments.java +++ b/src/de/qtc/rmg/internal/MethodArguments.java @@ -28,8 +28,8 @@ * @author Tobias Neitzel (@qtc_de) */ @SuppressWarnings("rawtypes") -public class MethodArguments implements Iterable>, Iterator> { - +public class MethodArguments implements Iterable>, Iterator> +{ private int size = 0; private int capacity = 0; private int currentIndex = 0; @@ -43,24 +43,38 @@ public MethodArguments(int capacity) this.methodArguments = new Pair[capacity]; } + @SuppressWarnings("unchecked") + public MethodArguments(Object argumentObject, Class argumentClass) + { + this.capacity = 1; + this.methodArguments = new Pair[capacity]; + + methodArguments[size++] = new Pair(argumentObject, argumentClass); + } + @Override - public Iterator> iterator() { + public Iterator> iterator() + { return this; } @Override - public boolean hasNext() { + public boolean hasNext() + { return currentIndex < size; } @Override - public Pair next() { + public Pair next() + { return methodArguments[currentIndex++]; } public void add(Object argumentObject, Class argumentClass) { - if(size < capacity) + if (size < capacity) + { methodArguments[size++] = new Pair(argumentObject, argumentClass); + } } } diff --git a/src/de/qtc/rmg/io/Formatter.java b/src/de/qtc/rmg/io/Formatter.java index b1755cc..b3556b1 100644 --- a/src/de/qtc/rmg/io/Formatter.java +++ b/src/de/qtc/rmg/io/Formatter.java @@ -21,8 +21,8 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class Formatter { - +public class Formatter +{ /** * Creates a formatted list of available bound names and their corresponding classes. Classes * are divided in known classes (classes that are available on the current class path) and @@ -37,26 +37,32 @@ public void listBoundNames(RemoteObjectWrapper[] remoteObjects) Logger.lineBreak(); Logger.increaseIndent(); - if( remoteObjects == null || remoteObjects.length == 0 ) { + if (remoteObjects == null || remoteObjects.length == 0) + { Logger.println("- No objects are bound to the registry."); return; } - for(RemoteObjectWrapper remoteObject : remoteObjects) { - + for (RemoteObjectWrapper remoteObject : remoteObjects) + { Logger.printlnMixedYellow("-", remoteObject.boundName); - if( remoteObject.remoteObject == null) + if (remoteObject.remoteObject == null) + { continue; + } Logger.increaseIndent(); - if( remoteObject.isKnown() ) { - Logger.printMixedBlue("-->", remoteObject.className, ""); + if (remoteObject.isKnown()) + { + Logger.printMixedBlue("-->", remoteObject.getInterfaceName(), ""); remoteObject.knownEndpoint.printEnum(); + } - } else { - Logger.printMixedBlue("-->", remoteObject.className); + else + { + Logger.printMixedBlue("-->", remoteObject.getInterfaceName()); Logger.printlnPlainMixedPurple("", "(unknown class)"); } @@ -74,7 +80,8 @@ public void listBoundNames(RemoteObjectWrapper[] remoteObjects) */ public void listGuessedMethods(List results) { - if( results.isEmpty() ) { + if (results.isEmpty()) + { Logger.printlnBlue("No remote methods identified :("); return; } @@ -83,14 +90,15 @@ public void listGuessedMethods(List results) Logger.lineBreak(); Logger.increaseIndent(); - for(RemoteObjectClient client : results ) { - + for (RemoteObjectClient client : results) + { List methods = client.remoteMethods; Logger.printlnMixedBlue("-", String.join(" == ", client.getBoundNames())); Logger.increaseIndent(); - for( MethodCandidate m : methods ) { + for (MethodCandidate m : methods) + { Logger.printlnMixedYellow("-->", m.getSignature()); } @@ -113,19 +121,21 @@ public void listCodebases() Logger.increaseIndent(); HashMap> codebases = CodebaseCollector.getCodebases(); - if(codebases.isEmpty()) { + if (codebases.isEmpty()) + { Logger.printlnMixedYellow("- The remote server", "does not", "expose any codebases."); Logger.decreaseIndent(); return; } - for( Entry> item : codebases.entrySet() ) { - + for (Entry> item : codebases.entrySet()) + { Logger.printlnMixedYellow("-", item.getKey()); Logger.increaseIndent(); Iterator iterator = item.getValue().iterator(); - while( iterator.hasNext() ) { + while (iterator.hasNext()) + { Logger.printlnMixedBlue("-->", iterator.next()); } @@ -153,8 +163,10 @@ public void listKnownEndpoint(KnownEndpoint knownEndpoint) Logger.printlnBlue("Class Name:"); Logger.increaseIndent(); - for(String className : knownEndpoint.getClassName()) + for (String className : knownEndpoint.getClassName()) + { Logger.printlnMixedYellow("-", className); + } Logger.decreaseIndent(); Logger.lineBreak(); @@ -164,8 +176,10 @@ public void listKnownEndpoint(KnownEndpoint knownEndpoint) String[] lines = knownEndpoint.getDescription().split("\n"); - for( String line : lines) + for (String line : lines) + { Logger.printlnYellow(line); + } Logger.decreaseIndent(); Logger.lineBreak(); @@ -173,8 +187,10 @@ public void listKnownEndpoint(KnownEndpoint knownEndpoint) Logger.printlnBlue("Remote Methods:"); Logger.increaseIndent(); - for(String remoteMethod : knownEndpoint.getRemoteMethods()) + for (String remoteMethod : knownEndpoint.getRemoteMethods()) + { Logger.printlnMixedYellow("-", remoteMethod); + } Logger.decreaseIndent(); Logger.lineBreak(); @@ -182,8 +198,10 @@ public void listKnownEndpoint(KnownEndpoint knownEndpoint) Logger.printlnBlue("References:"); Logger.increaseIndent(); - for(String reference : knownEndpoint.getReferences()) + for (String reference : knownEndpoint.getReferences()) + { Logger.printlnMixedYellow("-", reference); + } Logger.decreaseIndent(); listVulnerabilities(knownEndpoint.getVulnerabilities()); @@ -198,15 +216,17 @@ public void listKnownEndpoint(KnownEndpoint knownEndpoint) */ private void listVulnerabilities(List vulns) { - if( vulns == null || vulns.size() == 0 ) + if (vulns == null || vulns.size() == 0) + { return; + } Logger.lineBreak(); Logger.printlnBlue("Vulnerabilities:"); Logger.increaseIndent(); - for( Vulnerability vuln : vulns ) { - + for (Vulnerability vuln : vulns) + { Logger.lineBreak(); Logger.printlnBlue("-----------------------------------"); @@ -222,8 +242,10 @@ private void listVulnerabilities(List vulns) String[] lines = vuln.getDescription().split("\n"); - for( String line : lines) + for (String line : lines) + { Logger.printlnYellow(line); + } Logger.decreaseIndent(); Logger.lineBreak(); @@ -231,8 +253,10 @@ private void listVulnerabilities(List vulns) Logger.printlnBlue("References:"); Logger.increaseIndent(); - for(String reference : vuln.getReferences()) + for (String reference : vuln.getReferences()) + { Logger.printlnMixedYellow("-", reference); + } Logger.decreaseIndent(); } @@ -290,14 +314,16 @@ private void printSpringRemoting(SpringRemotingWrapper ref) */ private void printUnicastRef(UnicastWrapper ref) { - if(ref == null || ref.remoteObject == null) + if (ref == null || ref.remoteObject == null) + { return; + } Logger.print(" "); Logger.printPlainMixedBlue("Endpoint:", ref.getTarget()); - switch( ref.isTLSProtected() ) { - + switch (ref.isTLSProtected()) + { case 1: Logger.printPlainMixedGreen(" TLS:", "yes"); break; @@ -323,8 +349,10 @@ private void printUnicastRef(UnicastWrapper ref) */ private void printActivatableRef(ActivatableWrapper ref) { - if(ref == null || ref.remoteObject == null) + if (ref == null || ref.remoteObject == null) + { return; + } Logger.print(" "); Logger.printPlainMixedBlue("Activator:", ref.getActivatorEndpoint()); @@ -332,6 +360,8 @@ private void printActivatableRef(ActivatableWrapper ref) UnicastWrapper unicastRef = ref.getActivated(); if (unicastRef != null) + { printUnicastRef(unicastRef); + } } } diff --git a/src/de/qtc/rmg/operations/Dispatcher.java b/src/de/qtc/rmg/operations/Dispatcher.java index 4ed4ca4..d72af47 100644 --- a/src/de/qtc/rmg/operations/Dispatcher.java +++ b/src/de/qtc/rmg/operations/Dispatcher.java @@ -44,8 +44,8 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class Dispatcher { - +public class Dispatcher +{ private ArgumentHandler p; private String[] boundNames = null; @@ -71,7 +71,9 @@ public Dispatcher(ArgumentHandler p) private void obtainBoundNames() throws NoSuchObjectException { if(boundNames != null) + { return; + } boundNames = getRegistry().getBoundNames(); } @@ -92,19 +94,26 @@ private void obtainBoundObjects() throws NoSuchObjectException { int retryCount = 0; - if( boundNames == null ) + if (boundNames == null) + { obtainBoundNames(); + } while (retryCount < 5) { - try { + try + { remoteObjects = getRegistry().lookup(boundNames); return; + } - } catch (java.rmi.UnmarshalException e) { + catch (java.rmi.UnmarshalException e) + { retryCount += 1; + } - } catch( Exception e ) { + catch (Exception e) + { ExceptionHandler.unexpectedException(e, "lookup", "operation", true); } } @@ -115,15 +124,20 @@ private void obtainBoundObjects() throws NoSuchObjectException */ private void createMethodCandidate() { - if( !RMGOption.TARGET_SIGNATURE.notNull() ) + if (!RMGOption.TARGET_SIGNATURE.notNull()) + { return; + } String signature = RMGOption.TARGET_SIGNATURE.getValue(); - try { + try + { candidate = new MethodCandidate(signature); + } - } catch (CannotCompileException | NotFoundException e) { + catch (CannotCompileException | NotFoundException e) + { ExceptionHandler.invalidSignature(signature); } } @@ -162,8 +176,10 @@ private RMIRegistryEndpoint getRegistry() */ private RMIRegistryEndpoint getRegistry(RMIEndpoint rmi) { - if(rmiReg == null) + if (rmiReg == null) + { rmiReg = new RMIRegistryEndpoint(rmi); + } return rmiReg; } @@ -178,7 +194,8 @@ private RemoteObjectClient getRemoteObjectClient(RMIEndpoint rmi) { RMGOption.requireOneOf(RMGOption.TARGET_OBJID, RMGOption.TARGET_BOUND_NAME, RMGOption.TARGET_COMPONENT); - if(RMGOption.TARGET_BOUND_NAME.isNull() && RMGOption.TARGET_OBJID.isNull()) { + if (RMGOption.TARGET_BOUND_NAME.isNull() && RMGOption.TARGET_OBJID.isNull()) + { RMIComponent component = p.getComponent(); RMGOption.TARGET_OBJID.setValue( RMGUtils.getObjIDByComponent(component).toString() ); } @@ -196,14 +213,19 @@ private RemoteObjectClient getRemoteObjectClient(RMIEndpoint rmi) */ private RemoteObjectClient getRemoteObjectClient(String objIDString, String boundName, RMIEndpoint rmi) { - if( objIDString != null ) { + if (objIDString != null) + { ObjID objID = RMGUtils.parseObjID(objIDString); return new RemoteObjectClient(rmi, objID); + } - } else if( boundName != null ) { + else if (boundName != null) + { return new RemoteObjectClient(getRegistry(rmi), boundName); + } - } else { + else + { ExceptionHandler.missingTarget(p.getAction().name()); return null; } @@ -218,8 +240,10 @@ private RemoteObjectClient getRemoteObjectClient(String objIDString, String boun */ private void writeSamples(List results) { - if( results.size() == 0 ) + if (results.size() == 0) + { return; + } String templateFolder = RMGOption.GUESS_TEMPLATE_FOLDER.getValue(); String sampleFolder = RMGOption.GUESS_SAMPLE_FOLDER.getValue(); @@ -231,31 +255,38 @@ private void writeSamples(List results) Logger.lineBreak(); Logger.increaseIndent(); - try { + try + { SampleWriter writer = new SampleWriter(templateFolder, sampleFolder, sslValue, followRedirect); - for(RemoteObjectClient client: results) { - + for (RemoteObjectClient client: results) + { RemoteObjectWrapper remoteObject = client.remoteObject; - for(String boundName : client.getBoundNames()) { - + for (String boundName : client.getBoundNames()) + { Logger.printlnMixedYellow("Creating samples for bound name", boundName + "."); Logger.increaseIndent(); - if(!remoteObject.isKnown()) - writer.createInterface(boundName, remoteObject.className, client.remoteMethods); + if (!remoteObject.isKnown()) + { + writer.createInterface(boundName, remoteObject.getInterfaceName(), client.remoteMethods); + } - writer.createSamples(boundName, remoteObject.className, !remoteObject.isKnown(), client.remoteMethods, getRMIEndpoint()); + writer.createSamples(boundName, remoteObject.getInterfaceName(), !remoteObject.isKnown(), client.remoteMethods, getRMIEndpoint()); Logger.decreaseIndent(); } } + } - } catch (IOException | CannotCompileException | NotFoundException e) { + catch (IOException | CannotCompileException | NotFoundException e) + { ExceptionHandler.unexpectedException(e, "sample", "creation", true); + } - } catch (UnexpectedCharacterException e) { + catch (UnexpectedCharacterException e) + { Logger.eprintlnMixedYellow("Caught", "UnexpectedCharacterException", "during sample creation."); Logger.eprintln("This is caused by special characters within bound- or classes names."); Logger.eprintlnMixedYellow("You can enforce sample creation with the", "--trusted", "switch."); @@ -279,15 +310,21 @@ private Set getCandidates() boolean zeroArg = RMGOption.GUESS_ZERO_ARG.getBool(); boolean updateWordlist = RMGOption.GUESS_UPDATE.getBool(); - if( candidate != null ) { + if (candidate != null) + { candidates.add(candidate); + } - } else { - - try { + else + { + try + { WordlistHandler wlHandler = new WordlistHandler(wordlistFile, wordlistFolder, updateWordlist, zeroArg); candidates = wlHandler.getWordlistMethods(); - } catch( IOException e ) { + } + + catch (IOException e) + { Logger.eprintlnMixedYellow("Caught", "IOException", "while reading wordlist file(s)."); ExceptionHandler.stackTrace(e); RMGUtils.exit(); @@ -319,20 +356,23 @@ public void dispatchSerial() RMIEndpoint rmi = getRMIEndpoint(); RMIComponent component = p.getComponent(); - if( component == null ) { - - if( candidate == null ) + if (component == null) + { + if (candidate == null) + { ExceptionHandler.missingSignature(); + } int argumentPosition = RMGOption.ARGUMENT_POS.getValue(); RemoteObjectClient client = getRemoteObjectClient(rmi); client.gadgetCall(candidate, p.getGadget(), argumentPosition); + } - } else { - - switch( component ) { - + else + { + switch (component) + { case ACTIVATOR: ActivationClient act = new ActivationClient(rmi); act.gadgetCall(p.getGadget()); @@ -368,11 +408,15 @@ public void dispatchCall() RMIEndpoint rmi = getRMIEndpoint(); Object[] argumentArray = p.getCallArguments(); - if( candidate == null ) + if (candidate == null) + { ExceptionHandler.missingSignature(); + } - if( argumentArray.length != candidate.getArgumentCount() ) + if (argumentArray.length != candidate.getArgumentCount()) + { ExceptionHandler.wrongArgumentCount(candidate.getArgumentCount(), argumentArray.length); + } RemoteObjectClient client = getRemoteObjectClient(rmi); client.genericCall(candidate, argumentArray); @@ -396,18 +440,23 @@ public void dispatchCodebase() RMIComponent component = p.getComponent(); int argumentPosition = RMGOption.ARGUMENT_POS.getValue(); - try { + try + { payload = RMGUtils.makeSerializableClass(className, RMGOption.PAYLOAD_SERIAL_VERSION_UID.getValue()); payload = ((Class)payload).newInstance(); + } - } catch (CannotCompileException | InstantiationException | IllegalAccessException e) { + catch (CannotCompileException | InstantiationException | IllegalAccessException e) + { ExceptionHandler.unexpectedException(e, "payload", "creation", true); } - if( component == null ) { - - if( candidate == null) + if (component == null) + { + if (candidate == null) + { ExceptionHandler.missingSignature(); + } RemoteObjectClient client = getRemoteObjectClient(rmi); client.codebaseCall(candidate, payload, argumentPosition); @@ -416,18 +465,22 @@ public void dispatchCodebase() DGCClient dgc = new DGCClient(rmi); dgc.codebaseCall(p.getDgcMethod(), payload); + } - } else if( component == RMIComponent.REGISTRY ) { - + else if (component == RMIComponent.REGISTRY) + { RegistryClient reg = new RegistryClient(rmi); reg.codebaseCall(payload, p.getRegMethod(), RMGOption.BIND_BYPASS.getBool()); + } - } else if( component == RMIComponent.ACTIVATOR ) { - + else if (component == RMIComponent.ACTIVATOR) + { ActivationClient act = new ActivationClient(rmi); act.codebaseCall(payload); + } - } else { + else + { ExceptionHandler.internalError("dispatchCodebase", "No target was selected."); } } @@ -488,44 +541,54 @@ public void dispatchEnum() boolean enumJEP290Bypass = true; boolean marshal = true; - try { - - if( actions.contains(ScanAction.LIST) ) { - + try + { + if (actions.contains(ScanAction.LIST)) + { obtainBoundNames(); - if( !RMGOption.SSRFRESPONSE.notNull() || RMGOption.TARGET_BOUND_NAME.notNull() ) { + if (!RMGOption.SSRFRESPONSE.notNull() || RMGOption.TARGET_BOUND_NAME.notNull()) + { obtainBoundObjects(); format.listBoundNames(remoteObjects); Logger.lineBreak(); format.listCodebases(); + } - } else { + else + { remoteObjects = RemoteObjectWrapper.fromBoundNames(boundNames); format.listBoundNames(remoteObjects); } - if( RMGOption.SSRFRESPONSE.notNull() ) + if (RMGOption.SSRFRESPONSE.notNull()) + { return; + } } - if( actions.contains(ScanAction.STRING_MARSHALLING) ) { + if (actions.contains(ScanAction.STRING_MARSHALLING)) + { Logger.lineBreak(); marshal = registryClient.enumerateStringMarshalling(); } - if( actions.contains(ScanAction.CODEBASE) ) { + if (actions.contains(ScanAction.CODEBASE)) + { Logger.lineBreak(); registryClient.enumCodebase(marshal, p.getRegMethod(), RMGOption.ENUM_BYPASS.getBool()); } - if( actions.contains(ScanAction.LOCALHOST_BYPASS) ) { + if (actions.contains(ScanAction.LOCALHOST_BYPASS)) + { Logger.lineBreak(); registryClient.enumLocalhostBypass(); } + } - } catch( java.rmi.NoSuchObjectException e ) { + catch (java.rmi.NoSuchObjectException e) + { ExceptionHandler.noSuchObjectExceptionRegistryEnum(); enumJEP290Bypass = false; @@ -533,22 +596,26 @@ public void dispatchEnum() format.listCodebases(); } - if( actions.contains(ScanAction.SECURITY_MANAGER) ) { + if (actions.contains(ScanAction.SECURITY_MANAGER)) + { Logger.lineBreak(); dgc.enumSecurityManager(p.getDgcMethod()); } - if( actions.contains(ScanAction.JEP290) ) { + if (actions.contains(ScanAction.JEP290)) + { Logger.lineBreak(); dgc.enumJEP290(p.getDgcMethod()); } - if(enumJEP290Bypass && actions.contains(ScanAction.FILTER_BYPASS) ) { + if (enumJEP290Bypass && actions.contains(ScanAction.FILTER_BYPASS)) + { Logger.lineBreak(); registryClient.enumJEP290Bypass(p.getRegMethod(), RMGOption.ENUM_BYPASS.getBool(), marshal); } - if( actions.contains(ScanAction.ACTIVATOR) ) { + if (actions.contains(ScanAction.ACTIVATOR)) + { Logger.lineBreak(); ActivationClient activationClient = new ActivationClient(rmi); activationClient.enumActivator(); @@ -564,10 +631,13 @@ public void dispatchGuess() { Formatter format = new Formatter(); - try { + try + { obtainBoundObjects(); + } - } catch( NoSuchObjectException e ) { + catch (NoSuchObjectException e) + { ExceptionHandler.noSuchObjectException(e, "registry", true); } @@ -580,8 +650,10 @@ public void dispatchGuess() Logger.decreaseIndent(); format.listGuessedMethods(results); - if(results.size() > 0 && RMGOption.GUESS_CREATE_SAMPLES.getBool()) + if (results.size() > 0 && RMGOption.GUESS_CREATE_SAMPLES.getBool()) + { this.writeSamples(results); + } } /** @@ -598,10 +670,15 @@ public void dispatchKnown() KnownEndpointHolder keh = KnownEndpointHolder.getHolder(); KnownEndpoint endpoint = keh.lookup(className); - if( endpoint == null ) + if (endpoint == null) + { Logger.eprintlnMixedYellow("The specified class name", className, "isn't a known class."); + } + else + { formatter.listKnownEndpoint(endpoint); + } } /** @@ -651,8 +728,8 @@ public void dispatchRogueJMX() RogueJMX rogueJMX = new RogueJMX(listenerHost, listenerPort, RMGOption.ROGUEJMX_OBJID.getValue()); - if( RMGOption.ROGUEJMX_FORWARD_HOST.notNull() ) { - + if (RMGOption.ROGUEJMX_FORWARD_HOST.notNull()) + { String forwardHost = RMGOption.ROGUEJMX_FORWARD_HOST.getValue(); int forwardPort = RMGOption.require(RMGOption.ROGUEJMX_FORWARD_PORT); @@ -666,11 +743,14 @@ public void dispatchRogueJMX() rogueJMX.forwardTo(client); } - try { + try + { rogueJMX.export(); Logger.lineBreak(); + } - } catch( java.rmi.RemoteException e ) { + catch (java.rmi.RemoteException e) + { ExceptionHandler.unexpectedException(e, "exporting", "rogue JMX server", true); } } diff --git a/src/de/qtc/rmg/operations/MethodGuesser.java b/src/de/qtc/rmg/operations/MethodGuesser.java index a6b6281..e88f397 100644 --- a/src/de/qtc/rmg/operations/MethodGuesser.java +++ b/src/de/qtc/rmg/operations/MethodGuesser.java @@ -15,6 +15,7 @@ import de.qtc.rmg.io.Logger; import de.qtc.rmg.utils.ProgressBar; import de.qtc.rmg.utils.RMGUtils; +import de.qtc.rmg.utils.SpringRemotingWrapper; import de.qtc.rmg.utils.UnicastWrapper; /** @@ -37,8 +38,8 @@ * * @author Tobias Neitzel (@qtc_de) */ -public class MethodGuesser { - +public class MethodGuesser +{ private int padding = 0; private final ProgressBar progressBar; @@ -191,7 +192,7 @@ private UnicastWrapper[] handleKnownMethods(UnicastWrapper[] remoteObjects) else { RemoteObjectClient knownClient = new RemoteObjectClient(o); - knownClient.addRemoteMethods(RMGUtils.getKnownMethods(o.className)); + knownClient.addRemoteMethods(RMGUtils.getKnownMethods(o.getInterfaceName())); knownClientList.add(knownClient); } @@ -280,8 +281,17 @@ public List guessMethods() { for (Set candidates : candidateSets) { - Runnable r = new GuessingWorker(client, candidates); - pool.execute(r); + if (client.remoteObject instanceof SpringRemotingWrapper) + { + Runnable r = new SpringGuessingWorker(client, candidates); + pool.execute(r); + } + + else + { + Runnable r = new GuessingWorker(client, candidates); + pool.execute(r); + } } } @@ -317,9 +327,9 @@ public List guessMethods() */ private class GuessingWorker implements Runnable { - private String boundName; - private Set candidates; - private RemoteObjectClient client; + protected String boundName; + protected Set candidates; + protected RemoteObjectClient client; /** * Initialize the guessing worker with all the required information. @@ -340,7 +350,7 @@ public GuessingWorker(RemoteObjectClient client, Set candidates * * @param candidate MethodCandidate that was successfully guessed */ - private void logHit(MethodCandidate candidate) + protected void logHit(MethodCandidate candidate) { String prefix = Logger.blue("[ " + Logger.padRight(boundName, padding) + " ] "); Logger.printlnMixedYellow(prefix + "HIT! Method with signature", candidate.getSignature(), "exists!"); @@ -402,4 +412,68 @@ public void run() } } } + + private class SpringGuessingWorker extends GuessingWorker + { + public SpringGuessingWorker(RemoteObjectClient client, Set candidates) + { + super(client, candidates); + } + + public void run() + { + for (MethodCandidate candidate : candidates) + { + try + { + client.guessingCallSpring(candidate); + logHit(candidate); + } + + catch (java.lang.NoSuchMethodException e) + { + /* + * SpringRemoting resolves remote methods via reflection. If the requetsed method does not + * exist, it throws a java.lang.NoSuchMethodException. + */ + } + + catch (java.rmi.ServerException e) + { + Throwable cause = ExceptionHandler.getCause(e); + + if (cause instanceof java.lang.ClassNotFoundException) + { + } + + else + { + logHit(candidate); + } + } + + catch(Exception e) + { + /* + * If we end up here, an unexpected exception was raised that indicates a general error. + */ + Logger.printlnYellow(candidate.getSignature()); + StringWriter writer = new StringWriter(); + e.printStackTrace(new PrintWriter(writer)); + + String info = "Caught unexpected " + e.getClass().getName() + " during method guessing.\n" + +"Please report this to improve rmg :)\n" + +"Stack-Trace:\n" + +writer.toString(); + + Logger.println(info); + } + + finally + { + progressBar.taskDone(); + } + } + } + } } diff --git a/src/de/qtc/rmg/operations/RemoteObjectClient.java b/src/de/qtc/rmg/operations/RemoteObjectClient.java index bd72f68..82bc56c 100644 --- a/src/de/qtc/rmg/operations/RemoteObjectClient.java +++ b/src/de/qtc/rmg/operations/RemoteObjectClient.java @@ -6,6 +6,8 @@ import java.util.Iterator; import java.util.List; +import org.springframework.remoting.support.RemoteInvocation; + import de.qtc.rmg.internal.ExceptionHandler; import de.qtc.rmg.internal.MethodArguments; import de.qtc.rmg.internal.MethodCandidate; @@ -337,6 +339,17 @@ else if (cause instanceof java.lang.UnsupportedOperationException) } } + + public void guessingCallSpring(MethodCandidate targetMethod) throws Exception + { + RemoteInvocation invo = SpringRemotingWrapper.buildRemoteInvocation(targetMethod, new Object[] {}); + + MethodArguments args = new MethodArguments(invo, RemoteInvocation.class); + targetMethod = SpringRemotingWrapper.getInvokeMethod(); + + rmi.genericCall(null, -1, SpringRemotingWrapper.getInvokeMethod().getHash(), args, false, "Invoke", remoteRef, null); + } + /** * Just a wrapper around the guessingCall function of the RMIEndpoint class. * diff --git a/src/de/qtc/rmg/utils/RMGUtils.java b/src/de/qtc/rmg/utils/RMGUtils.java index ac27a2b..be84aa1 100644 --- a/src/de/qtc/rmg/utils/RMGUtils.java +++ b/src/de/qtc/rmg/utils/RMGUtils.java @@ -55,8 +55,8 @@ * @author Tobias Neitzel (@qtc_de) */ @SuppressWarnings({ "rawtypes", "deprecation", "restriction" }) -public class RMGUtils { - +public class RMGUtils +{ private static ClassPool pool; private static CtClass dummyClass; private static CtClass remoteClass; @@ -1132,7 +1132,7 @@ public static ObjID parseObjID(String objIdString) * @param remoteObject Object to obtain the class from * @return Class name of the implementor or one of its interfaces in case of a Proxy */ - public static String getClassName(Remote remoteObject) + public static String getInterfaceName(Remote remoteObject) { if( Proxy.isProxyClass(remoteObject.getClass()) ) { diff --git a/src/de/qtc/rmg/utils/RemoteObjectWrapper.java b/src/de/qtc/rmg/utils/RemoteObjectWrapper.java index d41d2b3..18bc882 100644 --- a/src/de/qtc/rmg/utils/RemoteObjectWrapper.java +++ b/src/de/qtc/rmg/utils/RemoteObjectWrapper.java @@ -23,11 +23,12 @@ @SuppressWarnings("restriction") public abstract class RemoteObjectWrapper { - public String className; public String boundName; public Remote remoteObject; public KnownEndpoint knownEndpoint; + private String interfaceName; + /** * This constructor is only used for special purposes during the enum action. The resulting * RemoteObjectWrapper is not fully functional and should not be used for other purposes than @@ -54,8 +55,8 @@ public RemoteObjectWrapper(String boundName, Remote remoteObject) this.boundName = boundName; this.remoteObject = remoteObject; - this.className = RMGUtils.getClassName(remoteObject); - this.knownEndpoint = KnownEndpointHolder.getHolder().lookup(className); + this.interfaceName = RMGUtils.getInterfaceName(remoteObject); + this.knownEndpoint = KnownEndpointHolder.getHolder().lookup(interfaceName); } /** @@ -86,11 +87,11 @@ public static RemoteObjectWrapper getInstance(Remote remote, String boundName) t RemoteObjectWrapper wrapper = null; RemoteRef ref = RMGUtils.extractRef(remote); - String className = RMGUtils.getClassName(remote); + String interfaceName = RMGUtils.getInterfaceName(remote); if (ref instanceof UnicastRef) { - if (className.equals(SpringRemotingWrapper.invocationHandlerClass)) + if (interfaceName.equals(SpringRemotingWrapper.invocationHandlerClass)) { wrapper = new SpringRemotingWrapper(remote, boundName, (UnicastRef)ref); } @@ -126,8 +127,10 @@ public static RemoteObjectWrapper getByName(String boundName, RemoteObjectWrappe { for(RemoteObjectWrapper o : list) { - if( o != null && o.boundName.equals(boundName) ) + if (o != null && o.boundName.equals(boundName)) + { return o; + } } return null; @@ -158,12 +161,24 @@ public static RemoteObjectWrapper[] fromBoundNames(String[] boundNames) */ public boolean isKnown() { - if( knownEndpoint == null ) + if (knownEndpoint == null) + { return false; + } return true; } + /** + * Return the interface name that is implemented by the remote object. + * + * @return interface name implemented by the remote object + */ + public String getInterfaceName() + { + return interfaceName; + } + /** * Transform an RemoteObjectWrapper into a UnicastWrapper. If the RemoteObjectWrapper is already * a UnicastWrapper, it is simply returned. If it is an ActivatableWrapper instead, it is activated. @@ -175,15 +190,22 @@ public UnicastWrapper getUnicastWrapper() UnicastWrapper returnValue = null; if (this instanceof UnicastWrapper) + { returnValue = (UnicastWrapper)this; + } else - - try { + { + try + { returnValue = ((ActivatableWrapper)this).activate(); - } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { + } + + catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) + { ExceptionHandler.unexpectedException(e, "activate", "call", true); } + } return returnValue; } diff --git a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java index fec0e4f..796df46 100644 --- a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java +++ b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java @@ -4,13 +4,16 @@ import org.springframework.remoting.support.RemoteInvocation; +import de.qtc.rmg.endpoints.KnownEndpointHolder; import de.qtc.rmg.internal.ExceptionHandler; import de.qtc.rmg.internal.MethodCandidate; +import de.qtc.rmg.io.Logger; import de.qtc.rmg.operations.RemoteObjectClient; import de.qtc.rmg.plugin.PluginSystem; import de.qtc.rmg.plugin.ReturnValueProvider; import javassist.CannotCompileException; import javassist.CtClass; +import javassist.CtPrimitiveType; import javassist.NotFoundException; import sun.rmi.server.UnicastRef; @@ -31,7 +34,7 @@ public class SpringRemotingWrapper extends UnicastWrapper private static MethodCandidate methodGet; private static MethodCandidate methodInvoke; - private static String interfaceName; + private static String remotingInterfaceName; public SpringRemotingWrapper(Remote remoteObject, String boundName, UnicastRef ref) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { @@ -43,12 +46,8 @@ public SpringRemotingWrapper(Remote remoteObject, String boundName, UnicastRef r RemoteObjectClient client = new RemoteObjectClient(this); client.genericCall(getInterfaceNameMethod(), new Object[] {}); - interfaceName = (String)respHandler.getValue(); - } - - public String getInterfaceName() - { - return interfaceName; + remotingInterfaceName = (String)respHandler.getValue(); + knownEndpoint = KnownEndpointHolder.getHolder().lookup(remotingInterfaceName); } /** @@ -118,17 +117,53 @@ public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMetho try { String methodName = targetMethod.getName(); - CtClass[] argTypes = targetMethod.getParameterTypes(); - invo.setMethodName(methodName); - Class[] parameterTypes = new Class[args.length]; + + CtClass[] argTypes = targetMethod.getParameterTypes(); + Class[] parameterTypes = new Class[argTypes.length]; try { - for (int ctr = 0; ctr < args.length; ctr++) + for (int ctr = 0; ctr < argTypes.length; ctr++) { - Class cls = Class.forName(argTypes[ctr].getName()); - parameterTypes[ctr] = cls; + if (argTypes[ctr].isPrimitive()) + { + if (argTypes[ctr] == CtPrimitiveType.intType) { + parameterTypes[ctr] = int.class; + } else if (argTypes[ctr] == CtPrimitiveType.booleanType) { + parameterTypes[ctr] = boolean.class; + } else if (argTypes[ctr] == CtPrimitiveType.byteType) { + parameterTypes[ctr] = byte.class; + } else if (argTypes[ctr] == CtPrimitiveType.charType) { + parameterTypes[ctr] = char.class; + } else if (argTypes[ctr] == CtPrimitiveType.shortType) { + parameterTypes[ctr] = short.class; + } else if (argTypes[ctr] == CtPrimitiveType.longType) { + parameterTypes[ctr] = long.class; + } else if (argTypes[ctr] == CtPrimitiveType.floatType) { + parameterTypes[ctr] = float.class; + } else if (argTypes[ctr] == CtPrimitiveType.doubleType) { + parameterTypes[ctr] = double.class; + } else { + throw new Error("unrecognized primitive type: " + argTypes[ctr]); + } + + } + + else + { + String className = argTypes[ctr].getName(); + className = className.replaceAll("\\[\\]", ""); + + if (argTypes[ctr].isArray()) + { + className = "[L" + className + ";"; + } + + Logger.printlnYellow(className); + Class cls = Class.forName(className); + parameterTypes[ctr] = cls; + } } } @@ -148,4 +183,9 @@ public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMetho return invo; } + + public String getInterfaceName() + { + return remotingInterfaceName; + } } diff --git a/src/de/qtc/rmg/utils/UnicastWrapper.java b/src/de/qtc/rmg/utils/UnicastWrapper.java index ee543fd..e1482f9 100644 --- a/src/de/qtc/rmg/utils/UnicastWrapper.java +++ b/src/de/qtc/rmg/utils/UnicastWrapper.java @@ -197,7 +197,7 @@ public static UnicastWrapper[] handleDuplicates(UnicastWrapper[] list) for(UnicastWrapper other : unique) { - if(other.className.equals(current.className)) { + if(other.getInterfaceName().equals(current.getInterfaceName())) { other.addDuplicate(current); continue outer; } From d81ee6d6682aaaead84a8316331d0f66e6c61d74 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Mon, 16 Oct 2023 22:12:53 +0200 Subject: [PATCH 19/60] Implement support for spring remoting method guess First working draft. --- src/de/qtc/rmg/operations/MethodGuesser.java | 100 ++++++++++++++---- .../rmg/operations/RemoteObjectClient.java | 9 +- src/de/qtc/rmg/utils/RMGUtils.java | 42 +++++++- .../qtc/rmg/utils/SpringRemotingWrapper.java | 69 +++++------- 4 files changed, 148 insertions(+), 72 deletions(-) diff --git a/src/de/qtc/rmg/operations/MethodGuesser.java b/src/de/qtc/rmg/operations/MethodGuesser.java index e88f397..4058b57 100644 --- a/src/de/qtc/rmg/operations/MethodGuesser.java +++ b/src/de/qtc/rmg/operations/MethodGuesser.java @@ -4,12 +4,16 @@ import java.io.StringWriter; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import org.springframework.remoting.support.RemoteInvocation; + import de.qtc.rmg.internal.ExceptionHandler; +import de.qtc.rmg.internal.MethodArguments; import de.qtc.rmg.internal.MethodCandidate; import de.qtc.rmg.internal.RMGOption; import de.qtc.rmg.io.Logger; @@ -283,7 +287,8 @@ public List guessMethods() { if (client.remoteObject instanceof SpringRemotingWrapper) { - Runnable r = new SpringGuessingWorker(client, candidates); + Map invocations = SpringRemotingWrapper.buildInvocationMap(candidates); + Runnable r = new SpringGuessingWorker(client, invocations); pool.execute(r); } @@ -413,28 +418,59 @@ public void run() } } - private class SpringGuessingWorker extends GuessingWorker + private class SpringGuessingWorker implements Runnable { - public SpringGuessingWorker(RemoteObjectClient client, Set candidates) + protected String boundName; + protected RemoteObjectClient client; + protected Map invocationMap; + + public SpringGuessingWorker(RemoteObjectClient client, Map invocationMap) { - super(client, candidates); + this.client = client; + this.boundName = client.getBoundName(); + this.invocationMap = invocationMap; + } + + protected void logHit(RemoteInvocation invocation) + { + MethodCandidate existingMethod = invocationMap.get(invocation); + + String prefix = Logger.blue("[ " + Logger.padRight(boundName, padding) + " ] "); + Logger.printlnMixedYellow(prefix + "HIT! Method with signature", existingMethod.getSignature(), "exists!"); + client.addRemoteMethod(existingMethod); } public void run() { - for (MethodCandidate candidate : candidates) + for (RemoteInvocation invocation : invocationMap.keySet()) { try { - client.guessingCallSpring(candidate); - logHit(candidate); + client.unmanagedCall(SpringRemotingWrapper.getInvokeMethod(), new MethodArguments(invocation, RemoteInvocation.class)); + + /* + * We always provide an invalid argument count for our SpringRemoting calls. + * We should never endup here, which would indicate a successful call. + */ + unexpectedError(invocation, null); + } + + catch (java.lang.IllegalArgumentException e) + { + /* + * Since SpringRemoting calls exposed methods via reflection, we can always provide an incorrect + * argument count during the call. If the method exists, this leads to an IllegalArgumentException, + * which is used to identify valid methods. + */ + logHit(invocation); } catch (java.lang.NoSuchMethodException e) { /* - * SpringRemoting resolves remote methods via reflection. If the requetsed method does not - * exist, it throws a java.lang.NoSuchMethodException. + * SpringRemoting resolves remote methods via reflection. If the requested method does not + * exist, it throws a java.lang.NoSuchMethodException. So this branch means that the guessed + * method simply does not exist and we can continue. */ } @@ -444,11 +480,19 @@ public void run() if (cause instanceof java.lang.ClassNotFoundException) { + /* + * Since SpringRemoting requires valid RMI calls, guessed methods may contain classes that + * are not known on the server side. In this case, ClassNotFoundExceptions are expected. This + * means that the method does not exist and we can continue. + */ } else { - logHit(candidate); + /* + * If we end up here, an unexpected exception was raised that indicates a general error. + */ + unexpectedError(invocation, e); } } @@ -457,16 +501,7 @@ public void run() /* * If we end up here, an unexpected exception was raised that indicates a general error. */ - Logger.printlnYellow(candidate.getSignature()); - StringWriter writer = new StringWriter(); - e.printStackTrace(new PrintWriter(writer)); - - String info = "Caught unexpected " + e.getClass().getName() + " during method guessing.\n" - +"Please report this to improve rmg :)\n" - +"Stack-Trace:\n" - +writer.toString(); - - Logger.println(info); + unexpectedError(invocation, e); } finally @@ -475,5 +510,30 @@ public void run() } } } + + private void unexpectedError(RemoteInvocation invocation, Exception e) + { + String info = ""; + StringWriter writer = new StringWriter(); + + Logger.printlnYellow(invocationMap.get(invocation).getSignature()); + + if (e != null) + { + e.printStackTrace(new PrintWriter(writer)); + + info = "Caught unexpected " + e.getClass().getName() + " during method guessing.\n" + +"Please report this to improve rmg :)\n" + +"Stack-Trace:\n" + +writer.toString(); + } + + else + { + info = "Spring Remoting call did not cause an exception. This is not expected."; + } + + Logger.println(info); + } } } diff --git a/src/de/qtc/rmg/operations/RemoteObjectClient.java b/src/de/qtc/rmg/operations/RemoteObjectClient.java index 82bc56c..1bfa3e3 100644 --- a/src/de/qtc/rmg/operations/RemoteObjectClient.java +++ b/src/de/qtc/rmg/operations/RemoteObjectClient.java @@ -340,14 +340,9 @@ else if (cause instanceof java.lang.UnsupportedOperationException) } - public void guessingCallSpring(MethodCandidate targetMethod) throws Exception + public void unmanagedCall(MethodCandidate targetMethod, MethodArguments args) throws Exception { - RemoteInvocation invo = SpringRemotingWrapper.buildRemoteInvocation(targetMethod, new Object[] {}); - - MethodArguments args = new MethodArguments(invo, RemoteInvocation.class); - targetMethod = SpringRemotingWrapper.getInvokeMethod(); - - rmi.genericCall(null, -1, SpringRemotingWrapper.getInvokeMethod().getHash(), args, false, "Invoke", remoteRef, null); + rmi.genericCall(null, -1, targetMethod.getHash(), args, false, targetMethod.getName(), remoteRef, null); } /** diff --git a/src/de/qtc/rmg/utils/RMGUtils.java b/src/de/qtc/rmg/utils/RMGUtils.java index be84aa1..a2cba99 100644 --- a/src/de/qtc/rmg/utils/RMGUtils.java +++ b/src/de/qtc/rmg/utils/RMGUtils.java @@ -1,6 +1,7 @@ package de.qtc.rmg.utils; import java.io.InvalidClassException; +import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -210,7 +211,7 @@ public static Class makeActivatableRef() throws CannotCompileException return Class.forName("sun.rmi.server.ActivatableRef"); } catch (ClassNotFoundException e) { // TODO needs to be implemented correctly - Logger.printlnYellow("[-] Not implemented yet!"); + Logger.eprintlnYellow("Not implemented yet!"); RMGUtils.exit(); } @@ -285,8 +286,7 @@ else if (!RMGOption.SOCKET_FACTORY_SSL.getBool() && (!RMGOption.CONN_SSL.getBool */ public static CtMethod makeMethod(String signature) throws CannotCompileException { - CtMethod method = CtNewMethod.make("public " + signature + ";", dummyClass); - return method; + return CtNewMethod.make("public " + signature + ";", dummyClass); } /** @@ -1331,4 +1331,40 @@ public static long getSerialVersionUID(InvalidClassException e) return Long.parseLong(message); } + + public static Class ctClassToClass(CtClass type) throws ClassNotFoundException, NotFoundException + { + if (type.isPrimitive()) + { + if (type == CtPrimitiveType.intType) { + return int.class; + } else if (type == CtPrimitiveType.booleanType) { + return boolean.class; + } else if (type == CtPrimitiveType.byteType) { + return byte.class; + } else if (type == CtPrimitiveType.charType) { + return char.class; + } else if (type == CtPrimitiveType.shortType) { + return short.class; + } else if (type == CtPrimitiveType.longType) { + return long.class; + } else if (type == CtPrimitiveType.floatType) { + return float.class; + } else if (type == CtPrimitiveType.doubleType) { + return double.class; + } else { + throw new Error("unrecognized primitive type: " + type); + } + } + + else if (type.isArray()) + { + return Array.newInstance(ctClassToClass(type.getComponentType()), 0).getClass(); + } + + else + { + return Class.forName(type.getName()); + } + } } diff --git a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java index 796df46..3b71ef0 100644 --- a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java +++ b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java @@ -1,6 +1,9 @@ package de.qtc.rmg.utils; import java.rmi.Remote; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; import org.springframework.remoting.support.RemoteInvocation; @@ -13,7 +16,6 @@ import de.qtc.rmg.plugin.ReturnValueProvider; import javassist.CannotCompileException; import javassist.CtClass; -import javassist.CtPrimitiveType; import javassist.NotFoundException; import sun.rmi.server.UnicastRef; @@ -116,9 +118,6 @@ public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMetho try { - String methodName = targetMethod.getName(); - invo.setMethodName(methodName); - CtClass[] argTypes = targetMethod.getParameterTypes(); Class[] parameterTypes = new Class[argTypes.length]; @@ -126,44 +125,7 @@ public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMetho { for (int ctr = 0; ctr < argTypes.length; ctr++) { - if (argTypes[ctr].isPrimitive()) - { - if (argTypes[ctr] == CtPrimitiveType.intType) { - parameterTypes[ctr] = int.class; - } else if (argTypes[ctr] == CtPrimitiveType.booleanType) { - parameterTypes[ctr] = boolean.class; - } else if (argTypes[ctr] == CtPrimitiveType.byteType) { - parameterTypes[ctr] = byte.class; - } else if (argTypes[ctr] == CtPrimitiveType.charType) { - parameterTypes[ctr] = char.class; - } else if (argTypes[ctr] == CtPrimitiveType.shortType) { - parameterTypes[ctr] = short.class; - } else if (argTypes[ctr] == CtPrimitiveType.longType) { - parameterTypes[ctr] = long.class; - } else if (argTypes[ctr] == CtPrimitiveType.floatType) { - parameterTypes[ctr] = float.class; - } else if (argTypes[ctr] == CtPrimitiveType.doubleType) { - parameterTypes[ctr] = double.class; - } else { - throw new Error("unrecognized primitive type: " + argTypes[ctr]); - } - - } - - else - { - String className = argTypes[ctr].getName(); - className = className.replaceAll("\\[\\]", ""); - - if (argTypes[ctr].isArray()) - { - className = "[L" + className + ";"; - } - - Logger.printlnYellow(className); - Class cls = Class.forName(className); - parameterTypes[ctr] = cls; - } + parameterTypes[ctr] = RMGUtils.ctClassToClass(argTypes[ctr]); } } @@ -172,6 +134,9 @@ public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMetho ExceptionHandler.internalError("SpringRemoting.buildRemoteInvocation", e.getMessage()); } + String methodName = targetMethod.getName(); + + invo.setMethodName(methodName); invo.setArguments(args); invo.setParameterTypes(parameterTypes); } @@ -184,6 +149,26 @@ public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMetho return invo; } + public static Map buildInvocationMap(Set candidates) + { + Map invocationMap = new HashMap(); + + for (MethodCandidate candidate : candidates) + { + Object[] args = new Object[] {}; + + if (candidate.getArgumentCount() == 0) + { + args = new Object[] {1}; + } + + RemoteInvocation invo = buildRemoteInvocation(candidate, args); + invocationMap.put(invo, candidate); + } + + return invocationMap; + } + public String getInterfaceName() { return remotingInterfaceName; From cb150ad5cc584f8c1cdad9404e46070e55579952 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Wed, 18 Oct 2023 09:27:57 +0200 Subject: [PATCH 20/60] Improve method guessing for spring-remoting --- src/de/qtc/rmg/io/Formatter.java | 10 ++- src/de/qtc/rmg/operations/MethodGuesser.java | 48 ++++++++------ .../qtc/rmg/utils/RemoteInvocationHolder.java | 62 +++++++++++++++++++ .../qtc/rmg/utils/SpringRemotingWrapper.java | 39 +++++++++--- 4 files changed, 129 insertions(+), 30 deletions(-) create mode 100644 src/de/qtc/rmg/utils/RemoteInvocationHolder.java diff --git a/src/de/qtc/rmg/io/Formatter.java b/src/de/qtc/rmg/io/Formatter.java index b3556b1..1502536 100644 --- a/src/de/qtc/rmg/io/Formatter.java +++ b/src/de/qtc/rmg/io/Formatter.java @@ -99,7 +99,15 @@ public void listGuessedMethods(List results) for (MethodCandidate m : methods) { - Logger.printlnMixedYellow("-->", m.getSignature()); + if (client.remoteObject instanceof SpringRemotingWrapper) + { + Logger.printlnMixedYellow("-->",SpringRemotingWrapper.getSignature(m)); + } + + else + { + Logger.printlnMixedYellow("-->", m.getSignature()); + } } Logger.decreaseIndent(); diff --git a/src/de/qtc/rmg/operations/MethodGuesser.java b/src/de/qtc/rmg/operations/MethodGuesser.java index 4058b57..d48e6f0 100644 --- a/src/de/qtc/rmg/operations/MethodGuesser.java +++ b/src/de/qtc/rmg/operations/MethodGuesser.java @@ -19,6 +19,7 @@ import de.qtc.rmg.io.Logger; import de.qtc.rmg.utils.ProgressBar; import de.qtc.rmg.utils.RMGUtils; +import de.qtc.rmg.utils.RemoteInvocationHolder; import de.qtc.rmg.utils.SpringRemotingWrapper; import de.qtc.rmg.utils.UnicastWrapper; @@ -51,6 +52,7 @@ public class MethodGuesser private List clientList; private List knownClientList; private List> candidateSets; + private List> invocationHolderSets; /** * To create a MethodGuesser you need to pass the references for remote objects you want to guess on. @@ -68,6 +70,12 @@ public MethodGuesser(UnicastWrapper[] remoteObjects, Set candid this.knownClientList = new ArrayList(); this.candidateSets = RMGUtils.splitSet(candidates, RMGOption.THREADS.getValue()); + if (SpringRemotingWrapper.containsSpringRemotingClient(remoteObjects)) + { + Set invocationHolders = SpringRemotingWrapper.getInvocationHolders(candidates); + invocationHolderSets = RMGUtils.splitSet(invocationHolders, RMGOption.THREADS.getValue()); + } + if (!RMGOption.GUESS_FORCE_GUESSING.getBool()) { remoteObjects = handleKnownMethods(remoteObjects); @@ -283,16 +291,18 @@ public List guessMethods() for (RemoteObjectClient client : clientList) { - for (Set candidates : candidateSets) + if (client.remoteObject instanceof SpringRemotingWrapper) { - if (client.remoteObject instanceof SpringRemotingWrapper) + for (Set invoHolder : invocationHolderSets) { - Map invocations = SpringRemotingWrapper.buildInvocationMap(candidates); - Runnable r = new SpringGuessingWorker(client, invocations); + Runnable r = new SpringGuessingWorker(client, invoHolder); pool.execute(r); } + } - else + else + { + for (Set candidates : candidateSets) { Runnable r = new GuessingWorker(client, candidates); pool.execute(r); @@ -422,37 +432,37 @@ private class SpringGuessingWorker implements Runnable { protected String boundName; protected RemoteObjectClient client; - protected Map invocationMap; + protected Set invocationHolders; - public SpringGuessingWorker(RemoteObjectClient client, Map invocationMap) + public SpringGuessingWorker(RemoteObjectClient client, Set invocationHolders) { this.client = client; this.boundName = client.getBoundName(); - this.invocationMap = invocationMap; + this.invocationHolders = invocationHolders; } - protected void logHit(RemoteInvocation invocation) + protected void logHit(RemoteInvocationHolder invoHolder) { - MethodCandidate existingMethod = invocationMap.get(invocation); + MethodCandidate existingMethod = invoHolder.getCandidate(); String prefix = Logger.blue("[ " + Logger.padRight(boundName, padding) + " ] "); - Logger.printlnMixedYellow(prefix + "HIT! Method with signature", existingMethod.getSignature(), "exists!"); + Logger.printlnMixedYellow(prefix + "HIT! Method with signature", SpringRemotingWrapper.getSignature(existingMethod), "exists!"); client.addRemoteMethod(existingMethod); } public void run() { - for (RemoteInvocation invocation : invocationMap.keySet()) + for (RemoteInvocationHolder invocationHolder : invocationHolders) { try { - client.unmanagedCall(SpringRemotingWrapper.getInvokeMethod(), new MethodArguments(invocation, RemoteInvocation.class)); + client.unmanagedCall(SpringRemotingWrapper.getInvokeMethod(), new MethodArguments(invocationHolder.getInvo(), RemoteInvocation.class)); /* * We always provide an invalid argument count for our SpringRemoting calls. * We should never endup here, which would indicate a successful call. */ - unexpectedError(invocation, null); + unexpectedError(invocationHolder, null); } catch (java.lang.IllegalArgumentException e) @@ -462,7 +472,7 @@ public void run() * argument count during the call. If the method exists, this leads to an IllegalArgumentException, * which is used to identify valid methods. */ - logHit(invocation); + logHit(invocationHolder); } catch (java.lang.NoSuchMethodException e) @@ -492,7 +502,7 @@ public void run() /* * If we end up here, an unexpected exception was raised that indicates a general error. */ - unexpectedError(invocation, e); + unexpectedError(invocationHolder, e); } } @@ -501,7 +511,7 @@ public void run() /* * If we end up here, an unexpected exception was raised that indicates a general error. */ - unexpectedError(invocation, e); + unexpectedError(invocationHolder, e); } finally @@ -511,12 +521,12 @@ public void run() } } - private void unexpectedError(RemoteInvocation invocation, Exception e) + private void unexpectedError(RemoteInvocationHolder invoHolder, Exception e) { String info = ""; StringWriter writer = new StringWriter(); - Logger.printlnYellow(invocationMap.get(invocation).getSignature()); + Logger.printlnYellow(invoHolder.getCandidate().getSignature()); if (e != null) { diff --git a/src/de/qtc/rmg/utils/RemoteInvocationHolder.java b/src/de/qtc/rmg/utils/RemoteInvocationHolder.java new file mode 100644 index 0000000..b2238d1 --- /dev/null +++ b/src/de/qtc/rmg/utils/RemoteInvocationHolder.java @@ -0,0 +1,62 @@ +package de.qtc.rmg.utils; + +import java.util.Arrays; + +import org.springframework.remoting.support.RemoteInvocation; + +import de.qtc.rmg.internal.MethodCandidate; + +public class RemoteInvocationHolder +{ + private RemoteInvocation invo; + private MethodCandidate candidate; + + public RemoteInvocationHolder(RemoteInvocation invo, MethodCandidate candidate) + { + this.invo = invo; + this.candidate = candidate; + } + + public boolean equals(Object other) + { + if (other instanceof RemoteInvocationHolder) + { + RemoteInvocationHolder otherInvocation = (RemoteInvocationHolder)other; + + if (otherInvocation.getName().equals(this.getName())) + { + if (Arrays.equals(otherInvocation.getTypes(), this.getTypes())) + { + return true; + } + } + } + + return false; + } + + public int hashCode() + { + return invo.toString().hashCode(); + } + + public String getName() + { + return invo.getMethodName(); + } + + public Class[] getTypes() + { + return invo.getParameterTypes(); + } + + public MethodCandidate getCandidate() + { + return candidate; + } + + public RemoteInvocation getInvo() + { + return invo; + } +} diff --git a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java index 3b71ef0..baf4fa7 100644 --- a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java +++ b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java @@ -1,8 +1,7 @@ package de.qtc.rmg.utils; import java.rmi.Remote; -import java.util.HashMap; -import java.util.Map; +import java.util.HashSet; import java.util.Set; import org.springframework.remoting.support.RemoteInvocation; @@ -10,7 +9,6 @@ import de.qtc.rmg.endpoints.KnownEndpointHolder; import de.qtc.rmg.internal.ExceptionHandler; import de.qtc.rmg.internal.MethodCandidate; -import de.qtc.rmg.io.Logger; import de.qtc.rmg.operations.RemoteObjectClient; import de.qtc.rmg.plugin.PluginSystem; import de.qtc.rmg.plugin.ReturnValueProvider; @@ -112,6 +110,11 @@ public boolean isRemotingCall(MethodCandidate targetMethod) return true; } + public String getInterfaceName() + { + return remotingInterfaceName; + } + public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMethod, Object[] args) { RemoteInvocation invo = new RemoteInvocation(); @@ -149,9 +152,9 @@ public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMetho return invo; } - public static Map buildInvocationMap(Set candidates) + public static Set getInvocationHolders(Set candidates) { - Map invocationMap = new HashMap(); + Set invocationHolderSet = new HashSet(); for (MethodCandidate candidate : candidates) { @@ -162,15 +165,31 @@ public static Map buildInvocationMap(Set Date: Tue, 7 Nov 2023 18:50:38 +0100 Subject: [PATCH 21/60] Prevent leakage of local ysoserial path When using remote-method-guessers ysoserial integration, gadget objects created by ysoserial were annotated by the marshaloutput stream. This annotation included the absoulte file system path of the ysoserial library, which represents a low impact information disclosure. Since remote-method-guesser already overrides the default RMIClassLoader, this behavior was now changed by always returning null as result of the getClassAnnotation method. --- src/de/qtc/rmg/internal/CodebaseCollector.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/de/qtc/rmg/internal/CodebaseCollector.java b/src/de/qtc/rmg/internal/CodebaseCollector.java index c02b9a1..c479c70 100644 --- a/src/de/qtc/rmg/internal/CodebaseCollector.java +++ b/src/de/qtc/rmg/internal/CodebaseCollector.java @@ -190,10 +190,14 @@ public ClassLoader getClassLoader(String codebase) throws MalformedURLException * function to return the codebase only supports String types. The currently selected approach * of rmg (which is the MaliciousOutputStream class) allows arbitrary objects and is therefore * more flexible. + * + * Since version v4.5.0, this function always returns null instead of invoking the original loaders + * getClassAnnotation method. This was changed, as the original loaders getClassAnnotation method + * leaked the local ysoserial path when using remote-method-guessers ysoserial integration. */ public String getClassAnnotation(Class cl) { - return originalLoader.getClassAnnotation(cl); + return null; } /** From 298f0033ab8a8e48187df8006fb1608063db4976 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 12 Nov 2023 07:04:53 +0100 Subject: [PATCH 22/60] Add custom socket factory obj to ExampleServer A new RemoteObject was added to port 9010 of the ExampleServer. This remote object is registred with a custom RMISocketFactory to allow tests of the dynamic SockerFactory creation feature of remote-method-guesser. --- .../resources/server/CHANGELOG.md | 19 +++++ .../example-server/resources/server/pom.xml | 7 +- .../src/de/qtc/rmg/server/ExampleServer.java | 70 +++++++++++++------ .../server/activation/ActivationServer.java | 45 ++++++------ .../server/activation/ActivationService.java | 2 +- .../server/activation/ActivationService2.java | 2 +- .../server/activation/IActivationService.java | 2 +- .../activation/IActivationService2.java | 2 +- .../server/factory/CustomSocketFactory.java | 28 ++++++++ .../factory/CustomSocketFactoryServer.java | 52 ++++++++++++++ .../qtc/rmg/server/legacy/LegacyServer.java | 64 +++++++++-------- .../src/de/qtc/rmg/server/utils/Utils.java | 2 +- 12 files changed, 218 insertions(+), 77 deletions(-) create mode 100644 docker/example-server/resources/server/CHANGELOG.md create mode 100644 docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java create mode 100644 docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java diff --git a/docker/example-server/resources/server/CHANGELOG.md b/docker/example-server/resources/server/CHANGELOG.md new file mode 100644 index 0000000..c7ffed1 --- /dev/null +++ b/docker/example-server/resources/server/CHANGELOG.md @@ -0,0 +1,19 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + +## v4.1.0 - Nov 12, 2023 + +### Added + +* Add an additional RemoteObject using a custom socket factory class + + +## v4.0.0 and before + +Changelog entries can be found within the global [CHANGELOG.md](/CHANGELOG.md) file +of remote-method-guesser. diff --git a/docker/example-server/resources/server/pom.xml b/docker/example-server/resources/server/pom.xml index c3694b5..3e4a730 100644 --- a/docker/example-server/resources/server/pom.xml +++ b/docker/example-server/resources/server/pom.xml @@ -3,7 +3,7 @@ 4.0.0 de.qtc.rmg.server.ExampleServer rmg-example-server - 3.3.0 + 4.1.0 rmg-example-server RMG Example Server @@ -49,6 +49,11 @@ de.qtc.rmg.server.ExampleServer + + + Tobias Neitzel (@qtc_de) + + jar-with-dependencies diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java index 39dc38f..261ebd9 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java @@ -12,6 +12,7 @@ import javax.rmi.ssl.SslRMIServerSocketFactory; import de.qtc.rmg.server.activation.ActivationServer; +import de.qtc.rmg.server.factory.CustomSocketFactoryServer; import de.qtc.rmg.server.interfaces.IPlainServer; import de.qtc.rmg.server.interfaces.ISecureServer; import de.qtc.rmg.server.interfaces.ISslServer; @@ -22,28 +23,40 @@ import de.qtc.rmg.server.utils.Logger; import de.qtc.rmg.server.utils.Utils; -public class ExampleServer { +public class ExampleServer +{ + private static final int registryPort = 1090; + private static final int activatorPort = 1098; + private static final int plainRegistryPort = 9010; - private static int registryPort = 1090; - private static Remote remoteObject1 = null; - private static Remote remoteObject2 = null; - private static Remote remoteObject3 = null; + private static Remote remoteObjectOne; + private static Remote remoteObjectTwo; + private static Remote remoteObjectThree; + + private static final String boundNameOne = "plain-server"; + private static final String boundNameTwo = "ssl-server"; + private static final String boundNameThree = "secure-server"; public static void main(String[] argv) { String disableColor = System.getProperty("de.qtc.rmg.server.disableColor"); + if (disableColor != null && disableColor.equalsIgnoreCase("true")) + { Logger.disableColor(); + } Logger.println("Initializing Java RMI Server:"); Logger.println(""); Logger.increaseIndent(); - if (System.getSecurityManager() == null) { + if (System.getSecurityManager() == null) + { System.setSecurityManager(new SecurityManager()); } - try { + try + { SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory(); SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory(); @@ -53,30 +66,47 @@ public static void main(String[] argv) Logger.println(""); Logger.printlnMixedBlue("Creating", "PlainServer", "object."); - remoteObject1 = new PlainServer(); - IPlainServer stub = (IPlainServer)UnicastRemoteObject.exportObject(remoteObject1, 0); - Utils.bindToRegistry(stub, registry, "plain-server"); + remoteObjectOne = new PlainServer(); + IPlainServer stub = (IPlainServer)UnicastRemoteObject.exportObject(remoteObjectOne, 0); + Utils.bindToRegistry(stub, registry, boundNameOne); Logger.printlnMixedBlue("Creating", "SSLServer", "object."); - remoteObject2 = new SslServer(); - ISslServer stub2 = (ISslServer)UnicastRemoteObject.exportObject(remoteObject2, 0, csf, ssf); - Utils.bindToRegistry(stub2, registry, "ssl-server"); + remoteObjectTwo = new SslServer(); + ISslServer stub2 = (ISslServer)UnicastRemoteObject.exportObject(remoteObjectTwo, 0, csf, ssf); + Utils.bindToRegistry(stub2, registry, boundNameTwo); Logger.printlnMixedBlue("Creating", "SecureServer", "object."); - remoteObject3 = new SecureServer(); - ISecureServer stub3 = (ISecureServer)UnicastRemoteObject.exportObject(remoteObject3, 0); - Utils.bindToRegistry(stub3, registry, "secure-server"); + remoteObjectThree = new SecureServer(); + ISecureServer stub3 = (ISecureServer)UnicastRemoteObject.exportObject(remoteObjectThree, 0); + Utils.bindToRegistry(stub3, registry, boundNameThree); Logger.decreaseIndent(); Logger.println(""); Logger.println("Server setup finished."); - Logger.println("Initializing legacy server."); + Logger.println("Initializing LegacyServer."); + Logger.println(""); + + LegacyServer.init(plainRegistryPort); + + Logger.println("LegacyServer setup finished."); + Logger.println("Initializing ActivationServer."); Logger.println(""); - LegacyServer.init(); - ActivationServer.init(); + ActivationServer.init(activatorPort); + + Logger.println("ActivationServer setup finished."); + Logger.println("Initializing CustomSocketFactoryServer."); + Logger.println(""); + + CustomSocketFactoryServer.startServer(plainRegistryPort); + + Logger.println("Setup finished."); + Logger.println("Waiting for incoming connections."); + Logger.println(""); + } - } catch (RemoteException | AlreadyBoundException | NotBoundException e) { + catch (RemoteException | AlreadyBoundException | NotBoundException e) + { Logger.eprintln("Unexpected RMI Error:"); e.printStackTrace(); } diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java index ee1abab..02c777d 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java @@ -30,10 +30,13 @@ @SuppressWarnings("unused") public class ActivationServer { - private static int activationSystemPort = 1098; - private static Remote remoteObject1 = null; - private static Remote remoteObject2 = null; - private static Remote remoteObject3 = null; + private static Remote remoteObjectOne; + private static Remote remoteObjectTwo; + private static Remote remoteObjectThree; + + private static final String boundNameOne = "activation-test"; + private static final String boundNameTwo = "activation-test2"; + private static final String boundNameThree = "plain-server"; private final static String codebase = "file:///opt/example-server.jar"; @@ -42,11 +45,12 @@ public class ActivationServer * group is created and two activatable RMI services are bound to the registry. Additionally, we bind one * non activatable service. */ - public static void init() + public static void init(int activationSystemPort) { Logger.increaseIndent(); - try { + try + { Logger.printMixedBlue("Creating", "ActivationSystem", "on port "); Logger.printlnPlainYellow(String.valueOf(activationSystemPort)); Utils.startActivation(activationSystemPort, null, "/tmp/activation-log", null); @@ -90,28 +94,25 @@ public static void init() Utils.toogleOutput(); ActivationDesc desc = new ActivationDesc(groupID, ActivationService.class.getName(), codebase, null); - remoteObject1 = Activatable.register(desc); + remoteObjectOne = Activatable.register(desc); ActivationDesc desc2 = new ActivationDesc(groupID, ActivationService2.class.getName(), codebase, null); - remoteObject2 = Activatable.register(desc2); - - remoteObject3 = new PlainServer(); - IPlainServer stub = (IPlainServer)UnicastRemoteObject.exportObject(remoteObject3, 0); - - Utils.bindToRegistry(remoteObject1, LocateRegistry.getRegistry(activationSystemPort), "activation-test"); - Utils.bindToRegistry(remoteObject2, LocateRegistry.getRegistry(activationSystemPort), "activation-test2"); - Utils.bindToRegistry(stub, LocateRegistry.getRegistry(activationSystemPort), "plain-server"); + remoteObjectTwo = Activatable.register(desc2); - Logger.println(""); - Logger.decreaseIndent(); + remoteObjectThree = new PlainServer(); + IPlainServer stub = (IPlainServer)UnicastRemoteObject.exportObject(remoteObjectThree, 0); - Logger.println("Server setup finished."); - Logger.println("Waiting for incoming connections."); - Logger.println(""); + Utils.bindToRegistry(remoteObjectOne, LocateRegistry.getRegistry(activationSystemPort), boundNameOne); + Utils.bindToRegistry(remoteObjectTwo, LocateRegistry.getRegistry(activationSystemPort), boundNameTwo); + Utils.bindToRegistry(stub, LocateRegistry.getRegistry(activationSystemPort), boundNameThree); + } - } catch (Exception e) { + catch (Exception e) + { Logger.eprintln("Unexpected RMI Error:"); e.printStackTrace(); } - } + + Logger.println(""); + Logger.decreaseIndent(); } } diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java index cb0a6cd..011c182 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java @@ -54,4 +54,4 @@ public String system(String command, String[] args) return result; } -} \ No newline at end of file +} diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java index 0db0a0a..f2c5673 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java @@ -55,4 +55,4 @@ public void updatePreferences(ArrayList preferences) throws RemoteExcept Logger.printlnMixedBlueYellow("[SecureServer]:", "Processing call for", "void updatePreferences(ArrayList preferences)"); this.preferences = preferences; } -} \ No newline at end of file +} diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java index e74260c..40ed5cf 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java @@ -7,4 +7,4 @@ public interface IActivationService extends Remote { String execute(String cmd) throws RemoteException; String system(String cmd, String[] args) throws RemoteException; -} \ No newline at end of file +} diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java index adde23e..1bf8094 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java @@ -10,4 +10,4 @@ public interface IActivationService2 extends Remote String login(HashMap credentials) throws RemoteException; void logMessage(int logLevel, Object message) throws RemoteException; void updatePreferences(ArrayList preferences) throws RemoteException; -} \ No newline at end of file +} diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java new file mode 100644 index 0000000..202ced7 --- /dev/null +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java @@ -0,0 +1,28 @@ +package de.qtc.rmg.server.factory; + +import java.io.IOException; +import java.io.Serializable; +import java.net.ServerSocket; +import java.net.Socket; +import java.rmi.server.RMISocketFactory; + +public class CustomSocketFactory extends RMISocketFactory implements Serializable +{ + private static final long serialVersionUID = -1168901302380021730L; + private final transient RMISocketFactory defaultFax; + + public CustomSocketFactory() + { + defaultFax = RMISocketFactory.getDefaultSocketFactory(); + } + + public ServerSocket createServerSocket(int arg0) throws IOException + { + return defaultFax.createServerSocket(arg0); + } + + public Socket createSocket(String arg0, int arg1) throws IOException + { + return defaultFax.createSocket(arg0, arg1); + } +} diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java new file mode 100644 index 0000000..dffae55 --- /dev/null +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java @@ -0,0 +1,52 @@ +package de.qtc.rmg.server.factory; + +import java.rmi.AlreadyBoundException; +import java.rmi.NotBoundException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.RMISocketFactory; +import java.rmi.server.UnicastRemoteObject; + +import de.qtc.rmg.server.interfaces.IPlainServer; +import de.qtc.rmg.server.operations.PlainServer; +import de.qtc.rmg.server.utils.Logger; +import de.qtc.rmg.server.utils.Utils; + +public class CustomSocketFactoryServer +{ + private static Remote remoteObjectOne;; + private static final String boundName = "custom-socks"; + + public static void startServer(int registryPort) + { + Logger.increaseIndent(); + + try + { + RMISocketFactory csf = new CustomSocketFactory(); + + Logger.printMixedBlue("Locating", "RMI-Registry", "on port "); + Logger.printlnPlainYellow(String.valueOf(registryPort)); + Registry registry = LocateRegistry.getRegistry(registryPort); + Logger.println(""); + + Logger.printlnMixedBlue("Creating", "PlainServer", "object."); + remoteObjectOne = new PlainServer(); + IPlainServer stub = (IPlainServer)UnicastRemoteObject.exportObject(remoteObjectOne, 0, csf, null); + Utils.bindToRegistry(stub, registry, boundName); + + Logger.println("Server setup finished."); + } + + catch (RemoteException | AlreadyBoundException | NotBoundException e) + { + Logger.eprintln("Unexpected RMI Error:"); + e.printStackTrace(); + } + + Logger.println(""); + Logger.decreaseIndent(); + } +} diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java index 4baa313..2af8e65 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java @@ -16,71 +16,77 @@ import de.qtc.rmg.server.utils.Utils; @SuppressWarnings("unused") -public class LegacyServer { - - private static int registryPort = 9010; - private static Remote remoteObject1 = null; - private static Remote remoteObject2 = null; - private static Remote remoteObject3 = null; - private static Remote remoteObject4 = null; - - - public static void init() +public class LegacyServer +{ + private static Remote remoteObjectOne; + private static Remote remoteObjectTwo; + private static Remote remoteObjectThree; + private static Remote remoteObjectFour; + + private static final String boundNameOne = "legacy-service"; + private static final String boundNameTwo = "plain-server"; + private static final String boundNameThree = "plain-server2"; + + public static void init(int registryPort) { Logger.increaseIndent(); - try { + try + { Logger.printMixedBlue("Creating", "RMI-Registry", "on port "); Logger.printlnPlainYellow(String.valueOf(registryPort)); Registry registry = LocateRegistry.createRegistry(registryPort); Logger.println(""); Logger.printlnMixedBlue("Creating", "LegacyServiceImpl", "object."); - remoteObject1 = new LegacyServiceImpl(); + remoteObjectOne = new LegacyServiceImpl(); Logger.increaseIndent(); Logger.printMixedYellow("Binding", "LegacyServiceImpl"); Logger.printlnPlainMixedBlue(" as", "legacy-service"); - Naming.rebind("//127.0.0.1:" + registryPort + "/legacy-service", remoteObject1); + Naming.rebind("//127.0.0.1:" + registryPort + "/legacy-service", remoteObjectOne); Object o = registry.lookup("legacy-service"); String className = o.getClass().getName(); - Logger.printMixedYellow("Boundname", "legacy-service"); + Logger.printMixedYellow("Boundname", boundNameOne); Logger.printlnPlainMixedBlue(" with class", className, "is ready."); Logger.decreaseIndent(); Logger.printlnMixedBlue("Creating", "PlainServer", "object."); - remoteObject2 = new PlainServer(); - IPlainServer stub1 = (IPlainServer)UnicastRemoteObject.exportObject(remoteObject2, 0); - Utils.bindToRegistry(stub1, registry, "plain-server"); + remoteObjectTwo = new PlainServer(); + IPlainServer stub1 = (IPlainServer)UnicastRemoteObject.exportObject(remoteObjectTwo, 0); + Utils.bindToRegistry(stub1, registry, boundNameTwo); Logger.printlnMixedBlue("Creating another", "PlainServer", "object."); - remoteObject3 = new PlainServer(); - IPlainServer stub2 = (IPlainServer)UnicastRemoteObject.exportObject(remoteObject3, 0); - Utils.bindToRegistry(stub2, registry, "plain-server2"); + remoteObjectThree = new PlainServer(); + IPlainServer stub2 = (IPlainServer)UnicastRemoteObject.exportObject(remoteObjectThree, 0); + Utils.bindToRegistry(stub2, registry, boundNameThree); - try { + try + { Logger.printlnMixedBlue("Creating", "ActivatorImp", "object."); Logger.increaseIndent(); - remoteObject4 = Utils.getActivator(registryPort, null); + remoteObjectFour = Utils.getActivator(registryPort, null); Logger.printlnMixedYellowFirst("Activator", "is ready."); + } - } catch( Exception e) { + catch (Exception e) + { Logger.printlnYellow("Activator initialization failed."); + } - } finally { + finally + { Logger.decreaseIndent(); } Logger.println(""); Logger.decreaseIndent(); + } - Logger.println("Server setup finished."); - Logger.println("Initializing activation server."); - Logger.println(""); - - } catch (RemoteException | MalformedURLException | AlreadyBoundException | NotBoundException e) { + catch (RemoteException | MalformedURLException | AlreadyBoundException | NotBoundException e) + { Logger.eprintln("Unexpected RMI Error:"); e.printStackTrace(); } diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java index df3d800..65463c7 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java @@ -114,4 +114,4 @@ public static void bindToRegistry(Remote object, Registry registry, String bound Logger.printlnPlainMixedBlue(" with interface", className, "is ready."); Logger.decreaseIndent(); } -} \ No newline at end of file +} From 522d868bbd00e1fa1c1d422ea887fda6b822c19e Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 14 Nov 2023 20:40:34 +0100 Subject: [PATCH 23/60] Add comments --- src/de/qtc/rmg/exceptions/SSRFException.java | 2 +- .../UnexpectedCharacterException.java | 2 +- src/de/qtc/rmg/internal/RMGOptionGroup.java | 2 +- src/de/qtc/rmg/internal/RMIComponent.java | 2 +- src/de/qtc/rmg/operations/MethodGuesser.java | 57 +++++++++++++++- .../rmg/operations/RemoteObjectClient.java | 10 ++- .../qtc/rmg/plugin/ReturnValueProvider.java | 19 ++++++ src/de/qtc/rmg/utils/EmptyWrapper.java | 2 +- src/de/qtc/rmg/utils/RMGUtils.java | 67 +++---------------- .../qtc/rmg/utils/RemoteInvocationHolder.java | 26 +++++++ src/de/qtc/rmg/utils/RogueJMX.java | 2 +- .../qtc/rmg/utils/SpringRemotingWrapper.java | 55 ++++++++++++++- 12 files changed, 175 insertions(+), 71 deletions(-) diff --git a/src/de/qtc/rmg/exceptions/SSRFException.java b/src/de/qtc/rmg/exceptions/SSRFException.java index 97f6c2b..2462de2 100644 --- a/src/de/qtc/rmg/exceptions/SSRFException.java +++ b/src/de/qtc/rmg/exceptions/SSRFException.java @@ -5,4 +5,4 @@ public class SSRFException extends Exception implements Serializable { private static final long serialVersionUID = 1L; -} \ No newline at end of file +} diff --git a/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java b/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java index 4461234..c9a0907 100644 --- a/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java +++ b/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java @@ -22,4 +22,4 @@ public UnexpectedCharacterException(String message) { super(message); } -} \ No newline at end of file +} diff --git a/src/de/qtc/rmg/internal/RMGOptionGroup.java b/src/de/qtc/rmg/internal/RMGOptionGroup.java index 7d517d4..0a57964 100644 --- a/src/de/qtc/rmg/internal/RMGOptionGroup.java +++ b/src/de/qtc/rmg/internal/RMGOptionGroup.java @@ -62,4 +62,4 @@ public ArgumentGroup addArgumentGroup(ArgumentParser argParser, Operation operat return group; } -} \ No newline at end of file +} diff --git a/src/de/qtc/rmg/internal/RMIComponent.java b/src/de/qtc/rmg/internal/RMIComponent.java index 248cdb8..6393dae 100644 --- a/src/de/qtc/rmg/internal/RMIComponent.java +++ b/src/de/qtc/rmg/internal/RMIComponent.java @@ -47,4 +47,4 @@ public static RMIComponent getByShortName(String shortName) return null; } -} \ No newline at end of file +} diff --git a/src/de/qtc/rmg/operations/MethodGuesser.java b/src/de/qtc/rmg/operations/MethodGuesser.java index d48e6f0..396a209 100644 --- a/src/de/qtc/rmg/operations/MethodGuesser.java +++ b/src/de/qtc/rmg/operations/MethodGuesser.java @@ -4,7 +4,6 @@ import java.io.StringWriter; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -22,6 +21,8 @@ import de.qtc.rmg.utils.RemoteInvocationHolder; import de.qtc.rmg.utils.SpringRemotingWrapper; import de.qtc.rmg.utils.UnicastWrapper; +import javassist.CannotCompileException; +import javassist.NotFoundException; /** * The MethodGuesser class is used to brute force available remote methods on Java RMI endpoints. It uses @@ -60,6 +61,10 @@ public class MethodGuesser * Furthermore, you need to specify a Set of MethodCandidates that represents the methods you want * to guess. * + * If one of the UnicastWrapper objects within the array is a SpringRemotingWrapper, the set of + * MethodCandidates gets cloned and transformed into a set of RemoteInvocation. Both sets are still + * available and the guessing procedure decides based on the wrapper type which set should be used. + * * @param remoteObjects Array of looked up remote objects from the RMI registry * @param candidates MethodCandidates that should be guessed */ @@ -203,9 +208,23 @@ private UnicastWrapper[] handleKnownMethods(UnicastWrapper[] remoteObjects) else { + List knownMethods = new ArrayList(); RemoteObjectClient knownClient = new RemoteObjectClient(o); - knownClient.addRemoteMethods(RMGUtils.getKnownMethods(o.getInterfaceName())); + for (String method : o.knownEndpoint.getRemoteMethods()) + { + try + { + knownMethods.add(new MethodCandidate(method)); + } + + catch (CannotCompileException | NotFoundException e) + { + Logger.printlnMixedYellowFirst("Internal Error", "- Unable to compile known method with signature: " + method); + } + } + + knownClient.addRemoteMethods(knownMethods); knownClientList.add(knownClient); } } @@ -267,7 +286,8 @@ else if (clientList.size() == 0) /** * This method starts the actual guessing process. It creates a GuessingWorker for each remoteClient in the clientList - * and for each Set of MethodCandidates in the candidateSets. + * and for each Set of MethodCandidates in the candidateSets. If the underlying RemoteObjectWrapper type of a client + * is a SpringRemotingWrapper, the spring remoting compatible SpringGuessingWorker will be used. * * @return List of RemoteObjectClient containing the successfully guessed methods. Only clients containing * guessed methods are returned. Clients without guessed methods are filtered. @@ -428,12 +448,23 @@ public void run() } } + /** + * The SpringGuessingWorker does basically the same as the GuessingWorker, but for spring remoting :) + * + * @author Tobias Neitzel (@qtc_de) + */ private class SpringGuessingWorker implements Runnable { protected String boundName; protected RemoteObjectClient client; protected Set invocationHolders; + /** + * Initialize the spring guessing worker with all the required information. + * + * @param client RemoteObjectClient to the targeted remote object + * @param invocationHolders set of RemoteInvocationHolders that contain the RemoteInvocations to guess + */ public SpringGuessingWorker(RemoteObjectClient client, Set invocationHolders) { this.client = client; @@ -441,6 +472,12 @@ public SpringGuessingWorker(RemoteObjectClient client, Set list) - */ - public static List getKnownMethods(String className) - { - List knownMethods = new ArrayList(); - - try { - CtClass knownClass = pool.getCtClass(className); - - if( knownClass.isInterface() ) - addKnownMethods(knownClass, knownMethods); - - for(CtClass intf : knownClass.getInterfaces()) { - - if(! isAssignableFrom(intf, "java.rmi.Remote")) - continue; - - addKnownMethods(intf, knownMethods); - } - - } catch(Exception e) { - ExceptionHandler.unexpectedException(e, "translation process", "of known remote methods", false); - } - - return knownMethods; - } - - /** - * Same as the previous addKnownMethods function, but takes the corresponding interface as argument directly. - * This function is called by the previous addKnownMethods function to add the methods. - * - * @param intf Interface class to add methods from - * @param boundName bound name that is using the known class - * @param guessedMethods list of successfully guessed methods (bound name -> list) - */ - public static void addKnownMethods(CtClass intf, List knownMethodCandidates) - { - try { - CtMethod[] knownMethods = intf.getDeclaredMethods(); - - for(CtMethod knownMethod: knownMethods) - knownMethodCandidates.add(new MethodCandidate(knownMethod)); - - } catch(Exception e) { - ExceptionHandler.unexpectedException(e, "translation process", "of known remote methods", false); - } - } - /** * Returns a human readable method signature of a CtMethod. Builtin methods only return the signature in * a non well formatted format. This function is used to display known remote methods as the result of a @@ -1332,6 +1274,15 @@ public static long getSerialVersionUID(InvalidClassException e) return Long.parseLong(message); } + /** + * Convert a CtClass back to an ordinary Class object. This method is intended to be called + * for classes that are known to already exist within the JVM. No compilation is triggered but + * the Class object is simply obtained by Class.forName (including handling for all the edge + * cases). + * + * @param type the CtClass that should be converted back to a Class object + * @return Class associated to the specified CtClass + */ public static Class ctClassToClass(CtClass type) throws ClassNotFoundException, NotFoundException { if (type.isPrimitive()) diff --git a/src/de/qtc/rmg/utils/RemoteInvocationHolder.java b/src/de/qtc/rmg/utils/RemoteInvocationHolder.java index b2238d1..17e5394 100644 --- a/src/de/qtc/rmg/utils/RemoteInvocationHolder.java +++ b/src/de/qtc/rmg/utils/RemoteInvocationHolder.java @@ -6,17 +6,43 @@ import de.qtc.rmg.internal.MethodCandidate; + +/** + * RemoteInvocation objects do not contain all information that MethodCandidates contain. When converting + * a MethodCandidate to a RemoteInvocation, information like the signature or the return value get lost. + * Moreover, two RemoteInvocations can be considered the same when they have a similar name and similar + * method arguments. The return value does not matter. + * + * The RemoteInvocationHolder class is designed to overcome these problems. It tracks the associated + * MethodCandidate to each RemoteInvocation and implements methods that allow to compare RemoteInvocations + * and to filter duplicates. + * + * @author Tobias Neitzel (@qtc_de) + */ public class RemoteInvocationHolder { private RemoteInvocation invo; private MethodCandidate candidate; + /** + * An RemoteInvocationWrapper simply contains a RemoteInvocation and the associated MethodCandidate. + * + * @param invo the RemoteInvocation + * @param candidate the associated MethodCandidate + */ public RemoteInvocationHolder(RemoteInvocation invo, MethodCandidate candidate) { this.invo = invo; this.candidate = candidate; } + /** + * Two RemoteInocationHolders are the same, if their contained RemoteInvocation uses the same + * method name and the same argument types. + * + * @param other Object to compare with + * @return true if the objects can be considered the same + */ public boolean equals(Object other) { if (other instanceof RemoteInvocationHolder) diff --git a/src/de/qtc/rmg/utils/RogueJMX.java b/src/de/qtc/rmg/utils/RogueJMX.java index 29ea49d..e0a48ab 100644 --- a/src/de/qtc/rmg/utils/RogueJMX.java +++ b/src/de/qtc/rmg/utils/RogueJMX.java @@ -225,4 +225,4 @@ public RMIConnection newClient(Object credentials) throws IOException return conditionalForward(credentials, "Authentication failed!"); } -} \ No newline at end of file +} diff --git a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java index baf4fa7..97c5305 100644 --- a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java +++ b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java @@ -10,6 +10,7 @@ import de.qtc.rmg.internal.ExceptionHandler; import de.qtc.rmg.internal.MethodCandidate; import de.qtc.rmg.operations.RemoteObjectClient; +import de.qtc.rmg.plugin.IResponseHandler; import de.qtc.rmg.plugin.PluginSystem; import de.qtc.rmg.plugin.ReturnValueProvider; import javassist.CannotCompileException; @@ -36,11 +37,21 @@ public class SpringRemotingWrapper extends UnicastWrapper private static String remotingInterfaceName; + /** + * Within it's constructor, SpringRemotingWrapper already sends an RMI call to the server using the getTargetInterfaceName method. + * This is required to tell remote-method-guesser what the underlying interface class is. This information is displayed within the + * enum output and used for identifying potentialy known endpoints. + * + * @param remoteObject the spring remoting remoteObject obtained from the registry + * @param boundName the boundName that is associated with the remoteObject + * @param ref a UnicastRef that can be used to call methods on the remoteObject + */ public SpringRemotingWrapper(Remote remoteObject, String boundName, UnicastRef ref) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { super(remoteObject, boundName, ref); ReturnValueProvider respHandler = new ReturnValueProvider(); + IResponseHandler cachedHandler = PluginSystem.getResponseHandler(); PluginSystem.setResponeHandler(respHandler); RemoteObjectClient client = new RemoteObjectClient(this); @@ -48,6 +59,8 @@ public SpringRemotingWrapper(Remote remoteObject, String boundName, UnicastRef r remotingInterfaceName = (String)respHandler.getValue(); knownEndpoint = KnownEndpointHolder.getHolder().lookup(remotingInterfaceName); + + PluginSystem.setResponeHandler(cachedHandler); } /** @@ -98,6 +111,12 @@ public static MethodCandidate getInvokeMethod() return methodInvoke; } + /** + * Determines whether the method to call is a known spring remoting method, that needs to be processed by the + * remoting wrapper itself, or whether it is an RMI method implemented by the underlying object. + * + * @return true if the method needs to be dispatched using spring remoting + */ public boolean isRemotingCall(MethodCandidate targetMethod) { long targetHash = targetMethod.getHash(); @@ -110,11 +129,24 @@ public boolean isRemotingCall(MethodCandidate targetMethod) return true; } + /** + * Return the interface name of the underlying interface class that can be accessed via spring remoting. + * + * @return interface name implemented by the underlying remote object + */ public String getInterfaceName() { return remotingInterfaceName; } + /** + * Prepare a RemoteInvocation object from a MethodCandidate and the user specified arguments. The resulting + * object can be passed to the spring remoting endpoint in order to call the specified MethodCandidate. + * + * @param targetMethod method that should be called via spring remoting + * @param args arguments that should be used for the call + * @return RemoteInvocation that can be passed to the spring remoting server + */ public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMethod, Object[] args) { RemoteInvocation invo = new RemoteInvocation(); @@ -152,6 +184,12 @@ public static RemoteInvocation buildRemoteInvocation(MethodCandidate targetMetho return invo; } + /** + * Transform a set of MethodCandidate to a set of RemoteInvocationHolders. + * + * @param candidates v set of MethodCandidate to transform + * @return set of RemoteInvocationHolders + */ public static Set getInvocationHolders(Set candidates) { Set invocationHolderSet = new HashSet(); @@ -165,7 +203,6 @@ public static Set getInvocationHolders(Set getInvocationHolders(Set Date: Tue, 14 Nov 2023 21:24:20 +0100 Subject: [PATCH 24/60] Add spring-remoting documentation --- docs/rmg/spring-remoting.md | 51 +++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 docs/rmg/spring-remoting.md diff --git a/docs/rmg/spring-remoting.md b/docs/rmg/spring-remoting.md new file mode 100644 index 0000000..44b9e8b --- /dev/null +++ b/docs/rmg/spring-remoting.md @@ -0,0 +1,51 @@ +### Spring Remoting + +---- + +The *Spring Framework* offers several methods of remoting and also provides a wrapper +around *RMI*. Despite support for serialization based remoting was removed in most recent +Spring versions (v6), it can still be encountered quite often. + +RMI via Spring Remoting is a little bit different than plain Java RMI. Instead of creating +a `RemoteObject` and registering it within an *RMI Registry*, Spring uses a wrapper `RemoteObject` +that gets registered within the registry instead. This wrapper contains a reference to the actual +object where calls should be performed on and supports the following methods: + +```java +java.lang.String getTargetInterfaceName() +java.lang.Object invoke(org.springframework.remoting.support.RemoteInvocation invo) +``` + +As you probably already guessed `getTargetInterfaceName` returns the name of the interface that +is implemented by the underlying object. The `invoke` method on the other hand is used to forward +method calls to the underlying object. The `RemoteInvocation` type contains all information required +for the method call, including the method name, the method argument types and the respective +argument values. The `invoke` method looks up the requested method via reflection and calls it +using the specified argument types. + + +### remote-method-guesser and Spring Remoting + +---- + +When *remote-method-guesser* encounters a Spring Remoting `RemoteObject` it highlights this already +during the enum action. For Spring Remoting based RemoteObjects, the underlying interface type is +displayed along with the usual information. + +Method calls dispatched via the [call](https://github.com/qtc-de/remote-method-guesser#call) action +are always wrapped into `RemoteInvocation` calls instead. This means that remote-method-guesser always +performs calls on the underlying object that is enclosed in the Spring Remoting wrapper. Exceptions +are made for the two known methods mentioned above. These will be dispatched on the wrapper object +itself. If you want to enforce forwarding via `RemoteInvocation`, you can use the `--spring-remoting` +option. + +Method guessing is always performed on the underlying object contained within the Spring Remoting +wrapper. All method candidates are wrapped into `RemoteInvocations` and send to the underlying object +via the `invoke` method. Since valid RMI calls have to be used, the different protocol based performance +boost techniques described in the [guessing docs](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/method-guessing.md) +do not apply to Spring Remoting. However, as method lookups are done via reflection and the methods +argument types and argument values are passed separately, it is still possible to use argument-confusion +to prevent accidental calls of RMI methods. Another advantage of Spring Remotings reflection based lookup +is that return values are not taken into account. Therefore, methods can be guessed by name and argument +types alone. remote-method-guesser automatically filters return value based duplicates out of method +wordlists. From 3e223f220a3de8e95d1a8d03ac0d89b14deb458e Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 19 Nov 2023 23:06:03 +0100 Subject: [PATCH 25/60] Add notes on inline-gadgets --- .gitignore | 2 + docs/rmg/inline-gadgets.md | 134 +++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 docs/rmg/inline-gadgets.md diff --git a/.gitignore b/.gitignore index 85f2342..87e85b8 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ buildNumber.properties .project .settings/ .internal/ +*.swp +*.bak diff --git a/docs/rmg/inline-gadgets.md b/docs/rmg/inline-gadgets.md new file mode 100644 index 0000000..a83f959 --- /dev/null +++ b/docs/rmg/inline-gadgets.md @@ -0,0 +1,134 @@ +### Inline Gadgets + +---- + +Since it's early days, *remote-method-guesser* provides a *ysoserial* integration, +that allows to create *ysoserial* gadgets by using command line parameters passed +within the *rmg* command line. For most situations, this approach is sufficient, +but sometimes support for *inline gadgets* would be useful. With *inline gadgets* +we mean gadgets that are passed e.g. as base64 encoded command line parameter. +This would e.g. allow to use serialization based rmg actions without having the +*ysoserial* even present. + +For version *v4.5.0* of remote-method-guesser, *inline gadgets* were part of the +roadmap. However, as it turned out, our considerations on how to implement them +were too naive and at the end, this feature was not implemented at all. In this +document we want to write down some of the problems we encountered, how they could +have been resolved and why we did not follow this path. + + +### ObjectOutputStream + +---- + +Our first concern was to write the user supplied object to the `ObjectOutputStream` +that one can obtain by calling the `getOutputStream` method on a `StreamRemoteCall` +object. Luckily, remote-method-guesser [already implemented](https://github.com/qtc-de/remote-method-guesser/blob/master/src/de/qtc/rmg/networking/RMIEndpoint.java#L157) +*RMI* calls on such a low level that all this stuff can be accessed quite easily. +Writing the user supplied object is however not that straight forward. We do not +want to deserialize the object, as this would require all gadget libraries to be +present and would lead to payload execution on the executing system. Just writing +the object as bytes to the output stream would also not work, as Java would mark +these bytes as a *byte array* within the output stream and they would not be +interpreted as object on the server side. Tampering with the `ObjectOutputStream` +implementation is therefore required. + +One of our first approaches was to subclass `ObjectOutputStream` and to overwrite +the `writeObject` method. We implemented a class `GadgetHolder` that contained +the user supplied gadget as byte array. The custom implementation of `writeObject` +checked whether the current object to be written is a `GadgetHolder` and wrote the +contained byte array directly to the `BlockDataOutputStream` that is part of each +`ObjectOutputStream`. + +Since the stream you get from `StreamRemoteCall` is already an `ObjectOutputStream`, +the above mentioned subclass was wrapped essentially an `ObjectOutputStream` wrapped +around an `ObjectOutputStream`. For this to work, it is important to overwrite the +`writeStreamHeader` method, to prevent any stream headers from being written during +the wrapping. Moreover, when writing to `BlockDataOutputStream`, one needs to make +sure that the correct `BlockDataMode` is configured on this stream. + +At the end, everything seemed to work well, but remote-method-guessers *gadget canaries* +made us aware, that this implementation is not working for nested objects. When +remote-method-guesser sends a gadget to the application server, it wraps this gadget +into an `Object` array. The first item within this array is the gadget, whereas the second +one is a dynamically created class. The application server will only attempt to deserialize +the second object, if the deserialization of the first one was successful. By checking for +a `ClassNotFound` exception containing the name of the dynamically created class, successful +gadget deserialization can be verified. + +When our subclassed `ObjectOutputStream` attempted to serialize the `Object` array, it used +the custom `writeObject` method. Since `Object[]` is not `GadgetHolder`, it called the superclass +implementation of `writeObject`. For an array however, `writeObject` does not use `writeObject` +to write the contained items to the stream, but uses `writeObject0` instead. This is a private +method and will therefore always use the implementation of the superclass. Nesting `GadgetHolder` +in any kind of other class is therefore not working. + +At this point we thought about removing *gadget canaries* when *inline gadgets* are used. But +this seemed not to be the *ideal* solution. After some other failed attempts, we thought that +operating on the underlying stream level would be the best. We associated a unique `SerialVersionUid` +to `GadgetHolder` and padded the user specified gadget with some static prefix and suffix bytes. +Within the `ObjectOutputStream` obtained from `StreamRemoteCall` we replaced the `BlockDataOutputStream` +with a custom stream class. This class checked for the `SerialVersionUid` of `GadgetHolder` and replaced +the object on the stream with the contents of the byte array contained in it's property. Sounds crazy, +but worked with great success - until we discovered the real problems. + + +### Reference Counting + +---- + +When serializing or deserializing objects, Java tracks certain locations (*handles*) within the stream +that might be referenced at a later point. E.g. if one object is referenced by several fields within a +class, the object only needs to be serialized once and each field can simply point to the already serialized +object. The handles themselves are not contained within the stream, but internally tracked during serialization +or deserialization. References to a handle are part of the stream. Handles are of type `int` and the internal +tracker starts at a value of `0x7e0000`. Each new handle increments this tracker by one. + +When creating a payload object using *ysoserial*, it usually contains a lot of these references. This again +causes problems with remote-method-guessers *gadget canaries*. When the actual payload object is wrapped inside +an `Object` array, the `Object` array type gets written first to the stream. Since this type could be referenced +later on, a handle is created for it. The handle count within the stream is no longer in sync with the handle count +that was used by *ysoserial* during the serialization. Therefore, the payload object will not be deserialized +correctly. + +This problem could be fixed by shifting the handle references within a payload object with the required value. +Sounds easy, but such an approach would require to reliably identify handle references within a payload object. +A simply match and replace for `0x7e....` would obviously not work, as such a value could appear in other locations +of the stream too. Therefore, one would need to implement a serialization parser like e.g. [SerializationDumper](https://github.com/NickstaDB/SerializationDumper) +and include it into remote-method-guesser. A lot of implementation effort - and at the end, it is still quite hacky. + +At this point we decided to drop *gadget canaries* when using *inline gadgets*, but the real problem is yet to come. + + +### MarshalOutputStream + +---- + +After implementing the above mentioned changes, the deserialization still did not work as expected. Comparing +the network traffic when using the ysoserial integration with the traffic created by an inline gadget revealed +that the former contained additional `TC_NULL` bytes that were missing within the inline gadget. This made us +remember something we already knew, but totally had forgotten. + +As it turned out, the assumption that `getOutputStream` on `StreamRemoteCall` returns an `ObjectOutputStream` was +false. What you get is an `ObjectOutput`, but the underlying implementation is a `ConncetionOutputStream` - a class +that extends `MarshalOutputStream`. `MarshalOutputStream` is well known to remote-method-guesser, as this class is +responsible for adding annotations to classes, a feature that allows e.g. remote codebases to work in RMI. + +The problem is now that `MarshalOutputStream` **always** writes an annotation to a class. Even if a codebase is not +used and there is noting to annotate, a `null` gets still written. On the other hand, `MarshalInputStream` expects +these annotations also to be present. A gadget created by *ysoserial* however uses a classical `ObjectOutputStream`. +Therefore, these annotation bytes are missing and the `MarshalInputStream` fails to deserialize the object. + +This problem could again be overcome in different ways. The easiest approach would probably be to add a `--stream` option +to *ysoserial* that allows to select `MarshalOutputStream` for payload creation. However, this would still require users +to know about this problematic and to use the appropriate option during payload creation. Another option would be to add the +missing `TC_NULL` bytes on the already serialized object, but this would require again a serialization parser. + + +### Conclusion + +---- + +At the end, we decided against the *inline gadget* feature and will not implement it. If remote-method-guessers +*ysoserial* integration does not work for you, we recommend using the prebuild [docker image](https://github.com/qtc-de/remote-method-guesser/pkgs/container/remote-method-guesser%2Frmg) +that contains *ysoserial* in the *non-slim* versions and should work out of the box. From b09e9a5465b58fa564dcbad73588d002a7f731ef Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Mon, 27 Nov 2023 17:44:09 +0100 Subject: [PATCH 26/60] Add GenericPrint to codebase The GenericPrint plugin is now included into rmg per default and can be activated by using the --return-value option. --- src/de/qtc/rmg/internal/RMGOption.java | 3 +- src/de/qtc/rmg/operations/Operation.java | 1 + src/de/qtc/rmg/plugin/GenericPrint.java | 237 +++++++++++++++++++++++ src/de/qtc/rmg/plugin/PluginSystem.java | 58 ++++-- 4 files changed, 282 insertions(+), 17 deletions(-) create mode 100644 src/de/qtc/rmg/plugin/GenericPrint.java diff --git a/src/de/qtc/rmg/internal/RMGOption.java b/src/de/qtc/rmg/internal/RMGOption.java index 269ae62..84a2d4c 100644 --- a/src/de/qtc/rmg/internal/RMGOption.java +++ b/src/de/qtc/rmg/internal/RMGOption.java @@ -110,7 +110,8 @@ public enum RMGOption { SOCKET_FACTORY_SSL("--socket-factory-ssl", "enforce SSL connections from dynamically created socket factories", Arguments.storeTrue(), RMGOptionGroup.CONNECTION), SOCKET_FACTORY("--socket-factory", "dynamically create a socket factory class with the specified name", Arguments.store(), RMGOptionGroup.CONNECTION, "classname"), - SPRING_REMOTING("--spring-remoting", "enforce method calls to be dispatched via spring remoting", Arguments.storeTrue(), RMGOptionGroup.CONNECTION); + SPRING_REMOTING("--spring-remoting", "enforce method calls to be dispatched via spring remoting", Arguments.storeTrue(), RMGOptionGroup.CONNECTION), + GENERIC_PRINT("--return-value", "attempt to output the return value using GenericPrint", Arguments.storeTrue(), RMGOptionGroup.ACTION); public final String name; public final String description; diff --git a/src/de/qtc/rmg/operations/Operation.java b/src/de/qtc/rmg/operations/Operation.java index 6fe043d..ac8da52 100644 --- a/src/de/qtc/rmg/operations/Operation.java +++ b/src/de/qtc/rmg/operations/Operation.java @@ -75,6 +75,7 @@ public enum Operation { RMGOption.SOCKET_FACTORY, RMGOption.SOCKET_FACTORY_SSL, RMGOption.SOCKET_FACTORY_PLAIN, + RMGOption.GENERIC_PRINT, }), CODEBASE("dispatchCodebase", " ", "Perform remote class loading attacks", new RMGOption[] { diff --git a/src/de/qtc/rmg/plugin/GenericPrint.java b/src/de/qtc/rmg/plugin/GenericPrint.java new file mode 100644 index 0000000..863fa21 --- /dev/null +++ b/src/de/qtc/rmg/plugin/GenericPrint.java @@ -0,0 +1,237 @@ +package de.qtc.rmg.plugin; + +import java.io.File; +import java.lang.reflect.Array; +import java.rmi.Remote; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; + +import de.qtc.rmg.internal.ExceptionHandler; +import de.qtc.rmg.io.Logger; +import de.qtc.rmg.utils.ActivatableWrapper; +import de.qtc.rmg.utils.RemoteObjectWrapper; +import de.qtc.rmg.utils.SpringRemotingWrapper; +import de.qtc.rmg.utils.UnicastWrapper; + +/** + * GenericPrint is an rmg ResponseHandler plugin that attempts to print all incoming + * server responses. It compares the incoming object to some known data types and chooses + * reasonable defaults to visualize them. + * + * From remote-method-guesser v5.0.0, GenericPrint is included per default and does not need + * to be compiled separately. It can be enabled by using the --generic-print option. + * + * @author Tobias Neitzel (@qtc_de) + */ +public class GenericPrint implements IResponseHandler +{ + /** + * The handleResponse function is called with the incoming responseObject from the + * RMI server. Depending on the corresponding class, a different print action is + * chosen. + * + * @param responseObject Incoming object from an RMI server response + */ + public void handleResponse(Object responseObject) + { + Class responseClass = responseObject.getClass(); + + if(responseObject instanceof Collection) + { + handleCollection(responseObject); + } + + else if(responseObject instanceof Map) + { + handleMap(responseObject); + } + + else if(responseClass.isArray()) + { + handleArray(responseObject); + } + + else if(Remote.class.isAssignableFrom(responseClass)) + { + handleRemote((Remote)responseObject); + } + + else if(responseObject instanceof File) + { + handleFile((File)responseObject); + } + + else if(responseObject instanceof Byte) + { + handleByte((byte)responseObject); + } + + else + { + handleDefault(responseObject); + } + } + + /** + * For each item within an collection, call handleResponse on the corresponding + * item value. + * + * @param o Object of the Collection type + */ + public void handleCollection(Object o) + { + for(Object item: (Collection)o) + { + handleResponse(item); + } + } + + /** + * For each entry within a map, handleResponse is called on the entry key and value. + * Furthermore, an arrow is printed in an attempt to visualize their relationship. + * + * @param o Object of the Map type + */ + public void handleMap(Object o) + { + Map map = (Map)o; + + for(Entry item: map.entrySet()) + { + handleResponse(item.getKey()); + System.out.print(" --> "); + handleResponse(item.getValue()); + } + } + + /** + * For each item within an array, call the handleResponse function. + * + * @param o Object of the Array type + */ + public void handleArray(Object o) + { + Object[] objectArray = null; + Class type = o.getClass().getComponentType(); + + if(type.isPrimitive()) + { + int length = Array.getLength(o); + objectArray = new Object[length]; + + for(int ctr = 0; ctr < length; ctr++) + { + objectArray[ctr] = Array.get(o, ctr); + } + } + + else + { + objectArray = (Object[])o; + } + + for(Object item: objectArray) + { + handleResponse(item); + } + } + + /** + * For all objects that extend Remote, the details of the remote reference are printed. + * This includes the class name, the remote TCP endpoint, the assigned ObjID and the + * configured socket factories. + * + * @param o Object that extends the Remote type + */ + public void handleRemote(Remote o) + { + try + { + RemoteObjectWrapper objectWrapper = RemoteObjectWrapper.getInstance(o); + + if ((objectWrapper instanceof UnicastWrapper) || objectWrapper instanceof SpringRemotingWrapper) + { + UnicastWrapper wrapper = (UnicastWrapper)objectWrapper; + + String csf = "default"; + String ssf = "default"; + + if (wrapper.csf != null) + { + csf = wrapper.csf.getClass().getName(); + } + + if (wrapper.ssf != null) + { + ssf = wrapper.ssf.getClass().getName(); + } + + Logger.printlnYellow("Printing unicast RemoteObject:"); + Logger.increaseIndent(); + Logger.printlnMixedBlue("Remote Class:\t\t", wrapper.getInterfaceName()); + Logger.printlnMixedBlue("Endpoint:\t\t", wrapper.getTarget()); + Logger.printlnMixedBlue("ObjID:\t\t\t", wrapper.objID.toString()); + Logger.printlnMixedBlue("ClientSocketFactory:\t", csf); + Logger.printlnMixedBlue("ServerSocketFactory:\t", ssf); + } + + else if (objectWrapper instanceof ActivatableWrapper) + { + ActivatableWrapper wrapper = (ActivatableWrapper)objectWrapper; + + Logger.printlnYellow("Printing activatable RemoteObject:"); + Logger.increaseIndent(); + Logger.printlnMixedBlue("Remote Class:\t\t", wrapper.getInterfaceName()); + Logger.printlnMixedBlue("Activator:\t\t", wrapper.getActivatorEndpoint()); + Logger.printlnMixedBlue("ActivationID:\t\t", wrapper.activationUID.toString()); + } + + else + { + Logger.eprintlnYellow("Unsupported object type."); + } + } + + catch (Exception e) + { + ExceptionHandler.unexpectedException(e, "constructing", "RemoteObjectWrapper", true); + } + + finally + { + Logger.decreaseIndent(); + } + } + + /** + * For File objects, print their absolute path. + * + * @param o File object + */ + public void handleFile(File o) + { + Logger.println(o.getAbsolutePath()); + } + + /** + * Byte objects are converted to hex and printed. As a single byte is most likely part of a + * sequence, we print without a newline. + * + * @param o File object + */ + public void handleByte(byte o) + { + Logger.printPlain(String.format("%02x", o)); + } + + /** + * The default action for each object is to print it using it's toString method. + * + * @param o Object that did not matched one of the previously mentioned types. + */ + public void handleDefault(Object o) + { + Logger.println(o.toString()); + } +} diff --git a/src/de/qtc/rmg/plugin/PluginSystem.java b/src/de/qtc/rmg/plugin/PluginSystem.java index f66e340..0639f89 100644 --- a/src/de/qtc/rmg/plugin/PluginSystem.java +++ b/src/de/qtc/rmg/plugin/PluginSystem.java @@ -11,6 +11,7 @@ import de.qtc.rmg.exceptions.MalformedPluginException; import de.qtc.rmg.internal.ExceptionHandler; +import de.qtc.rmg.internal.RMGOption; import de.qtc.rmg.io.Logger; import de.qtc.rmg.operations.Operation; import de.qtc.rmg.utils.RMGUtils; @@ -49,8 +50,15 @@ public static void init(String pluginPath) argumentProvider = provider; socketFactoryProvider = provider; - if(pluginPath != null) + if (RMGOption.GENERIC_PRINT.getBool()) + { + responseHandler = new GenericPrint(); + } + + if (pluginPath != null) + { loadPlugin(pluginPath); + } } /** @@ -73,55 +81,73 @@ private static void loadPlugin(String pluginPath) JarInputStream jarStream = null; File pluginFile = new File(pluginPath); - if(!pluginFile.exists()) { + if (!pluginFile.exists()) + { Logger.eprintlnMixedYellow("Specified plugin path", pluginPath, "does not exist."); RMGUtils.exit(); } - try { + try + { jarStream = new JarInputStream(new FileInputStream(pluginFile)); Manifest mf = jarStream.getManifest(); pluginClassName = mf.getMainAttributes().getValue(manifestAttribute); jarStream.close(); - if(pluginClassName == null) + if (pluginClassName == null) + { throw new MalformedPluginException(); - - } catch(Exception e) { + } + } + + catch (Exception e) + { Logger.eprintlnMixedYellow("Caught", e.getClass().getName(), "while reading the Manifest of the specified plugin."); Logger.eprintlnMixedBlue("Plugins need to be valid JAR files that contain the", manifestAttribute, "attribute."); RMGUtils.exit(); } - try { + try + { URLClassLoader ucl = new URLClassLoader(new URL[] {pluginFile.toURI().toURL()}); Class pluginClass = Class.forName(pluginClassName, true, ucl); pluginInstance = pluginClass.newInstance(); - } catch(Exception e) { + } + + catch (Exception e) + { Logger.eprintMixedYellow("Caught", e.getClass().getName(), "while reading plugin file "); Logger.printlnPlainBlue(pluginPath); ExceptionHandler.showStackTrace(e); RMGUtils.exit(); } - if(pluginInstance instanceof IPayloadProvider) { + if (pluginInstance instanceof IPayloadProvider) + { payloadProvider = (IPayloadProvider)pluginInstance; inUse = true; - - } if(pluginInstance instanceof IResponseHandler) { + } + + if (pluginInstance instanceof IResponseHandler) + { responseHandler = (IResponseHandler)pluginInstance; inUse = true; - - } if(pluginInstance instanceof IArgumentProvider) { + } + + if(pluginInstance instanceof IArgumentProvider) + { argumentProvider = (IArgumentProvider)pluginInstance; inUse = true; - - } if(pluginInstance instanceof ISocketFactoryProvider) { + } + + if(pluginInstance instanceof ISocketFactoryProvider) + { socketFactoryProvider = (ISocketFactoryProvider)pluginInstance; inUse = true; } - if(!inUse) { + if (!inUse) + { Logger.eprintMixedBlue("Plugin", pluginPath, "was successfully loaded, but is "); Logger.eprintlnPlainYellow("not in use."); Logger.eprintlnMixedYellow("Plugins should implement at least one of the", "IPayloadProvider, IResponseHandler, IArgumentProvider or ISocketFactoryProvider", "interfaces."); From c93d6b85908f0bf0fcf3a7fc4f63b564b2a46e0b Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sat, 9 Dec 2023 12:42:22 +0100 Subject: [PATCH 27/60] Switch namespace Switch namespace from de.qtc to eu.tneitzel. The initial namespace was chosen without further thinking about it. From version v5.0.0 it is planned to expose remote-method-guesser also via maven repositories. Therefore, we switch now to a namespace that is actually owned by the author. --- README.md | 28 ++++++------ docker/example-server/README.md | 40 ++++++++--------- .../example-server/docker-compose-jdk11.yml | 4 +- docker/example-server/docker-compose-jdk8.yml | 4 +- docker/example-server/docker-compose-jdk9.yml | 4 +- .../example-server/resources/server/pom.xml | 4 +- .../src/de/qtc/rmg/server/ExampleServer.java | 26 +++++------ .../server/activation/ActivationServer.java | 10 ++--- .../server/activation/ActivationService.java | 6 +-- .../server/activation/ActivationService2.java | 4 +- .../server/activation/IActivationService.java | 2 +- .../activation/IActivationService2.java | 2 +- .../server/factory/CustomSocketFactory.java | 2 +- .../factory/CustomSocketFactoryServer.java | 10 ++--- .../rmg/server/interfaces/IPlainServer.java | 2 +- .../rmg/server/interfaces/ISecureServer.java | 2 +- .../qtc/rmg/server/interfaces/ISslServer.java | 2 +- .../qtc/rmg/server/legacy/LegacyServer.java | 10 ++--- .../qtc/rmg/server/legacy/LegacyService.java | 2 +- .../rmg/server/legacy/LegacyServiceImpl.java | 4 +- .../rmg/server/legacy/StringContainer.java | 2 +- .../rmg/server/operations/PlainServer.java | 8 ++-- .../rmg/server/operations/SecureServer.java | 6 +-- .../qtc/rmg/server/operations/SslServer.java | 8 ++-- .../qtc/rmg/server/utils/CodebaseLogger.java | 2 +- .../src/de/qtc/rmg/server/utils/Logger.java | 2 +- .../src/de/qtc/rmg/server/utils/Utils.java | 2 +- .../spring-remoting/resources/server/pom.xml | 4 +- .../rmg/springremoting/ServerOperations.java | 2 +- .../springremoting/SpringRemotingService.java | 2 +- .../de/qtc/rmg/springremoting/Starter.java | 2 +- docker/ssrf-server/README.md | 4 +- docker/ssrf-server/resources/server/pom.xml | 4 +- .../src/de/qtc/rmg/server/ssrf/Starter.java | 14 +++--- .../qtc/rmg/server/ssrf/http/JarHandler.java | 4 +- .../qtc/rmg/server/ssrf/http/SSRFHandler.java | 4 +- .../qtc/rmg/server/ssrf/http/SSRFServer.java | 4 +- .../qtc/rmg/server/ssrf/rmi/FileManager.java | 2 +- .../qtc/rmg/server/ssrf/rmi/IFileManager.java | 2 +- .../ssrf/rmi/LocalhostJmxConnector.java | 2 +- .../ssrf/rmi/LocalhostSocketFactory.java | 2 +- .../de/qtc/rmg/server/ssrf/utils/Logger.java | 2 +- docs/rmg/actions.md | 16 +++---- docs/rmg/inline-gadgets.md | 2 +- docs/rmg/method-guessing.md | 2 +- docs/rmg/plugin-system.md | 34 +++++++------- docs/rmi/unicast-remote-object.md | 4 +- plugins/GenericPrint.java | 12 ++--- pom.xml | 4 +- src/de/qtc/rmg/Starter.java | 10 ++--- src/de/qtc/rmg/endpoints/KnownEndpoint.java | 4 +- .../rmg/endpoints/KnownEndpointHolder.java | 2 +- src/de/qtc/rmg/endpoints/Vulnerability.java | 2 +- .../exceptions/MalformedPluginException.java | 2 +- src/de/qtc/rmg/exceptions/SSRFException.java | 2 +- .../UnexpectedCharacterException.java | 2 +- src/de/qtc/rmg/internal/ArgumentHandler.java | 14 +++--- .../qtc/rmg/internal/CodebaseCollector.java | 4 +- src/de/qtc/rmg/internal/ExceptionHandler.java | 6 +-- src/de/qtc/rmg/internal/MethodArguments.java | 2 +- src/de/qtc/rmg/internal/MethodCandidate.java | 8 ++-- src/de/qtc/rmg/internal/Pair.java | 2 +- src/de/qtc/rmg/internal/RMGOption.java | 8 ++-- src/de/qtc/rmg/internal/RMGOptionGroup.java | 4 +- src/de/qtc/rmg/internal/RMIComponent.java | 2 +- src/de/qtc/rmg/io/DevNullOutputStream.java | 2 +- src/de/qtc/rmg/io/Formatter.java | 20 ++++----- src/de/qtc/rmg/io/Logger.java | 4 +- src/de/qtc/rmg/io/MaliciousOutputStream.java | 10 ++--- src/de/qtc/rmg/io/RawObjectInputStream.java | 4 +- src/de/qtc/rmg/io/RawObjectOutputStream.java | 4 +- src/de/qtc/rmg/io/SampleWriter.java | 12 ++--- src/de/qtc/rmg/io/SingleOpOutputStream.java | 4 +- src/de/qtc/rmg/io/WordlistHandler.java | 4 +- .../qtc/rmg/networking/DGCClientSocket.java | 4 +- .../networking/DGCClientSocketFactory.java | 2 +- .../networking/DGCClientSslSocketFactory.java | 2 +- .../rmg/networking/DummySocketFactory.java | 4 +- .../qtc/rmg/networking/DummyTrustManager.java | 2 +- .../rmg/networking/LimitedSocketFactory.java | 6 +-- .../rmg/networking/LoopbackSocketFactory.java | 8 ++-- .../networking/LoopbackSslSocketFactory.java | 8 ++-- src/de/qtc/rmg/networking/RMIEndpoint.java | 18 ++++---- .../rmg/networking/RMIRegistryEndpoint.java | 18 ++++---- .../rmg/networking/SSRFResponseSocket.java | 4 +- .../networking/SSRFResponseSocketFactory.java | 2 +- src/de/qtc/rmg/networking/SSRFSocket.java | 14 +++--- .../qtc/rmg/networking/SSRFSocketFactory.java | 2 +- .../rmg/networking/TimeoutSocketFactory.java | 2 +- .../rmg/networking/TrustAllSocketFactory.java | 8 ++-- .../qtc/rmg/operations/ActivationClient.java | 14 +++--- src/de/qtc/rmg/operations/DGCClient.java | 18 ++++---- src/de/qtc/rmg/operations/Dispatcher.java | 44 +++++++++---------- src/de/qtc/rmg/operations/MethodGuesser.java | 22 +++++----- src/de/qtc/rmg/operations/Operation.java | 6 +-- src/de/qtc/rmg/operations/PortScanner.java | 18 ++++---- src/de/qtc/rmg/operations/RegistryClient.java | 20 ++++----- .../rmg/operations/RemoteObjectClient.java | 26 +++++------ src/de/qtc/rmg/operations/ScanAction.java | 6 +-- src/de/qtc/rmg/plugin/DefaultProvider.java | 32 +++++++------- src/de/qtc/rmg/plugin/GenericPrint.java | 14 +++--- src/de/qtc/rmg/plugin/IArgumentProvider.java | 2 +- src/de/qtc/rmg/plugin/IPayloadProvider.java | 4 +- src/de/qtc/rmg/plugin/IResponseHandler.java | 2 +- .../rmg/plugin/ISocketFactoryProvider.java | 2 +- src/de/qtc/rmg/plugin/PluginSystem.java | 14 +++--- .../qtc/rmg/plugin/ReturnValueProvider.java | 2 +- src/de/qtc/rmg/utils/ActivatableWrapper.java | 14 +++--- .../rmg/utils/DefinitelyNonExistingClass.java | 2 +- src/de/qtc/rmg/utils/EmptyWrapper.java | 2 +- src/de/qtc/rmg/utils/ProgressBar.java | 6 +-- src/de/qtc/rmg/utils/RMGUtils.java | 24 +++++----- .../qtc/rmg/utils/RemoteInvocationHolder.java | 4 +- src/de/qtc/rmg/utils/RemoteObjectWrapper.java | 8 ++-- src/de/qtc/rmg/utils/RogueJMX.java | 10 ++--- src/de/qtc/rmg/utils/Security.java | 6 +-- .../qtc/rmg/utils/SpringRemotingWrapper.java | 16 +++---- src/de/qtc/rmg/utils/UnicastWrapper.java | 4 +- src/de/qtc/rmg/utils/YsoIntegration.java | 10 ++--- tests/generic/tests/ssrf-response.yml | 4 +- tests/jdk11/tests/enum.yml | 30 ++++++------- tests/jdk8/tests/enum.yml | 30 ++++++------- tests/jdk9/tests/enum.yml | 30 ++++++------- tests/utils/PluginTest.java | 10 ++--- 124 files changed, 512 insertions(+), 512 deletions(-) diff --git a/README.md b/README.md index e49a6a1..487d357 100644 --- a/README.md +++ b/README.md @@ -140,13 +140,13 @@ bind operations. When using the ``bind`` or ``rebind`` action *remote-method-gue [+] RMI registry bound names: [+] [+] - plain-server2 -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff7, 9040809218460289711] [+] - legacy-service -[+] --> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) +[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) [+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ffc, 4854919471498518309] [+] - plain-server -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff8, 6721714394791464813] [qtc@devbox ~]$ rmg bind 172.17.0.2 9010 127.0.0.1:4444 my-object --localhost-bypass @@ -159,16 +159,16 @@ bind operations. When using the ``bind`` or ``rebind`` action *remote-method-gue [+] RMI registry bound names: [+] [+] - plain-server2 -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff7, 9040809218460289711] [+] - my-object [+] --> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server) [+] Endpoint: 127.0.0.1:4444 ObjID: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722] [+] - legacy-service -[+] --> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) +[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) [+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ffc, 4854919471498518309] [+] - plain-server -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff8, 6721714394791464813] ``` @@ -302,20 +302,20 @@ page](./docs/rmg/actions.md#enum). [+] RMI registry bound names: [+] [+] - plain-server2 -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ff7, -3079588349672331489] [+] - legacy-service -[+] --> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) +[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) [+] Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ffc, -2969569395601583761] [+] - plain-server -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ff8, 1319708214331962145] [+] [+] RMI server codebase enumeration: [+] [+] - http://iinsecure.example/well-hidden-development-folder/ -[+] --> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub -[+] --> de.qtc.rmg.server.interfaces.IPlainServer +[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer [+] [+] RMI server String unmarshalling enumeration: [+] @@ -500,13 +500,13 @@ for each *bound name* and *remote-method-guesser* displays them during the ``enu [+] RMI registry bound names: [+] [+] - plain-server2 -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646] [+] - legacy-service -[+] --> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) +[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) [+] Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ffc, 625759208507801754] [+] - plain-server -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ff8, -6355415622579283910] ``` diff --git a/docker/example-server/README.md b/docker/example-server/README.md index 994b4b1..0ee750b 100644 --- a/docker/example-server/README.md +++ b/docker/example-server/README.md @@ -34,21 +34,21 @@ The registry on port `1090` is *SSL* protected and contains three available boun [+] RMI registry bound names: [+] [+] - plain-server -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:40579 TLS: no ObjID: [-492549a8:1809adab6bf:-7fff, 8831379559932805383] [+] - ssl-server -[+] --> de.qtc.rmg.server.interfaces.ISslServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.ISslServer (unknown class) [+] Endpoint: iinsecure.example:42031 TLS: yes ObjID: [-492549a8:1809adab6bf:-7ffe, -8819602238278920745] [+] - secure-server -[+] --> de.qtc.rmg.server.interfaces.ISecureServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.ISecureServer (unknown class) [+] Endpoint: iinsecure.example:40579 TLS: no ObjID: [-492549a8:1809adab6bf:-7ffd, -5037949272481440924] [+] [+] RMI server codebase enumeration: [+] [+] - http://iinsecure.example/well-hidden-development-folder/ -[+] --> de.qtc.rmg.server.interfaces.ISslServer -[+] --> de.qtc.rmg.server.interfaces.IPlainServer -[+] --> de.qtc.rmg.server.interfaces.ISecureServer +[+] --> eu.tneitzel.rmg.server.interfaces.ISslServer +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer +[+] --> eu.tneitzel.rmg.server.interfaces.ISecureServer [+] [+] RMI server String unmarshalling enumeration: [+] @@ -96,13 +96,13 @@ The registry on port `1098` hosts an *Activation System* and has some *activatab [+] RMI registry bound names: [+] [+] - activation-test -[+] --> de.qtc.rmg.server.activation.IActivationService (unknown class) +[+] --> eu.tneitzel.rmg.server.activation.IActivationService (unknown class) [+] Activator: iinsecure.example:1098 ActivationID: -492549a8:1809adab6bf:-7ff1 [+] - activation-test2 -[+] --> de.qtc.rmg.server.activation.IActivationService2 (unknown class) +[+] --> eu.tneitzel.rmg.server.activation.IActivationService2 (unknown class) [+] Activator: iinsecure.example:1098 ActivationID: -492549a8:1809adab6bf:-7fee [+] - plain-server -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:40579 TLS: no ObjID: [-492549a8:1809adab6bf:-7fec, 5541025679742310482] [+] - java.rmi.activation.ActivationSystem [+] --> sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activator) @@ -111,10 +111,10 @@ The registry on port `1098` hosts an *Activation System* and has some *activatab [+] RMI server codebase enumeration: [+] [+] - http://iinsecure.example/well-hidden-development-folder/ -[+] --> de.qtc.rmg.server.interfaces.IPlainServer -[+] --> de.qtc.rmg.server.activation.IActivationService +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer +[+] --> eu.tneitzel.rmg.server.activation.IActivationService [+] --> sun.rmi.server.Activation$ActivationSystemImpl_Stub -[+] --> de.qtc.rmg.server.activation.IActivationService2 +[+] --> eu.tneitzel.rmg.server.activation.IActivationService2 [+] [+] RMI server String unmarshalling enumeration: [+] @@ -167,20 +167,20 @@ registry port binds an *RMI Activator instance*, but not a full working *Activat [+] RMI registry bound names: [+] [+] - plain-server2 -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:40579 TLS: no ObjID: [-492549a8:1809adab6bf:-7ff7, 8893583921173173865] [+] - legacy-service -[+] --> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) +[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class) [+] Endpoint: iinsecure.example:40579 TLS: no ObjID: [-492549a8:1809adab6bf:-7ffc, -5452660335673756521] [+] - plain-server -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:40579 TLS: no ObjID: [-492549a8:1809adab6bf:-7ff8, 5860842907020657289] [+] [+] RMI server codebase enumeration: [+] [+] - http://iinsecure.example/well-hidden-development-folder/ -[+] --> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub -[+] --> de.qtc.rmg.server.interfaces.IPlainServer +[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer [+] [+] RMI server String unmarshalling enumeration: [+] @@ -230,8 +230,8 @@ to enable *codebase logging*: ```yaml environment: [...] - -Djava.rmi.server.RMIClassLoaderSpi=de.qtc.rmg.server.utils.CodebaseLogger - -Dde.qtc.rmg.server.disableColor=true + -Djava.rmi.server.RMIClassLoaderSpi=eu.tneitzel.rmg.server.utils.CodebaseLogger + -Deu.tneitzel.rmg.server.disableColor=true ``` Each successful method call is logged on the server side. The following listing shows the output after the server @@ -265,7 +265,7 @@ Picked up _JAVA_OPTIONS: -Djava.rmi.server.hostname=iinsecure.example -Djava [2022.05.06 - 19:45:12] [2022.05.06 - 19:45:12] Creating LegacyServiceImpl object. [2022.05.06 - 19:45:12] Binding LegacyServiceImpl as legacy-service -[2022.05.06 - 19:45:12] Boundname legacy-service with class de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub is ready. +[2022.05.06 - 19:45:12] Boundname legacy-service with class eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub is ready. [2022.05.06 - 19:45:12] Creating PlainServer object. [2022.05.06 - 19:45:12] Binding Object as plain-server [2022.05.06 - 19:45:12] Boundname plain-server with interface IPlainServer is ready. diff --git a/docker/example-server/docker-compose-jdk11.yml b/docker/example-server/docker-compose-jdk11.yml index 95241cf..60d7595 100644 --- a/docker/example-server/docker-compose-jdk11.yml +++ b/docker/example-server/docker-compose-jdk11.yml @@ -16,8 +16,8 @@ services: -Djava.rmi.server.codebase=http://iinsecure.example/well-hidden-development-folder/ - > DELETE_THIS_AND_THE_ABOVE_LINE_TO_ENABLE_CODEBASE_LOGGING_OR_TO_DISABLE_COLOR= - -Djava.rmi.server.RMIClassLoaderSpi=de.qtc.rmg.server.utils.CodebaseLogger - -Dde.qtc.rmg.server.disableColor=true + -Djava.rmi.server.RMIClassLoaderSpi=eu.tneitzel.rmg.server.utils.CodebaseLogger + -Deu.tneitzel.rmg.server.disableColor=true volumes: - ./resources/trust/store.p12:/opt/store.p12 - ./resources/conf/policy:/opt/policy diff --git a/docker/example-server/docker-compose-jdk8.yml b/docker/example-server/docker-compose-jdk8.yml index 13af7af..72ce467 100644 --- a/docker/example-server/docker-compose-jdk8.yml +++ b/docker/example-server/docker-compose-jdk8.yml @@ -16,8 +16,8 @@ services: -Djava.rmi.server.codebase=http://iinsecure.example/well-hidden-development-folder/ - > DELETE_THIS_AND_THE_ABOVE_LINE_TO_ENABLE_CODEBASE_LOGGING_OR_TO_DISABLE_COLOR= - -Djava.rmi.server.RMIClassLoaderSpi=de.qtc.rmg.server.utils.CodebaseLogger - -Dde.qtc.rmg.server.disableColor=true + -Djava.rmi.server.RMIClassLoaderSpi=eu.tneitzel.rmg.server.utils.CodebaseLogger + -Deu.tneitzel.rmg.server.disableColor=true volumes: - ./resources/trust/store.p12:/opt/store.p12 - ./resources/conf/policy:/opt/policy diff --git a/docker/example-server/docker-compose-jdk9.yml b/docker/example-server/docker-compose-jdk9.yml index f979b62..b0072e6 100644 --- a/docker/example-server/docker-compose-jdk9.yml +++ b/docker/example-server/docker-compose-jdk9.yml @@ -16,8 +16,8 @@ services: -Djava.rmi.server.codebase=http://iinsecure.example/well-hidden-development-folder/ - > DELETE_THIS_AND_THE_ABOVE_LINE_TO_ENABLE_CODEBASE_LOGGING_OR_TO_DISABLE_COLOR= - -Djava.rmi.server.RMIClassLoaderSpi=de.qtc.rmg.server.utils.CodebaseLogger - -Dde.qtc.rmg.server.disableColor=true + -Djava.rmi.server.RMIClassLoaderSpi=eu.tneitzel.rmg.server.utils.CodebaseLogger + -Deu.tneitzel.rmg.server.disableColor=true volumes: - ./resources/trust/store.p12:/opt/store.p12 - ./resources/conf/policy:/opt/policy diff --git a/docker/example-server/resources/server/pom.xml b/docker/example-server/resources/server/pom.xml index 3e4a730..848cb7f 100644 --- a/docker/example-server/resources/server/pom.xml +++ b/docker/example-server/resources/server/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - de.qtc.rmg.server.ExampleServer + eu.tneitzel.rmg.server.ExampleServer rmg-example-server 4.1.0 rmg-example-server @@ -47,7 +47,7 @@ rmg-example-server-${project.version} - de.qtc.rmg.server.ExampleServer + eu.tneitzel.rmg.server.ExampleServer diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java index 261ebd9..cc6ba7e 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server; +package eu.tneitzel.rmg.server; import java.rmi.AlreadyBoundException; import java.rmi.NotBoundException; @@ -11,17 +11,17 @@ import javax.rmi.ssl.SslRMIClientSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; -import de.qtc.rmg.server.activation.ActivationServer; -import de.qtc.rmg.server.factory.CustomSocketFactoryServer; -import de.qtc.rmg.server.interfaces.IPlainServer; -import de.qtc.rmg.server.interfaces.ISecureServer; -import de.qtc.rmg.server.interfaces.ISslServer; -import de.qtc.rmg.server.legacy.LegacyServer; -import de.qtc.rmg.server.operations.PlainServer; -import de.qtc.rmg.server.operations.SecureServer; -import de.qtc.rmg.server.operations.SslServer; -import de.qtc.rmg.server.utils.Logger; -import de.qtc.rmg.server.utils.Utils; +import eu.tneitzel.rmg.server.activation.ActivationServer; +import eu.tneitzel.rmg.server.factory.CustomSocketFactoryServer; +import eu.tneitzel.rmg.server.interfaces.IPlainServer; +import eu.tneitzel.rmg.server.interfaces.ISecureServer; +import eu.tneitzel.rmg.server.interfaces.ISslServer; +import eu.tneitzel.rmg.server.legacy.LegacyServer; +import eu.tneitzel.rmg.server.operations.PlainServer; +import eu.tneitzel.rmg.server.operations.SecureServer; +import eu.tneitzel.rmg.server.operations.SslServer; +import eu.tneitzel.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.utils.Utils; public class ExampleServer { @@ -39,7 +39,7 @@ public class ExampleServer public static void main(String[] argv) { - String disableColor = System.getProperty("de.qtc.rmg.server.disableColor"); + String disableColor = System.getProperty("eu.tneitzel.rmg.server.disableColor"); if (disableColor != null && disableColor.equalsIgnoreCase("true")) { diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java index 02c777d..5b7fa3c 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.activation; +package eu.tneitzel.rmg.server.activation; import java.rmi.AccessException; import java.rmi.AlreadyBoundException; @@ -15,10 +15,10 @@ import java.rmi.server.UnicastRemoteObject; import java.util.Properties; -import de.qtc.rmg.server.interfaces.IPlainServer; -import de.qtc.rmg.server.operations.PlainServer; -import de.qtc.rmg.server.utils.Logger; -import de.qtc.rmg.server.utils.Utils; +import eu.tneitzel.rmg.server.interfaces.IPlainServer; +import eu.tneitzel.rmg.server.operations.PlainServer; +import eu.tneitzel.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.utils.Utils; /** * Create an ActivationServer. This class does basically the same as rmid, but skips some configuration diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java index 011c182..4006525 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.activation; +package eu.tneitzel.rmg.server.activation; import java.io.IOException; import java.rmi.MarshalledObject; @@ -6,8 +6,8 @@ import java.rmi.activation.Activatable; import java.rmi.activation.ActivationID; -import de.qtc.rmg.server.utils.Logger; -import de.qtc.rmg.server.utils.Utils; +import eu.tneitzel.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.utils.Utils; public class ActivationService extends Activatable implements IActivationService { diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java index f2c5673..64ae13e 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.activation; +package eu.tneitzel.rmg.server.activation; import java.rmi.MarshalledObject; import java.rmi.RemoteException; @@ -10,7 +10,7 @@ import javax.rmi.ssl.SslRMIClientSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; -import de.qtc.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.utils.Logger; public class ActivationService2 extends Activatable implements IActivationService2 { diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java index 40ed5cf..338782d 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.activation; +package eu.tneitzel.rmg.server.activation; import java.rmi.Remote; import java.rmi.RemoteException; diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java index 1bf8094..84d55dd 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.activation; +package eu.tneitzel.rmg.server.activation; import java.rmi.Remote; import java.rmi.RemoteException; diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java index 202ced7..2c80b57 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.factory; +package eu.tneitzel.rmg.server.factory; import java.io.IOException; import java.io.Serializable; diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java index dffae55..8960652 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.factory; +package eu.tneitzel.rmg.server.factory; import java.rmi.AlreadyBoundException; import java.rmi.NotBoundException; @@ -9,10 +9,10 @@ import java.rmi.server.RMISocketFactory; import java.rmi.server.UnicastRemoteObject; -import de.qtc.rmg.server.interfaces.IPlainServer; -import de.qtc.rmg.server.operations.PlainServer; -import de.qtc.rmg.server.utils.Logger; -import de.qtc.rmg.server.utils.Utils; +import eu.tneitzel.rmg.server.interfaces.IPlainServer; +import eu.tneitzel.rmg.server.operations.PlainServer; +import eu.tneitzel.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.utils.Utils; public class CustomSocketFactoryServer { diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/IPlainServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/IPlainServer.java index d6a0e69..504e1e7 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/IPlainServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/IPlainServer.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.interfaces; +package eu.tneitzel.rmg.server.interfaces; import java.rmi.Remote; import java.rmi.RemoteException; diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISecureServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISecureServer.java index 34fb9b2..b2b2e41 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISecureServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISecureServer.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.interfaces; +package eu.tneitzel.rmg.server.interfaces; import java.rmi.Remote; import java.rmi.RemoteException; diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISslServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISslServer.java index c4aefdf..887b5d7 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISslServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISslServer.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.interfaces; +package eu.tneitzel.rmg.server.interfaces; import java.rmi.Remote; import java.rmi.RemoteException; diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java index 2af8e65..ed5b363 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.legacy; +package eu.tneitzel.rmg.server.legacy; import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; @@ -10,10 +10,10 @@ import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; -import de.qtc.rmg.server.interfaces.IPlainServer; -import de.qtc.rmg.server.operations.PlainServer; -import de.qtc.rmg.server.utils.Logger; -import de.qtc.rmg.server.utils.Utils; +import eu.tneitzel.rmg.server.interfaces.IPlainServer; +import eu.tneitzel.rmg.server.operations.PlainServer; +import eu.tneitzel.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.utils.Utils; @SuppressWarnings("unused") public class LegacyServer diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyService.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyService.java index eb3698e..b0cf542 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyService.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyService.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.legacy; +package eu.tneitzel.rmg.server.legacy; import java.rmi.Remote; import java.rmi.RemoteException; diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServiceImpl.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServiceImpl.java index dd2011c..8fdea7b 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServiceImpl.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServiceImpl.java @@ -1,10 +1,10 @@ -package de.qtc.rmg.server.legacy; +package eu.tneitzel.rmg.server.legacy; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.HashMap; -import de.qtc.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.utils.Logger; @SuppressWarnings("serial") public class LegacyServiceImpl extends UnicastRemoteObject implements LegacyService diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/StringContainer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/StringContainer.java index 1bfc48a..f4a6974 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/StringContainer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/StringContainer.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.legacy; +package eu.tneitzel.rmg.server.legacy; public class StringContainer { } diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/PlainServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/PlainServer.java index ac24dba..5b4df8c 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/PlainServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/PlainServer.java @@ -1,10 +1,10 @@ -package de.qtc.rmg.server.operations; +package eu.tneitzel.rmg.server.operations; import java.io.IOException; -import de.qtc.rmg.server.interfaces.IPlainServer; -import de.qtc.rmg.server.utils.Logger; -import de.qtc.rmg.server.utils.Utils; +import eu.tneitzel.rmg.server.interfaces.IPlainServer; +import eu.tneitzel.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.utils.Utils; public class PlainServer implements IPlainServer { diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SecureServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SecureServer.java index e6990bf..4a700ed 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SecureServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SecureServer.java @@ -1,11 +1,11 @@ -package de.qtc.rmg.server.operations; +package eu.tneitzel.rmg.server.operations; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.HashMap; -import de.qtc.rmg.server.interfaces.ISecureServer; -import de.qtc.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.interfaces.ISecureServer; +import eu.tneitzel.rmg.server.utils.Logger; public class SecureServer implements ISecureServer { diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SslServer.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SslServer.java index 0ad47ba..aaa96f4 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SslServer.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SslServer.java @@ -1,10 +1,10 @@ -package de.qtc.rmg.server.operations; +package eu.tneitzel.rmg.server.operations; import java.io.IOException; -import de.qtc.rmg.server.interfaces.ISslServer; -import de.qtc.rmg.server.utils.Logger; -import de.qtc.rmg.server.utils.Utils; +import eu.tneitzel.rmg.server.interfaces.ISslServer; +import eu.tneitzel.rmg.server.utils.Logger; +import eu.tneitzel.rmg.server.utils.Utils; public class SslServer implements ISslServer { diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/CodebaseLogger.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/CodebaseLogger.java index 2fef221..d35104e 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/CodebaseLogger.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/CodebaseLogger.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.utils; +package eu.tneitzel.rmg.server.utils; import java.net.MalformedURLException; import java.rmi.server.RMIClassLoader; diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Logger.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Logger.java index e9747bb..239b3e3 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Logger.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Logger.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.utils; +package eu.tneitzel.rmg.server.utils; import java.text.SimpleDateFormat; import java.util.Date; diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java b/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java index 65463c7..36c3179 100644 --- a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java +++ b/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.utils; +package eu.tneitzel.rmg.server.utils; import java.io.BufferedReader; import java.io.IOException; diff --git a/docker/spring-remoting/resources/server/pom.xml b/docker/spring-remoting/resources/server/pom.xml index b587eff..38ef934 100644 --- a/docker/spring-remoting/resources/server/pom.xml +++ b/docker/spring-remoting/resources/server/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - de.qtc.rmg + eu.tneitzel.rmg spring-remoting 1.0.0 @@ -40,7 +40,7 @@ rmg-spring-remoting-server-${project.version} - de.qtc.rmg.springremoting.Starter + eu.tneitzel.rmg.springremoting.Starter true diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java index 670552d..3fa69bb 100644 --- a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java +++ b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.springremoting; +package eu.tneitzel.rmg.springremoting; public interface ServerOperations { diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java index b7da479..1f40b03 100644 --- a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java +++ b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.springremoting; +package eu.tneitzel.rmg.springremoting; import java.io.BufferedReader; import java.io.IOException; diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java index 0d82a4e..4dcb1ce 100644 --- a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java +++ b/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.springremoting; +package eu.tneitzel.rmg.springremoting; import org.springframework.boot.SpringApplication; diff --git a/docker/ssrf-server/README.md b/docker/ssrf-server/README.md index 307a1c1..5437df1 100644 --- a/docker/ssrf-server/README.md +++ b/docker/ssrf-server/README.md @@ -76,13 +76,13 @@ In this example we use *remote-method-guesser's* enum action to enumerate availa [+] RMI registry bound names: [+] [+] - FileManager -[+] --> de.qtc.rmg.server.ssrf.rmi.IFileManager (unknown class) +[+] --> eu.tneitzel.rmg.server.ssrf.rmi.IFileManager (unknown class) [+] Endpoint: localhost:34289 ObjID: [2fd1b5a8:17d842f762e:-7fff, 8844200108184892689] [+] [+] RMI server codebase enumeration: [+] [+] - http://localhost:8000/rmi-class-definitions.jar -[+] --> de.qtc.rmg.server.ssrf.rmi.IFileManager +[+] --> eu.tneitzel.rmg.server.ssrf.rmi.IFileManager ``` diff --git a/docker/ssrf-server/resources/server/pom.xml b/docker/ssrf-server/resources/server/pom.xml index 710ab08..2f68369 100644 --- a/docker/ssrf-server/resources/server/pom.xml +++ b/docker/ssrf-server/resources/server/pom.xml @@ -3,7 +3,7 @@ 4.0.0 - de.qtc.rmg.server.ssrf + eu.tneitzel.rmg.server.ssrf rmg-ssrf-server 1.3.0 rmg-ssrf-server @@ -50,7 +50,7 @@ rmg-ssrf-server-${project.version} - de.qtc.rmg.server.ssrf.Starter + eu.tneitzel.rmg.server.ssrf.Starter true diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/Starter.java b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/Starter.java index cbed899..3bcf82f 100644 --- a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/Starter.java +++ b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/Starter.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.ssrf; +package eu.tneitzel.rmg.server.ssrf; import java.io.IOException; import java.rmi.AlreadyBoundException; @@ -6,12 +6,12 @@ import java.rmi.registry.Registry; import java.rmi.server.RMISocketFactory; -import de.qtc.rmg.server.ssrf.http.SSRFServer; -import de.qtc.rmg.server.ssrf.rmi.FileManager; -import de.qtc.rmg.server.ssrf.rmi.IFileManager; -import de.qtc.rmg.server.ssrf.rmi.LocalhostJmxConnector; -import de.qtc.rmg.server.ssrf.rmi.LocalhostSocketFactory; -import de.qtc.rmg.server.ssrf.utils.Logger; +import eu.tneitzel.rmg.server.ssrf.http.SSRFServer; +import eu.tneitzel.rmg.server.ssrf.rmi.FileManager; +import eu.tneitzel.rmg.server.ssrf.rmi.IFileManager; +import eu.tneitzel.rmg.server.ssrf.rmi.LocalhostJmxConnector; +import eu.tneitzel.rmg.server.ssrf.rmi.LocalhostSocketFactory; +import eu.tneitzel.rmg.server.ssrf.utils.Logger; /** * The Starter class is responsible for creating an HTTP server that is vulnerable diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/JarHandler.java b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/JarHandler.java index 256e332..72db243 100644 --- a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/JarHandler.java +++ b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/JarHandler.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.ssrf.http; +package eu.tneitzel.rmg.server.ssrf.http; import java.io.File; import java.io.IOException; @@ -8,7 +8,7 @@ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; -import de.qtc.rmg.server.ssrf.utils.Logger; +import eu.tneitzel.rmg.server.ssrf.utils.Logger; /** * The JarHandler handles requests to the codebase endpoint specified within the RMI server. diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFHandler.java b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFHandler.java index 24b7ead..89809c3 100644 --- a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFHandler.java +++ b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFHandler.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.ssrf.http; +package eu.tneitzel.rmg.server.ssrf.http; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -8,7 +8,7 @@ import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; -import de.qtc.rmg.server.ssrf.utils.Logger; +import eu.tneitzel.rmg.server.ssrf.utils.Logger; import org.apache.commons.io.HexDump; import org.apache.commons.io.IOUtils; diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFServer.java b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFServer.java index 64e467d..69398b2 100644 --- a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFServer.java +++ b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFServer.java @@ -1,11 +1,11 @@ -package de.qtc.rmg.server.ssrf.http; +package eu.tneitzel.rmg.server.ssrf.http; import java.io.IOException; import java.net.InetSocketAddress; import com.sun.net.httpserver.HttpServer; -import de.qtc.rmg.server.ssrf.utils.Logger; +import eu.tneitzel.rmg.server.ssrf.utils.Logger; /** * The SSRFServer class creates an HTTP server that is vulnerable to SSRF attacks. diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/FileManager.java b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/FileManager.java index e93fab9..c9547da 100644 --- a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/FileManager.java +++ b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/FileManager.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.ssrf.rmi; +package eu.tneitzel.rmg.server.ssrf.rmi; import java.io.File; import java.io.IOException; diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/IFileManager.java b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/IFileManager.java index 4dbf0ed..02debfc 100644 --- a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/IFileManager.java +++ b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/IFileManager.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.ssrf.rmi; +package eu.tneitzel.rmg.server.ssrf.rmi; import java.io.File; import java.io.IOException; diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostJmxConnector.java b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostJmxConnector.java index 769cfe1..9bf1263 100644 --- a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostJmxConnector.java +++ b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostJmxConnector.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.ssrf.rmi; +package eu.tneitzel.rmg.server.ssrf.rmi; import java.io.IOException; import java.lang.management.ManagementFactory; diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostSocketFactory.java b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostSocketFactory.java index 81cd2a5..753cc91 100644 --- a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostSocketFactory.java +++ b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.ssrf.rmi; +package eu.tneitzel.rmg.server.ssrf.rmi; import java.io.IOException; import java.net.InetSocketAddress; diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/utils/Logger.java b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/utils/Logger.java index 80ce9c9..56ea126 100644 --- a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/utils/Logger.java +++ b/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/utils/Logger.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.server.ssrf.utils; +package eu.tneitzel.rmg.server.ssrf.utils; import java.text.SimpleDateFormat; import java.util.Date; diff --git a/docs/rmg/actions.md b/docs/rmg/actions.md index 49160a3..a8a1135 100644 --- a/docs/rmg/actions.md +++ b/docs/rmg/actions.md @@ -295,13 +295,13 @@ following listing shows an example for this situation: [+] RMI registry bound names: [+] [+] - activation-test -[+] --> de.qtc.rmg.server.activation.IActivationService (unknown class) +[+] --> eu.tneitzel.rmg.server.activation.IActivationService (unknown class) [+] Activator: iinsecure.example:1098 ActivationID: 6fd4e3c:180ac45a068:-7ff1 [+] - activation-test2 -[+] --> de.qtc.rmg.server.activation.IActivationService2 (unknown class) +[+] --> eu.tneitzel.rmg.server.activation.IActivationService2 (unknown class) [+] Activator: iinsecure.example:1098 ActivationID: 6fd4e3c:180ac45a068:-7fee [+] - plain-server -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:41867 TLS: no ObjID: [6fd4e3c:180ac45a068:-7fec, 969949632761859811] [+] - java.rmi.activation.ActivationSystem [+] --> sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System) @@ -327,15 +327,15 @@ the obtained `UnicastRef` is then displayed as usual below the activation relate [+] RMI registry bound names: [+] [+] - activation-test -[+] --> de.qtc.rmg.server.activation.IActivationService (unknown class) +[+] --> eu.tneitzel.rmg.server.activation.IActivationService (unknown class) [+] Activator: iinsecure.example:1098 ActivationID: 6fd4e3c:180ac45a068:-7ff1 [+] Endpoint: iinsecure.example:37597 TLS: no ObjID: [1c74dc89:180ac521427:-7ffb, 3078273701606404425] [+] - activation-test2 -[+] --> de.qtc.rmg.server.activation.IActivationService2 (unknown class) +[+] --> eu.tneitzel.rmg.server.activation.IActivationService2 (unknown class) [+] Activator: iinsecure.example:1098 ActivationID: 6fd4e3c:180ac45a068:-7fee [+] Endpoint: iinsecure.example:35721 TLS: yes ObjID: [1c74dc89:180ac521427:-7ff8, 6235870260204364974] [+] - plain-server -[+] --> de.qtc.rmg.server.interfaces.IPlainServer (unknown class) +[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class) [+] Endpoint: iinsecure.example:41867 TLS: no ObjID: [6fd4e3c:180ac45a068:-7fec, 969949632761859811] [+] - java.rmi.activation.ActivationSystem [+] --> sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System) @@ -733,13 +733,13 @@ the ``--bound-name`` during the action, more detailed information can be obtaine [+] RMI registry bound names: [+] [+] - FileManager -[+] --> de.qtc.rmg.server.ssrf.rmi.IFileManager (unknown class) +[+] --> eu.tneitzel.rmg.server.ssrf.rmi.IFileManager (unknown class) [+] Endpoint: localhost:36983 ObjID: [-36af9747:17d8947959b:-7fff, 292657548115654006] [+] [+] RMI server codebase enumeration: [+] [+] - http://localhost:8000/rmi-class-definitions.jar -[+] --> de.qtc.rmg.server.ssrf.rmi.IFileManager +[+] --> eu.tneitzel.rmg.server.ssrf.rmi.IFileManager ``` Apart from ``list`` the following scan actions are available: diff --git a/docs/rmg/inline-gadgets.md b/docs/rmg/inline-gadgets.md index a83f959..d579065 100644 --- a/docs/rmg/inline-gadgets.md +++ b/docs/rmg/inline-gadgets.md @@ -23,7 +23,7 @@ have been resolved and why we did not follow this path. Our first concern was to write the user supplied object to the `ObjectOutputStream` that one can obtain by calling the `getOutputStream` method on a `StreamRemoteCall` -object. Luckily, remote-method-guesser [already implemented](https://github.com/qtc-de/remote-method-guesser/blob/master/src/de/qtc/rmg/networking/RMIEndpoint.java#L157) +object. Luckily, remote-method-guesser [already implemented](https://github.com/qtc-de/remote-method-guesser/blob/master/src/eu.tneitzel.rmg/networking/RMIEndpoint.java#L157) *RMI* calls on such a low level that all this stuff can be accessed quite easily. Writing the user supplied object is however not that straight forward. We do not want to deserialize the object, as this would require all gadget libraries to be diff --git a/docs/rmg/method-guessing.md b/docs/rmg/method-guessing.md index f65e32f..f2778bf 100644 --- a/docs/rmg/method-guessing.md +++ b/docs/rmg/method-guessing.md @@ -379,7 +379,7 @@ although the speedup was just marginal. Summarized: *rmg v3.3.0* implements the hybrid approach. Pure primitive methods are guessed by using the *Ping polyglot* technique, whereas methods with at least one non primitive argument type are guessed by extending the ``TC_BLOCKDATA`` structure over it's expected length. The corresponding -implementation can be found in the [MethodCandidate](https://github.com/qtc-de/remote-method-guesser/blob/develop/src/de/qtc/rmg/internal/MethodCandidate.java) +implementation can be found in the [MethodCandidate](https://github.com/qtc-de/remote-method-guesser/blob/develop/src/eu.tneitzel.rmg/internal/MethodCandidate.java) class within the ``sendArguments`` method. diff --git a/docs/rmg/plugin-system.md b/docs/rmg/plugin-system.md index b173eee..8ec76f1 100644 --- a/docs/rmg/plugin-system.md +++ b/docs/rmg/plugin-system.md @@ -161,25 +161,25 @@ that is applied by RMI when the RMI server location was set to *localhost*. The following listing contains the default implementation that is used by *remote-method-guesser* internally: ```java -package de.qtc.rmg.plugin; +package eu.tneitzel.rmg.plugin; import java.lang.reflect.Method; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMISocketFactory; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.networking.DGCClientSocketFactory; -import de.qtc.rmg.networking.LoopbackSocketFactory; -import de.qtc.rmg.networking.LoopbackSslSocketFactory; -import de.qtc.rmg.networking.SSRFResponseSocketFactory; -import de.qtc.rmg.networking.SSRFSocketFactory; -import de.qtc.rmg.networking.TrustAllSocketFactory; -import de.qtc.rmg.operations.Operation; -import de.qtc.rmg.operations.RegistryClient; -import de.qtc.rmg.utils.RMGUtils; -import de.qtc.rmg.utils.YsoIntegration; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.networking.DGCClientSocketFactory; +import eu.tneitzel.rmg.networking.LoopbackSocketFactory; +import eu.tneitzel.rmg.networking.LoopbackSslSocketFactory; +import eu.tneitzel.rmg.networking.SSRFResponseSocketFactory; +import eu.tneitzel.rmg.networking.SSRFSocketFactory; +import eu.tneitzel.rmg.networking.TrustAllSocketFactory; +import eu.tneitzel.rmg.operations.Operation; +import eu.tneitzel.rmg.operations.RegistryClient; +import eu.tneitzel.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.utils.YsoIntegration; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; @@ -263,7 +263,7 @@ public class DefaultProvider implements IArgumentProvider, IPayloadProvider, ISo ClassPool pool = ClassPool.getDefault(); try { - CtClass evaluator = pool.makeClass("de.qtc.rmg.plugin.DefaultProviderEval"); + CtClass evaluator = pool.makeClass("eu.tneitzel.rmg.plugin.DefaultProviderEval"); String evalFunction = "public static Object[] eval() {" + " return new Object[] { " + argumentString + "};" + "}"; @@ -357,7 +357,7 @@ public class DefaultProvider implements IArgumentProvider, IPayloadProvider, ISo public String getDefaultSSLSocketFactory(String host, int port) { if( RMGOption.SSRFRESPONSE.notNull() ) - return "de.qtc.rmg.networking.DGCClientSslSocketFactory"; + return "eu.tneitzel.rmg.networking.DGCClientSslSocketFactory"; TrustAllSocketFactory trustAllFax = new TrustAllSocketFactory(); @@ -365,7 +365,7 @@ public class DefaultProvider implements IArgumentProvider, IPayloadProvider, ISo LoopbackSslSocketFactory.fac = trustAllFax.getSSLSocketFactory(); LoopbackSslSocketFactory.followRedirect = RMGOption.CONN_FOLLOW.getBool(); - return "de.qtc.rmg.networking.LoopbackSslSocketFactory"; + return "eu.tneitzel.rmg.networking.LoopbackSslSocketFactory"; } } ``` diff --git a/docs/rmi/unicast-remote-object.md b/docs/rmi/unicast-remote-object.md index a5ce777..0acde08 100644 --- a/docs/rmi/unicast-remote-object.md +++ b/docs/rmi/unicast-remote-object.md @@ -307,7 +307,7 @@ to provide a permissive ``SecurityManager`` yourself in advance to prevent this. it is not made part of it's default codebase yet: ```java -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.lang.reflect.Constructor; import java.rmi.Remote; @@ -320,7 +320,7 @@ import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.UnicastRemoteObject; import java.util.Properties; -import de.qtc.rmg.networking.RMIWhisperer; +import eu.tneitzel.rmg.networking.RMIWhisperer; import sun.rmi.server.Activation; import sun.rmi.server.ActivationGroupImpl; diff --git a/plugins/GenericPrint.java b/plugins/GenericPrint.java index 468d614..0670f80 100644 --- a/plugins/GenericPrint.java +++ b/plugins/GenericPrint.java @@ -5,12 +5,12 @@ import java.util.Map; import java.util.Map.Entry; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.plugin.IResponseHandler; -import de.qtc.rmg.utils.ActivatableWrapper; -import de.qtc.rmg.utils.RemoteObjectWrapper; -import de.qtc.rmg.utils.UnicastWrapper; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.plugin.IResponseHandler; +import eu.tneitzel.rmg.utils.ActivatableWrapper; +import eu.tneitzel.rmg.utils.RemoteObjectWrapper; +import eu.tneitzel.rmg.utils.UnicastWrapper; /** * GenericPrint is an rmg ResponseHandler plugin that attempts to print all incoming diff --git a/pom.xml b/pom.xml index c593c46..c3e6412 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 - de.qtc.rmg + eu.tneitzel.rmg remote-method-guesser remote-method-guesser jar @@ -87,7 +87,7 @@ rmg-${project.version} - de.qtc.rmg.Starter + eu.tneitzel.rmg.Starter true diff --git a/src/de/qtc/rmg/Starter.java b/src/de/qtc/rmg/Starter.java index e030896..aedaac5 100644 --- a/src/de/qtc/rmg/Starter.java +++ b/src/de/qtc/rmg/Starter.java @@ -1,9 +1,9 @@ -package de.qtc.rmg; +package eu.tneitzel.rmg; -import de.qtc.rmg.internal.ArgumentHandler; -import de.qtc.rmg.operations.Dispatcher; -import de.qtc.rmg.operations.Operation; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.internal.ArgumentHandler; +import eu.tneitzel.rmg.operations.Dispatcher; +import eu.tneitzel.rmg.operations.Operation; +import eu.tneitzel.rmg.utils.RMGUtils; /** * The Starter class contains the entrypoint of remote-method-guesser. It is responsible diff --git a/src/de/qtc/rmg/endpoints/KnownEndpoint.java b/src/de/qtc/rmg/endpoints/KnownEndpoint.java index ea90264..698bd7b 100644 --- a/src/de/qtc/rmg/endpoints/KnownEndpoint.java +++ b/src/de/qtc/rmg/endpoints/KnownEndpoint.java @@ -1,8 +1,8 @@ -package de.qtc.rmg.endpoints; +package eu.tneitzel.rmg.endpoints; import java.util.List; -import de.qtc.rmg.io.Logger; +import eu.tneitzel.rmg.io.Logger; /** * The KnownEndpoint class represents a well known RMI endpoint. By the term 'well known' we mean diff --git a/src/de/qtc/rmg/endpoints/KnownEndpointHolder.java b/src/de/qtc/rmg/endpoints/KnownEndpointHolder.java index 5f7c8b9..4a61544 100644 --- a/src/de/qtc/rmg/endpoints/KnownEndpointHolder.java +++ b/src/de/qtc/rmg/endpoints/KnownEndpointHolder.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.endpoints; +package eu.tneitzel.rmg.endpoints; import java.io.InputStream; import java.util.List; diff --git a/src/de/qtc/rmg/endpoints/Vulnerability.java b/src/de/qtc/rmg/endpoints/Vulnerability.java index 8a205fc..076f829 100644 --- a/src/de/qtc/rmg/endpoints/Vulnerability.java +++ b/src/de/qtc/rmg/endpoints/Vulnerability.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.endpoints; +package eu.tneitzel.rmg.endpoints; import java.util.List; diff --git a/src/de/qtc/rmg/exceptions/MalformedPluginException.java b/src/de/qtc/rmg/exceptions/MalformedPluginException.java index f9b12ba..28b0371 100644 --- a/src/de/qtc/rmg/exceptions/MalformedPluginException.java +++ b/src/de/qtc/rmg/exceptions/MalformedPluginException.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.exceptions; +package eu.tneitzel.rmg.exceptions; /** * MalformedPluginExceptions are thrown then an rmg plugin was specified on the command diff --git a/src/de/qtc/rmg/exceptions/SSRFException.java b/src/de/qtc/rmg/exceptions/SSRFException.java index 2462de2..30f18f9 100644 --- a/src/de/qtc/rmg/exceptions/SSRFException.java +++ b/src/de/qtc/rmg/exceptions/SSRFException.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.exceptions; +package eu.tneitzel.rmg.exceptions; import java.io.Serializable; diff --git a/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java b/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java index c9a0907..b271fe1 100644 --- a/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java +++ b/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.exceptions; +package eu.tneitzel.rmg.exceptions; /** * UnexpectedCharacterException may be thrown during the dynamic creation diff --git a/src/de/qtc/rmg/internal/ArgumentHandler.java b/src/de/qtc/rmg/internal/ArgumentHandler.java index 15cf98d..aede6a9 100644 --- a/src/de/qtc/rmg/internal/ArgumentHandler.java +++ b/src/de/qtc/rmg/internal/ArgumentHandler.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.internal; +package eu.tneitzel.rmg.internal; import java.io.FileInputStream; import java.io.IOException; @@ -10,12 +10,12 @@ import java.util.Properties; import java.util.Set; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.operations.Operation; -import de.qtc.rmg.operations.PortScanner; -import de.qtc.rmg.operations.ScanAction; -import de.qtc.rmg.plugin.PluginSystem; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.operations.Operation; +import eu.tneitzel.rmg.operations.PortScanner; +import eu.tneitzel.rmg.operations.ScanAction; +import eu.tneitzel.rmg.plugin.PluginSystem; +import eu.tneitzel.rmg.utils.RMGUtils; import net.sourceforge.argparse4j.ArgumentParsers; import net.sourceforge.argparse4j.inf.ArgumentParser; import net.sourceforge.argparse4j.inf.ArgumentParserException; diff --git a/src/de/qtc/rmg/internal/CodebaseCollector.java b/src/de/qtc/rmg/internal/CodebaseCollector.java index c479c70..1015833 100644 --- a/src/de/qtc/rmg/internal/CodebaseCollector.java +++ b/src/de/qtc/rmg/internal/CodebaseCollector.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.internal; +package eu.tneitzel.rmg.internal; import java.net.MalformedURLException; import java.rmi.server.RMIClassLoader; @@ -7,7 +7,7 @@ import java.util.HashSet; import java.util.Set; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.utils.RMGUtils; import javassist.CannotCompileException; import javassist.NotFoundException; diff --git a/src/de/qtc/rmg/internal/ExceptionHandler.java b/src/de/qtc/rmg/internal/ExceptionHandler.java index 6487130..2a611fe 100644 --- a/src/de/qtc/rmg/internal/ExceptionHandler.java +++ b/src/de/qtc/rmg/internal/ExceptionHandler.java @@ -1,9 +1,9 @@ -package de.qtc.rmg.internal; +package eu.tneitzel.rmg.internal; import java.rmi.server.ObjID; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.utils.RMGUtils; /** * During the different RMI operations you have always a roughly same set of exceptions diff --git a/src/de/qtc/rmg/internal/MethodArguments.java b/src/de/qtc/rmg/internal/MethodArguments.java index 40ed33d..772b603 100644 --- a/src/de/qtc/rmg/internal/MethodArguments.java +++ b/src/de/qtc/rmg/internal/MethodArguments.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.internal; +package eu.tneitzel.rmg.internal; import java.util.Iterator; diff --git a/src/de/qtc/rmg/internal/MethodCandidate.java b/src/de/qtc/rmg/internal/MethodCandidate.java index b344374..db4f60a 100644 --- a/src/de/qtc/rmg/internal/MethodCandidate.java +++ b/src/de/qtc/rmg/internal/MethodCandidate.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.internal; +package eu.tneitzel.rmg.internal; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -8,9 +8,9 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.io.RawObjectOutputStream; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.io.RawObjectOutputStream; +import eu.tneitzel.rmg.utils.RMGUtils; import javassist.CannotCompileException; import javassist.CtClass; import javassist.CtMethod; diff --git a/src/de/qtc/rmg/internal/Pair.java b/src/de/qtc/rmg/internal/Pair.java index 31e9a54..232a652 100644 --- a/src/de/qtc/rmg/internal/Pair.java +++ b/src/de/qtc/rmg/internal/Pair.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.internal; +package eu.tneitzel.rmg.internal; /** * For the MethodArguments class, a Pair type is required. Unfortunately, Java 8 does not support such a diff --git a/src/de/qtc/rmg/internal/RMGOption.java b/src/de/qtc/rmg/internal/RMGOption.java index 84a2d4c..9210622 100644 --- a/src/de/qtc/rmg/internal/RMGOption.java +++ b/src/de/qtc/rmg/internal/RMGOption.java @@ -1,11 +1,11 @@ -package de.qtc.rmg.internal; +package eu.tneitzel.rmg.internal; import java.util.EnumSet; import java.util.Properties; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.operations.Operation; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.operations.Operation; +import eu.tneitzel.rmg.utils.RMGUtils; import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.inf.Argument; import net.sourceforge.argparse4j.inf.ArgumentAction; diff --git a/src/de/qtc/rmg/internal/RMGOptionGroup.java b/src/de/qtc/rmg/internal/RMGOptionGroup.java index 0a57964..6d36494 100644 --- a/src/de/qtc/rmg/internal/RMGOptionGroup.java +++ b/src/de/qtc/rmg/internal/RMGOptionGroup.java @@ -1,8 +1,8 @@ -package de.qtc.rmg.internal; +package eu.tneitzel.rmg.internal; import java.util.HashMap; -import de.qtc.rmg.operations.Operation; +import eu.tneitzel.rmg.operations.Operation; import net.sourceforge.argparse4j.inf.ArgumentGroup; import net.sourceforge.argparse4j.inf.ArgumentParser; diff --git a/src/de/qtc/rmg/internal/RMIComponent.java b/src/de/qtc/rmg/internal/RMIComponent.java index 6393dae..36045ea 100644 --- a/src/de/qtc/rmg/internal/RMIComponent.java +++ b/src/de/qtc/rmg/internal/RMIComponent.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.internal; +package eu.tneitzel.rmg.internal; /** * The RMIComponent enum represents the different RMI components that may be targeted diff --git a/src/de/qtc/rmg/io/DevNullOutputStream.java b/src/de/qtc/rmg/io/DevNullOutputStream.java index 3ad664c..35e3cb1 100644 --- a/src/de/qtc/rmg/io/DevNullOutputStream.java +++ b/src/de/qtc/rmg/io/DevNullOutputStream.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.io; +package eu.tneitzel.rmg.io; import java.io.IOException; import java.io.OutputStream; diff --git a/src/de/qtc/rmg/io/Formatter.java b/src/de/qtc/rmg/io/Formatter.java index 1502536..29ea6c4 100644 --- a/src/de/qtc/rmg/io/Formatter.java +++ b/src/de/qtc/rmg/io/Formatter.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.io; +package eu.tneitzel.rmg.io; import java.util.HashMap; import java.util.Iterator; @@ -6,15 +6,15 @@ import java.util.Map.Entry; import java.util.Set; -import de.qtc.rmg.endpoints.KnownEndpoint; -import de.qtc.rmg.endpoints.Vulnerability; -import de.qtc.rmg.internal.CodebaseCollector; -import de.qtc.rmg.internal.MethodCandidate; -import de.qtc.rmg.operations.RemoteObjectClient; -import de.qtc.rmg.utils.ActivatableWrapper; -import de.qtc.rmg.utils.RemoteObjectWrapper; -import de.qtc.rmg.utils.SpringRemotingWrapper; -import de.qtc.rmg.utils.UnicastWrapper; +import eu.tneitzel.rmg.endpoints.KnownEndpoint; +import eu.tneitzel.rmg.endpoints.Vulnerability; +import eu.tneitzel.rmg.internal.CodebaseCollector; +import eu.tneitzel.rmg.internal.MethodCandidate; +import eu.tneitzel.rmg.operations.RemoteObjectClient; +import eu.tneitzel.rmg.utils.ActivatableWrapper; +import eu.tneitzel.rmg.utils.RemoteObjectWrapper; +import eu.tneitzel.rmg.utils.SpringRemotingWrapper; +import eu.tneitzel.rmg.utils.UnicastWrapper; /** * The formatter class is used to print formatted output for the enum and guess operations. diff --git a/src/de/qtc/rmg/io/Logger.java b/src/de/qtc/rmg/io/Logger.java index 958e875..7469b50 100644 --- a/src/de/qtc/rmg/io/Logger.java +++ b/src/de/qtc/rmg/io/Logger.java @@ -1,6 +1,6 @@ -package de.qtc.rmg.io; +package eu.tneitzel.rmg.io; -import de.qtc.rmg.internal.RMGOption; +import eu.tneitzel.rmg.internal.RMGOption; /** * The Logger class exposes static methods that can be used to create colored output. diff --git a/src/de/qtc/rmg/io/MaliciousOutputStream.java b/src/de/qtc/rmg/io/MaliciousOutputStream.java index f679184..b717996 100644 --- a/src/de/qtc/rmg/io/MaliciousOutputStream.java +++ b/src/de/qtc/rmg/io/MaliciousOutputStream.java @@ -1,13 +1,13 @@ -package de.qtc.rmg.io; +package eu.tneitzel.rmg.io; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.lang.reflect.Field; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.utils.DefinitelyNonExistingClass; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.utils.DefinitelyNonExistingClass; +import eu.tneitzel.rmg.utils.RMGUtils; import sun.rmi.server.MarshalOutputStream; /** @@ -51,7 +51,7 @@ public MaliciousOutputStream(OutputStream out) throws IOException super(out); if( !MarshalOutputStream.class.isAssignableFrom(out.getClass()) ) { - Logger.eprintlnMixedYellow("Internal error:", "de.qtc.rmg.io.MaliciousOutputStream", "requires MaliciousOutputStream."); + Logger.eprintlnMixedYellow("Internal error:", "eu.tneitzel.rmg.io.MaliciousOutputStream", "requires MaliciousOutputStream."); RMGUtils.exit(); } diff --git a/src/de/qtc/rmg/io/RawObjectInputStream.java b/src/de/qtc/rmg/io/RawObjectInputStream.java index 86ca3fe..1089a6c 100644 --- a/src/de/qtc/rmg/io/RawObjectInputStream.java +++ b/src/de/qtc/rmg/io/RawObjectInputStream.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.io; +package eu.tneitzel.rmg.io; import java.io.DataInput; import java.io.IOException; @@ -6,7 +6,7 @@ import java.io.ObjectInputStream; import java.lang.reflect.Field; -import de.qtc.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.ExceptionHandler; /** * Wrapper class for an ObjectInputStream. Allows to perform raw byte operations on the underlying diff --git a/src/de/qtc/rmg/io/RawObjectOutputStream.java b/src/de/qtc/rmg/io/RawObjectOutputStream.java index 4ad82d6..987f641 100644 --- a/src/de/qtc/rmg/io/RawObjectOutputStream.java +++ b/src/de/qtc/rmg/io/RawObjectOutputStream.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.io; +package eu.tneitzel.rmg.io; import java.io.DataOutput; import java.io.IOException; @@ -6,7 +6,7 @@ import java.io.OutputStream; import java.lang.reflect.Field; -import de.qtc.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.ExceptionHandler; /** * Wrapper class for an ObjectOutputStream. Allows to perform raw byte operations on the underlying diff --git a/src/de/qtc/rmg/io/SampleWriter.java b/src/de/qtc/rmg/io/SampleWriter.java index 12dcde4..e932d55 100644 --- a/src/de/qtc/rmg/io/SampleWriter.java +++ b/src/de/qtc/rmg/io/SampleWriter.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.io; +package eu.tneitzel.rmg.io; import java.io.File; import java.io.IOException; @@ -11,11 +11,11 @@ import org.apache.commons.io.IOUtils; -import de.qtc.rmg.exceptions.UnexpectedCharacterException; -import de.qtc.rmg.internal.MethodCandidate; -import de.qtc.rmg.networking.RMIEndpoint; -import de.qtc.rmg.utils.RMGUtils; -import de.qtc.rmg.utils.Security; +import eu.tneitzel.rmg.exceptions.UnexpectedCharacterException; +import eu.tneitzel.rmg.internal.MethodCandidate; +import eu.tneitzel.rmg.networking.RMIEndpoint; +import eu.tneitzel.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.utils.Security; import javassist.CannotCompileException; import javassist.CtClass; import javassist.CtMethod; diff --git a/src/de/qtc/rmg/io/SingleOpOutputStream.java b/src/de/qtc/rmg/io/SingleOpOutputStream.java index adb8d95..3e9ea6c 100644 --- a/src/de/qtc/rmg/io/SingleOpOutputStream.java +++ b/src/de/qtc/rmg/io/SingleOpOutputStream.java @@ -1,8 +1,8 @@ -package de.qtc.rmg.io; +package eu.tneitzel.rmg.io; import java.io.ByteArrayOutputStream; -import de.qtc.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.ExceptionHandler; /** * The SingleOpOutputStream class is used during SSRF operations. When the SSRF option is used, diff --git a/src/de/qtc/rmg/io/WordlistHandler.java b/src/de/qtc/rmg/io/WordlistHandler.java index 3298fbb..8971532 100644 --- a/src/de/qtc/rmg/io/WordlistHandler.java +++ b/src/de/qtc/rmg/io/WordlistHandler.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.io; +package eu.tneitzel.rmg.io; import java.io.File; import java.io.IOException; @@ -13,7 +13,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import de.qtc.rmg.internal.MethodCandidate; +import eu.tneitzel.rmg.internal.MethodCandidate; import javassist.CannotCompileException; import javassist.NotFoundException; diff --git a/src/de/qtc/rmg/networking/DGCClientSocket.java b/src/de/qtc/rmg/networking/DGCClientSocket.java index b860860..2bf2845 100644 --- a/src/de/qtc/rmg/networking/DGCClientSocket.java +++ b/src/de/qtc/rmg/networking/DGCClientSocket.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -9,7 +9,7 @@ import java.net.Socket; import java.rmi.server.UID; -import de.qtc.rmg.io.DevNullOutputStream; +import eu.tneitzel.rmg.io.DevNullOutputStream; import sun.rmi.server.MarshalOutputStream; import sun.rmi.transport.TransportConstants; diff --git a/src/de/qtc/rmg/networking/DGCClientSocketFactory.java b/src/de/qtc/rmg/networking/DGCClientSocketFactory.java index 71f68ab..2940efc 100644 --- a/src/de/qtc/rmg/networking/DGCClientSocketFactory.java +++ b/src/de/qtc/rmg/networking/DGCClientSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.net.ServerSocket; diff --git a/src/de/qtc/rmg/networking/DGCClientSslSocketFactory.java b/src/de/qtc/rmg/networking/DGCClientSslSocketFactory.java index 621345d..638ae51 100644 --- a/src/de/qtc/rmg/networking/DGCClientSslSocketFactory.java +++ b/src/de/qtc/rmg/networking/DGCClientSslSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.net.InetAddress; diff --git a/src/de/qtc/rmg/networking/DummySocketFactory.java b/src/de/qtc/rmg/networking/DummySocketFactory.java index b04aa24..db632b0 100644 --- a/src/de/qtc/rmg/networking/DummySocketFactory.java +++ b/src/de/qtc/rmg/networking/DummySocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.io.Serializable; @@ -6,7 +6,7 @@ import java.net.Socket; import java.rmi.server.RMISocketFactory; -import de.qtc.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.ExceptionHandler; /** * During the creation of the An Trinh registry whitelist bypass gadget, the creation of a diff --git a/src/de/qtc/rmg/networking/DummyTrustManager.java b/src/de/qtc/rmg/networking/DummyTrustManager.java index f7ce6f8..78deac3 100644 --- a/src/de/qtc/rmg/networking/DummyTrustManager.java +++ b/src/de/qtc/rmg/networking/DummyTrustManager.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; diff --git a/src/de/qtc/rmg/networking/LimitedSocketFactory.java b/src/de/qtc/rmg/networking/LimitedSocketFactory.java index c44fc6a..3b717ad 100644 --- a/src/de/qtc/rmg/networking/LimitedSocketFactory.java +++ b/src/de/qtc/rmg/networking/LimitedSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.net.InetAddress; @@ -9,8 +9,8 @@ import java.net.UnknownHostException; import java.rmi.server.RMISocketFactory; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.utils.RMGUtils; /** * The LimitedSocketFactoryClass is used when creating a rogue JMX server. It is required diff --git a/src/de/qtc/rmg/networking/LoopbackSocketFactory.java b/src/de/qtc/rmg/networking/LoopbackSocketFactory.java index f59496b..34adfbc 100644 --- a/src/de/qtc/rmg/networking/LoopbackSocketFactory.java +++ b/src/de/qtc/rmg/networking/LoopbackSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.net.Socket; import java.net.UnknownHostException; @@ -6,9 +6,9 @@ import java.net.ServerSocket; import java.rmi.server.RMISocketFactory; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; /** * Remote objects bound to an RMI registry are usually pointing to remote endpoints diff --git a/src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java b/src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java index 8e75468..1b64a65 100644 --- a/src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java +++ b/src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.net.InetAddress; @@ -8,9 +8,9 @@ import javax.net.ssl.SSLSocketFactory; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; /** * Remote objects bound to an RMI registry are usually pointing to remote endpoints diff --git a/src/de/qtc/rmg/networking/RMIEndpoint.java b/src/de/qtc/rmg/networking/RMIEndpoint.java index 3ce8a19..045af61 100644 --- a/src/de/qtc/rmg/networking/RMIEndpoint.java +++ b/src/de/qtc/rmg/networking/RMIEndpoint.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.io.ObjectInput; @@ -9,14 +9,14 @@ import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RemoteRef; -import de.qtc.rmg.exceptions.SSRFException; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodArguments; -import de.qtc.rmg.internal.MethodCandidate; -import de.qtc.rmg.internal.Pair; -import de.qtc.rmg.io.MaliciousOutputStream; -import de.qtc.rmg.io.RawObjectInputStream; -import de.qtc.rmg.plugin.PluginSystem; +import eu.tneitzel.rmg.exceptions.SSRFException; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodArguments; +import eu.tneitzel.rmg.internal.MethodCandidate; +import eu.tneitzel.rmg.internal.Pair; +import eu.tneitzel.rmg.io.MaliciousOutputStream; +import eu.tneitzel.rmg.io.RawObjectInputStream; +import eu.tneitzel.rmg.plugin.PluginSystem; import javassist.CtClass; import javassist.CtPrimitiveType; import sun.rmi.server.UnicastRef; diff --git a/src/de/qtc/rmg/networking/RMIRegistryEndpoint.java b/src/de/qtc/rmg/networking/RMIRegistryEndpoint.java index 0934d40..fef1e47 100644 --- a/src/de/qtc/rmg/networking/RMIRegistryEndpoint.java +++ b/src/de/qtc/rmg/networking/RMIRegistryEndpoint.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.io.InvalidClassException; @@ -11,14 +11,14 @@ import java.util.HashMap; import java.util.Map; -import de.qtc.rmg.exceptions.SSRFException; -import de.qtc.rmg.internal.CodebaseCollector; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.plugin.PluginSystem; -import de.qtc.rmg.utils.RMGUtils; -import de.qtc.rmg.utils.RemoteObjectWrapper; +import eu.tneitzel.rmg.exceptions.SSRFException; +import eu.tneitzel.rmg.internal.CodebaseCollector; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.plugin.PluginSystem; +import eu.tneitzel.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.utils.RemoteObjectWrapper; import javassist.tools.reflect.Reflection; /** diff --git a/src/de/qtc/rmg/networking/SSRFResponseSocket.java b/src/de/qtc/rmg/networking/SSRFResponseSocket.java index 882d882..49f6950 100644 --- a/src/de/qtc/rmg/networking/SSRFResponseSocket.java +++ b/src/de/qtc/rmg/networking/SSRFResponseSocket.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -8,7 +8,7 @@ import java.io.OutputStream; import java.net.Socket; -import de.qtc.rmg.io.DevNullOutputStream; +import eu.tneitzel.rmg.io.DevNullOutputStream; import sun.rmi.transport.TransportConstants; /** diff --git a/src/de/qtc/rmg/networking/SSRFResponseSocketFactory.java b/src/de/qtc/rmg/networking/SSRFResponseSocketFactory.java index 8c2d33f..1ad11e6 100644 --- a/src/de/qtc/rmg/networking/SSRFResponseSocketFactory.java +++ b/src/de/qtc/rmg/networking/SSRFResponseSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.net.ServerSocket; diff --git a/src/de/qtc/rmg/networking/SSRFSocket.java b/src/de/qtc/rmg/networking/SSRFSocket.java index 4fa49ad..68ebcc2 100644 --- a/src/de/qtc/rmg/networking/SSRFSocket.java +++ b/src/de/qtc/rmg/networking/SSRFSocket.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -12,12 +12,12 @@ import java.nio.charset.StandardCharsets; import java.rmi.server.UID; -import de.qtc.rmg.exceptions.SSRFException; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.io.SingleOpOutputStream; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.exceptions.SSRFException; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.io.SingleOpOutputStream; +import eu.tneitzel.rmg.utils.RMGUtils; import sun.rmi.server.MarshalOutputStream; import sun.rmi.transport.TransportConstants; diff --git a/src/de/qtc/rmg/networking/SSRFSocketFactory.java b/src/de/qtc/rmg/networking/SSRFSocketFactory.java index 121f161..d3f3552 100644 --- a/src/de/qtc/rmg/networking/SSRFSocketFactory.java +++ b/src/de/qtc/rmg/networking/SSRFSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.net.ServerSocket; diff --git a/src/de/qtc/rmg/networking/TimeoutSocketFactory.java b/src/de/qtc/rmg/networking/TimeoutSocketFactory.java index b11577f..1229ba8 100644 --- a/src/de/qtc/rmg/networking/TimeoutSocketFactory.java +++ b/src/de/qtc/rmg/networking/TimeoutSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.net.InetSocketAddress; diff --git a/src/de/qtc/rmg/networking/TrustAllSocketFactory.java b/src/de/qtc/rmg/networking/TrustAllSocketFactory.java index 98a8708..88f498e 100644 --- a/src/de/qtc/rmg/networking/TrustAllSocketFactory.java +++ b/src/de/qtc/rmg/networking/TrustAllSocketFactory.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.networking; +package eu.tneitzel.rmg.networking; import java.io.IOException; import java.net.InetSocketAddress; @@ -12,9 +12,9 @@ import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.utils.RMGUtils; /** * Wrapper around an SSLSocketFactory that trusts all certificates. This is used for TLS protected diff --git a/src/de/qtc/rmg/operations/ActivationClient.java b/src/de/qtc/rmg/operations/ActivationClient.java index 8e013fc..38f5f19 100644 --- a/src/de/qtc/rmg/operations/ActivationClient.java +++ b/src/de/qtc/rmg/operations/ActivationClient.java @@ -1,14 +1,14 @@ -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.rmi.server.ObjID; import java.rmi.server.RemoteRef; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodArguments; -import de.qtc.rmg.internal.RMIComponent; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.io.MaliciousOutputStream; -import de.qtc.rmg.networking.RMIEndpoint; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodArguments; +import eu.tneitzel.rmg.internal.RMIComponent; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.io.MaliciousOutputStream; +import eu.tneitzel.rmg.networking.RMIEndpoint; import javassist.ClassPool; import javassist.CtClass; diff --git a/src/de/qtc/rmg/operations/DGCClient.java b/src/de/qtc/rmg/operations/DGCClient.java index bdeebf4..11901c8 100644 --- a/src/de/qtc/rmg/operations/DGCClient.java +++ b/src/de/qtc/rmg/operations/DGCClient.java @@ -1,15 +1,15 @@ -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.rmi.server.ObjID; import java.util.HashMap; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodArguments; -import de.qtc.rmg.internal.RMIComponent; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.io.MaliciousOutputStream; -import de.qtc.rmg.networking.RMIEndpoint; -import de.qtc.rmg.utils.DefinitelyNonExistingClass; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodArguments; +import eu.tneitzel.rmg.internal.RMIComponent; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.io.MaliciousOutputStream; +import eu.tneitzel.rmg.networking.RMIEndpoint; +import eu.tneitzel.rmg.utils.DefinitelyNonExistingClass; /** * The distributed garbage collector (DGC) is a well known RMI object with publicly known method definitions. @@ -94,7 +94,7 @@ public void enumSecurityManager(String callName) Logger.statusDefault(); ExceptionHandler.showStackTrace(e); - } else if( c.getMessage().equals("de.qtc.rmg.utils.DefinitelyNonExistingClass")) { + } else if( c.getMessage().equals("eu.tneitzel.rmg.utils.DefinitelyNonExistingClass")) { Logger.printlnMixedYellow("- RMI server", "did not", "attempt to parse the supplied codebase."); Logger.printlnMixedBlue(" --> The server", "does use", "a Security Manager."); Logger.statusDefault(); diff --git a/src/de/qtc/rmg/operations/Dispatcher.java b/src/de/qtc/rmg/operations/Dispatcher.java index d72af47..e136b6b 100644 --- a/src/de/qtc/rmg/operations/Dispatcher.java +++ b/src/de/qtc/rmg/operations/Dispatcher.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.io.IOException; import java.rmi.NoSuchObjectException; @@ -10,25 +10,25 @@ import javax.management.remote.rmi.RMIServer; -import de.qtc.rmg.endpoints.KnownEndpoint; -import de.qtc.rmg.endpoints.KnownEndpointHolder; -import de.qtc.rmg.exceptions.UnexpectedCharacterException; -import de.qtc.rmg.internal.ArgumentHandler; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodCandidate; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.internal.RMIComponent; -import de.qtc.rmg.io.Formatter; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.io.SampleWriter; -import de.qtc.rmg.io.WordlistHandler; -import de.qtc.rmg.networking.RMIEndpoint; -import de.qtc.rmg.networking.RMIRegistryEndpoint; -import de.qtc.rmg.utils.RMGUtils; -import de.qtc.rmg.utils.RemoteObjectWrapper; -import de.qtc.rmg.utils.RogueJMX; -import de.qtc.rmg.utils.UnicastWrapper; -import de.qtc.rmg.utils.YsoIntegration; +import eu.tneitzel.rmg.endpoints.KnownEndpoint; +import eu.tneitzel.rmg.endpoints.KnownEndpointHolder; +import eu.tneitzel.rmg.exceptions.UnexpectedCharacterException; +import eu.tneitzel.rmg.internal.ArgumentHandler; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodCandidate; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.internal.RMIComponent; +import eu.tneitzel.rmg.io.Formatter; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.io.SampleWriter; +import eu.tneitzel.rmg.io.WordlistHandler; +import eu.tneitzel.rmg.networking.RMIEndpoint; +import eu.tneitzel.rmg.networking.RMIRegistryEndpoint; +import eu.tneitzel.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.utils.RemoteObjectWrapper; +import eu.tneitzel.rmg.utils.RogueJMX; +import eu.tneitzel.rmg.utils.UnicastWrapper; +import eu.tneitzel.rmg.utils.YsoIntegration; import javassist.CannotCompileException; import javassist.NotFoundException; @@ -37,9 +37,9 @@ * to the ArgumentParser object and extracts all required arguments parameters for the corresponding method calls. * * Methods within the Dispatcher class can be annotated with the Parameters annotation to specify additional requirements - * on their expected arguments. Refer to the de.qtc.rmg.annotations.Parameters class for more details. + * on their expected arguments. Refer to the eu.tneitzel.rmg.annotations.Parameters class for more details. * - * To add a new operation to rmg, the operation must first be registered within the de.qtc.rmg.operations.Operation class. + * To add a new operation to rmg, the operation must first be registered within the eu.tneitzel.rmg.operations.Operation class. * A new Operation needs to be created there that references the corresponding method within this class. * * @author Tobias Neitzel (@qtc_de) diff --git a/src/de/qtc/rmg/operations/MethodGuesser.java b/src/de/qtc/rmg/operations/MethodGuesser.java index 396a209..d6b7915 100644 --- a/src/de/qtc/rmg/operations/MethodGuesser.java +++ b/src/de/qtc/rmg/operations/MethodGuesser.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.io.PrintWriter; import java.io.StringWriter; @@ -11,16 +11,16 @@ import org.springframework.remoting.support.RemoteInvocation; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodArguments; -import de.qtc.rmg.internal.MethodCandidate; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.utils.ProgressBar; -import de.qtc.rmg.utils.RMGUtils; -import de.qtc.rmg.utils.RemoteInvocationHolder; -import de.qtc.rmg.utils.SpringRemotingWrapper; -import de.qtc.rmg.utils.UnicastWrapper; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodArguments; +import eu.tneitzel.rmg.internal.MethodCandidate; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.utils.ProgressBar; +import eu.tneitzel.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.utils.RemoteInvocationHolder; +import eu.tneitzel.rmg.utils.SpringRemotingWrapper; +import eu.tneitzel.rmg.utils.UnicastWrapper; import javassist.CannotCompileException; import javassist.NotFoundException; diff --git a/src/de/qtc/rmg/operations/Operation.java b/src/de/qtc/rmg/operations/Operation.java index ac8da52..c5418bd 100644 --- a/src/de/qtc/rmg/operations/Operation.java +++ b/src/de/qtc/rmg/operations/Operation.java @@ -1,9 +1,9 @@ -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.lang.reflect.Method; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; import net.sourceforge.argparse4j.inf.Subparser; import net.sourceforge.argparse4j.inf.Subparsers; diff --git a/src/de/qtc/rmg/operations/PortScanner.java b/src/de/qtc/rmg/operations/PortScanner.java index 41ef90b..66031b5 100644 --- a/src/de/qtc/rmg/operations/PortScanner.java +++ b/src/de/qtc/rmg/operations/PortScanner.java @@ -1,18 +1,18 @@ -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.rmi.server.ObjID; import java.rmi.server.RMIClientSocketFactory; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodArguments; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.networking.RMIEndpoint; -import de.qtc.rmg.networking.TimeoutSocketFactory; -import de.qtc.rmg.networking.TrustAllSocketFactory; -import de.qtc.rmg.utils.ProgressBar; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodArguments; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.networking.RMIEndpoint; +import eu.tneitzel.rmg.networking.TimeoutSocketFactory; +import eu.tneitzel.rmg.networking.TrustAllSocketFactory; +import eu.tneitzel.rmg.utils.ProgressBar; /** diff --git a/src/de/qtc/rmg/operations/RegistryClient.java b/src/de/qtc/rmg/operations/RegistryClient.java index f64f6e5..27c6870 100644 --- a/src/de/qtc/rmg/operations/RegistryClient.java +++ b/src/de/qtc/rmg/operations/RegistryClient.java @@ -1,18 +1,18 @@ -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.rmi.server.ObjID; import javax.management.remote.rmi.RMIServerImpl_Stub; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodArguments; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.internal.RMIComponent; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.io.MaliciousOutputStream; -import de.qtc.rmg.networking.RMIEndpoint; -import de.qtc.rmg.utils.RMGUtils; -import de.qtc.rmg.utils.YsoIntegration; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodArguments; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.internal.RMIComponent; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.io.MaliciousOutputStream; +import eu.tneitzel.rmg.networking.RMIEndpoint; +import eu.tneitzel.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.utils.YsoIntegration; import sun.rmi.server.UnicastRef; import sun.rmi.transport.LiveRef; import sun.rmi.transport.tcp.TCPEndpoint; diff --git a/src/de/qtc/rmg/operations/RemoteObjectClient.java b/src/de/qtc/rmg/operations/RemoteObjectClient.java index 1f2d32a..b749379 100644 --- a/src/de/qtc/rmg/operations/RemoteObjectClient.java +++ b/src/de/qtc/rmg/operations/RemoteObjectClient.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.rmi.server.ObjID; import java.util.ArrayList; @@ -6,18 +6,18 @@ import java.util.Iterator; import java.util.List; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodArguments; -import de.qtc.rmg.internal.MethodCandidate; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.internal.RMIComponent; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.networking.RMIEndpoint; -import de.qtc.rmg.networking.RMIRegistryEndpoint; -import de.qtc.rmg.utils.DefinitelyNonExistingClass; -import de.qtc.rmg.utils.RMGUtils; -import de.qtc.rmg.utils.SpringRemotingWrapper; -import de.qtc.rmg.utils.UnicastWrapper; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodArguments; +import eu.tneitzel.rmg.internal.MethodCandidate; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.internal.RMIComponent; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.networking.RMIEndpoint; +import eu.tneitzel.rmg.networking.RMIRegistryEndpoint; +import eu.tneitzel.rmg.utils.DefinitelyNonExistingClass; +import eu.tneitzel.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.utils.SpringRemotingWrapper; +import eu.tneitzel.rmg.utils.UnicastWrapper; import javassist.CannotCompileException; import javassist.CtClass; import javassist.NotFoundException; diff --git a/src/de/qtc/rmg/operations/ScanAction.java b/src/de/qtc/rmg/operations/ScanAction.java index 80a2741..414b621 100644 --- a/src/de/qtc/rmg/operations/ScanAction.java +++ b/src/de/qtc/rmg/operations/ScanAction.java @@ -1,10 +1,10 @@ -package de.qtc.rmg.operations; +package eu.tneitzel.rmg.operations; import java.util.EnumSet; import java.util.List; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.utils.RMGUtils; /** * The ScanAction Enum represents available enumeration techniques that are applied during rmg's diff --git a/src/de/qtc/rmg/plugin/DefaultProvider.java b/src/de/qtc/rmg/plugin/DefaultProvider.java index 1549452..3cca421 100644 --- a/src/de/qtc/rmg/plugin/DefaultProvider.java +++ b/src/de/qtc/rmg/plugin/DefaultProvider.java @@ -1,21 +1,21 @@ -package de.qtc.rmg.plugin; +package eu.tneitzel.rmg.plugin; import java.lang.reflect.Method; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMISocketFactory; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.networking.DGCClientSocketFactory; -import de.qtc.rmg.networking.LoopbackSocketFactory; -import de.qtc.rmg.networking.SSRFResponseSocketFactory; -import de.qtc.rmg.networking.SSRFSocketFactory; -import de.qtc.rmg.networking.TrustAllSocketFactory; -import de.qtc.rmg.operations.Operation; -import de.qtc.rmg.operations.RegistryClient; -import de.qtc.rmg.utils.RMGUtils; -import de.qtc.rmg.utils.YsoIntegration; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.networking.DGCClientSocketFactory; +import eu.tneitzel.rmg.networking.LoopbackSocketFactory; +import eu.tneitzel.rmg.networking.SSRFResponseSocketFactory; +import eu.tneitzel.rmg.networking.SSRFSocketFactory; +import eu.tneitzel.rmg.networking.TrustAllSocketFactory; +import eu.tneitzel.rmg.operations.Operation; +import eu.tneitzel.rmg.operations.RegistryClient; +import eu.tneitzel.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.utils.YsoIntegration; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; @@ -99,7 +99,7 @@ public Object[] getArgumentArray(String argumentString) ClassPool pool = ClassPool.getDefault(); try { - CtClass evaluator = pool.makeClass("de.qtc.rmg.plugin.DefaultProviderEval"); + CtClass evaluator = pool.makeClass("eu.tneitzel.rmg.plugin.DefaultProviderEval"); String evalFunction = "public static Object[] eval() {" + " return new Object[] { " + argumentString + "};" + "}"; @@ -195,9 +195,9 @@ public String getDefaultSSLSocketFactory(String host, int port) { if (RMGOption.SSRFRESPONSE.notNull()) { - return "de.qtc.rmg.networking.DGCClientSslSocketFactory"; + return "eu.tneitzel.rmg.networking.DGCClientSslSocketFactory"; } - return "de.qtc.rmg.networking.LoopbackSslSocketFactory"; + return "eu.tneitzel.rmg.networking.LoopbackSslSocketFactory"; } } diff --git a/src/de/qtc/rmg/plugin/GenericPrint.java b/src/de/qtc/rmg/plugin/GenericPrint.java index 863fa21..e13564f 100644 --- a/src/de/qtc/rmg/plugin/GenericPrint.java +++ b/src/de/qtc/rmg/plugin/GenericPrint.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.plugin; +package eu.tneitzel.rmg.plugin; import java.io.File; import java.lang.reflect.Array; @@ -7,12 +7,12 @@ import java.util.Map; import java.util.Map.Entry; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.utils.ActivatableWrapper; -import de.qtc.rmg.utils.RemoteObjectWrapper; -import de.qtc.rmg.utils.SpringRemotingWrapper; -import de.qtc.rmg.utils.UnicastWrapper; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.utils.ActivatableWrapper; +import eu.tneitzel.rmg.utils.RemoteObjectWrapper; +import eu.tneitzel.rmg.utils.SpringRemotingWrapper; +import eu.tneitzel.rmg.utils.UnicastWrapper; /** * GenericPrint is an rmg ResponseHandler plugin that attempts to print all incoming diff --git a/src/de/qtc/rmg/plugin/IArgumentProvider.java b/src/de/qtc/rmg/plugin/IArgumentProvider.java index 3e996d0..4af7690 100644 --- a/src/de/qtc/rmg/plugin/IArgumentProvider.java +++ b/src/de/qtc/rmg/plugin/IArgumentProvider.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.plugin; +package eu.tneitzel.rmg.plugin; /** * The IArgumentProvider interface is used during rmg's 'call' action to obtain the argument array that should be diff --git a/src/de/qtc/rmg/plugin/IPayloadProvider.java b/src/de/qtc/rmg/plugin/IPayloadProvider.java index f1a69d7..94ec081 100644 --- a/src/de/qtc/rmg/plugin/IPayloadProvider.java +++ b/src/de/qtc/rmg/plugin/IPayloadProvider.java @@ -1,6 +1,6 @@ -package de.qtc.rmg.plugin; +package eu.tneitzel.rmg.plugin; -import de.qtc.rmg.operations.Operation; +import eu.tneitzel.rmg.operations.Operation; /** * The IPayloadProvider interface is used during all rmg actions that send payload objects to the remote server. diff --git a/src/de/qtc/rmg/plugin/IResponseHandler.java b/src/de/qtc/rmg/plugin/IResponseHandler.java index a652dd3..9235416 100644 --- a/src/de/qtc/rmg/plugin/IResponseHandler.java +++ b/src/de/qtc/rmg/plugin/IResponseHandler.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.plugin; +package eu.tneitzel.rmg.plugin; /** * The IResponseHandler interface is used during rmg's 'call' action to handle the return value of an invoked method. diff --git a/src/de/qtc/rmg/plugin/ISocketFactoryProvider.java b/src/de/qtc/rmg/plugin/ISocketFactoryProvider.java index 68cc488..0a57ac9 100644 --- a/src/de/qtc/rmg/plugin/ISocketFactoryProvider.java +++ b/src/de/qtc/rmg/plugin/ISocketFactoryProvider.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.plugin; +package eu.tneitzel.rmg.plugin; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMISocketFactory; diff --git a/src/de/qtc/rmg/plugin/PluginSystem.java b/src/de/qtc/rmg/plugin/PluginSystem.java index 0639f89..40f1baf 100644 --- a/src/de/qtc/rmg/plugin/PluginSystem.java +++ b/src/de/qtc/rmg/plugin/PluginSystem.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.plugin; +package eu.tneitzel.rmg.plugin; import java.io.File; import java.io.FileInputStream; @@ -9,12 +9,12 @@ import java.util.jar.JarInputStream; import java.util.jar.Manifest; -import de.qtc.rmg.exceptions.MalformedPluginException; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.operations.Operation; -import de.qtc.rmg.utils.RMGUtils; +import eu.tneitzel.rmg.exceptions.MalformedPluginException; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.operations.Operation; +import eu.tneitzel.rmg.utils.RMGUtils; /** * The PluginSystem class allows rmg to be extended by user defined classes. It can be used to setup diff --git a/src/de/qtc/rmg/plugin/ReturnValueProvider.java b/src/de/qtc/rmg/plugin/ReturnValueProvider.java index f30204e..504c884 100644 --- a/src/de/qtc/rmg/plugin/ReturnValueProvider.java +++ b/src/de/qtc/rmg/plugin/ReturnValueProvider.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.plugin; +package eu.tneitzel.rmg.plugin; /** * ReturnValueProvider is a helper class that can be used to capture return values of custom diff --git a/src/de/qtc/rmg/utils/ActivatableWrapper.java b/src/de/qtc/rmg/utils/ActivatableWrapper.java index 759a9c9..053024d 100644 --- a/src/de/qtc/rmg/utils/ActivatableWrapper.java +++ b/src/de/qtc/rmg/utils/ActivatableWrapper.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.io.IOException; import java.lang.reflect.Field; @@ -7,12 +7,12 @@ import java.rmi.server.RemoteRef; import java.rmi.server.UID; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.networking.RMIEndpoint; -import de.qtc.rmg.operations.ActivationClient; -import de.qtc.rmg.plugin.IResponseHandler; -import de.qtc.rmg.plugin.PluginSystem; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.networking.RMIEndpoint; +import eu.tneitzel.rmg.operations.ActivationClient; +import eu.tneitzel.rmg.plugin.IResponseHandler; +import eu.tneitzel.rmg.plugin.PluginSystem; import sun.rmi.server.UnicastRef; import sun.rmi.transport.LiveRef; import sun.rmi.transport.tcp.TCPEndpoint; diff --git a/src/de/qtc/rmg/utils/DefinitelyNonExistingClass.java b/src/de/qtc/rmg/utils/DefinitelyNonExistingClass.java index 8e1e1d5..bc1b2bd 100644 --- a/src/de/qtc/rmg/utils/DefinitelyNonExistingClass.java +++ b/src/de/qtc/rmg/utils/DefinitelyNonExistingClass.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.io.Serializable; diff --git a/src/de/qtc/rmg/utils/EmptyWrapper.java b/src/de/qtc/rmg/utils/EmptyWrapper.java index ce7133e..0b776d1 100644 --- a/src/de/qtc/rmg/utils/EmptyWrapper.java +++ b/src/de/qtc/rmg/utils/EmptyWrapper.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; /** * EmptyWrapper is basically a dummy class that extends RemoteWrapper. It is only used diff --git a/src/de/qtc/rmg/utils/ProgressBar.java b/src/de/qtc/rmg/utils/ProgressBar.java index 6b3c11a..e38b4ac 100644 --- a/src/de/qtc/rmg/utils/ProgressBar.java +++ b/src/de/qtc/rmg/utils/ProgressBar.java @@ -1,7 +1,7 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; /** * Simple progress bar that is used during the guess and scan operations. diff --git a/src/de/qtc/rmg/utils/RMGUtils.java b/src/de/qtc/rmg/utils/RMGUtils.java index 433a176..299743c 100644 --- a/src/de/qtc/rmg/utils/RMGUtils.java +++ b/src/de/qtc/rmg/utils/RMGUtils.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.io.InvalidClassException; import java.lang.reflect.Array; @@ -25,12 +25,12 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodArguments; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.internal.RMIComponent; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.io.MaliciousOutputStream; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodArguments; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.internal.RMIComponent; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.io.MaliciousOutputStream; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; @@ -86,7 +86,7 @@ public static void init() ExceptionHandler.internalError("RMGUtils.init", "Caught unexpected NotFoundException."); } - dummyClass = pool.makeInterface("de.qtc.rmg.Dummy"); + dummyClass = pool.makeInterface("eu.tneitzel.rmg.Dummy"); createdClasses = new HashSet(); } @@ -250,12 +250,12 @@ public static Class makeSocketFactory(String className, long serialVersionUID) t if (!RMGOption.SOCKET_FACTORY_PLAIN.getBool() && (RMGOption.CONN_SSL.getBool() || RMGOption.SOCKET_FACTORY_SSL.getBool())) { - ctClass = pool.getAndRename("de.qtc.rmg.networking.LoopbackSslSocketFactory", className); + ctClass = pool.getAndRename("eu.tneitzel.rmg.networking.LoopbackSslSocketFactory", className); } else if (!RMGOption.SOCKET_FACTORY_SSL.getBool() && (!RMGOption.CONN_SSL.getBool() || RMGOption.SOCKET_FACTORY_PLAIN.getBool())) { - ctClass = pool.getAndRename("de.qtc.rmg.networking.LoopbackSocketFactory", className); + ctClass = pool.getAndRename("eu.tneitzel.rmg.networking.LoopbackSocketFactory", className); } else @@ -607,7 +607,7 @@ public static void exit() */ public static void enableCodebase() { - System.setProperty("java.rmi.server.RMIClassLoaderSpi", "de.qtc.rmg.internal.CodebaseCollector"); + System.setProperty("java.rmi.server.RMIClassLoaderSpi", "eu.tneitzel.rmg.internal.CodebaseCollector"); System.setProperty("java.rmi.server.useCodebaseOnly", "false"); } @@ -618,7 +618,7 @@ public static void enableCodebase() */ public static void enableCodebaseCollector() { - System.setProperty("java.rmi.server.RMIClassLoaderSpi", "de.qtc.rmg.internal.CodebaseCollector"); + System.setProperty("java.rmi.server.RMIClassLoaderSpi", "eu.tneitzel.rmg.internal.CodebaseCollector"); } /** diff --git a/src/de/qtc/rmg/utils/RemoteInvocationHolder.java b/src/de/qtc/rmg/utils/RemoteInvocationHolder.java index 17e5394..092a1c3 100644 --- a/src/de/qtc/rmg/utils/RemoteInvocationHolder.java +++ b/src/de/qtc/rmg/utils/RemoteInvocationHolder.java @@ -1,10 +1,10 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.util.Arrays; import org.springframework.remoting.support.RemoteInvocation; -import de.qtc.rmg.internal.MethodCandidate; +import eu.tneitzel.rmg.internal.MethodCandidate; /** diff --git a/src/de/qtc/rmg/utils/RemoteObjectWrapper.java b/src/de/qtc/rmg/utils/RemoteObjectWrapper.java index 18bc882..e5f897f 100644 --- a/src/de/qtc/rmg/utils/RemoteObjectWrapper.java +++ b/src/de/qtc/rmg/utils/RemoteObjectWrapper.java @@ -1,11 +1,11 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.rmi.Remote; import java.rmi.server.RemoteRef; -import de.qtc.rmg.endpoints.KnownEndpoint; -import de.qtc.rmg.endpoints.KnownEndpointHolder; -import de.qtc.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.endpoints.KnownEndpoint; +import eu.tneitzel.rmg.endpoints.KnownEndpointHolder; +import eu.tneitzel.rmg.internal.ExceptionHandler; import javassist.tools.reflect.Reflection; import sun.rmi.server.UnicastRef; diff --git a/src/de/qtc/rmg/utils/RogueJMX.java b/src/de/qtc/rmg/utils/RogueJMX.java index e0a48ab..7495afa 100644 --- a/src/de/qtc/rmg/utils/RogueJMX.java +++ b/src/de/qtc/rmg/utils/RogueJMX.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -12,10 +12,10 @@ import javax.management.remote.rmi.RMIConnection; import javax.management.remote.rmi.RMIServer; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.networking.LimitedSocketFactory; -import de.qtc.rmg.operations.RemoteObjectClient; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.networking.LimitedSocketFactory; +import eu.tneitzel.rmg.operations.RemoteObjectClient; import sun.rmi.server.UnicastServerRef; import sun.rmi.transport.LiveRef; diff --git a/src/de/qtc/rmg/utils/Security.java b/src/de/qtc/rmg/utils/Security.java index 213dcb3..39b8a65 100644 --- a/src/de/qtc/rmg/utils/Security.java +++ b/src/de/qtc/rmg/utils/Security.java @@ -1,10 +1,10 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.util.regex.Matcher; import java.util.regex.Pattern; -import de.qtc.rmg.exceptions.UnexpectedCharacterException; -import de.qtc.rmg.internal.RMGOption; +import eu.tneitzel.rmg.exceptions.UnexpectedCharacterException; +import eu.tneitzel.rmg.internal.RMGOption; /** * During sample creation, remote-method-guesser creates sample files with filenames and contents controlled by diff --git a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java index 97c5305..79e60cf 100644 --- a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java +++ b/src/de/qtc/rmg/utils/SpringRemotingWrapper.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.rmi.Remote; import java.util.HashSet; @@ -6,13 +6,13 @@ import org.springframework.remoting.support.RemoteInvocation; -import de.qtc.rmg.endpoints.KnownEndpointHolder; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.MethodCandidate; -import de.qtc.rmg.operations.RemoteObjectClient; -import de.qtc.rmg.plugin.IResponseHandler; -import de.qtc.rmg.plugin.PluginSystem; -import de.qtc.rmg.plugin.ReturnValueProvider; +import eu.tneitzel.rmg.endpoints.KnownEndpointHolder; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.MethodCandidate; +import eu.tneitzel.rmg.operations.RemoteObjectClient; +import eu.tneitzel.rmg.plugin.IResponseHandler; +import eu.tneitzel.rmg.plugin.PluginSystem; +import eu.tneitzel.rmg.plugin.ReturnValueProvider; import javassist.CannotCompileException; import javassist.CtClass; import javassist.NotFoundException; diff --git a/src/de/qtc/rmg/utils/UnicastWrapper.java b/src/de/qtc/rmg/utils/UnicastWrapper.java index e1482f9..d4dfb91 100644 --- a/src/de/qtc/rmg/utils/UnicastWrapper.java +++ b/src/de/qtc/rmg/utils/UnicastWrapper.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.lang.reflect.Field; import java.lang.reflect.Proxy; @@ -13,7 +13,7 @@ import javax.rmi.ssl.SslRMIClientSocketFactory; -import de.qtc.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.ExceptionHandler; import sun.rmi.server.UnicastRef; import sun.rmi.transport.LiveRef; import sun.rmi.transport.tcp.TCPEndpoint; diff --git a/src/de/qtc/rmg/utils/YsoIntegration.java b/src/de/qtc/rmg/utils/YsoIntegration.java index b49d66e..9a16c81 100644 --- a/src/de/qtc/rmg/utils/YsoIntegration.java +++ b/src/de/qtc/rmg/utils/YsoIntegration.java @@ -1,4 +1,4 @@ -package de.qtc.rmg.utils; +package eu.tneitzel.rmg.utils; import java.io.File; import java.lang.reflect.Constructor; @@ -22,10 +22,10 @@ import javax.net.ServerSocketFactory; -import de.qtc.rmg.internal.ExceptionHandler; -import de.qtc.rmg.internal.RMGOption; -import de.qtc.rmg.io.Logger; -import de.qtc.rmg.networking.DummySocketFactory; +import eu.tneitzel.rmg.internal.ExceptionHandler; +import eu.tneitzel.rmg.internal.RMGOption; +import eu.tneitzel.rmg.io.Logger; +import eu.tneitzel.rmg.networking.DummySocketFactory; import sun.rmi.server.UnicastRef; import sun.rmi.transport.LiveRef; import sun.rmi.transport.tcp.TCPEndpoint; diff --git a/tests/generic/tests/ssrf-response.yml b/tests/generic/tests/ssrf-response.yml index ebd8cea..4c31977 100644 --- a/tests/generic/tests/ssrf-response.yml +++ b/tests/generic/tests/ssrf-response.yml @@ -77,7 +77,7 @@ tests: - contains: values: - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'Endpoint: iinsecure.dev:37797 TLS: no ObjID: [79bf1d8a:17b14e4e4b0:-7ff8, -8372830402508756097]' - 'http://iinsecure.dev/well-hidden-development-folder/' @@ -316,7 +316,7 @@ tests: - contains: values: - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'Endpoint: iinsecure.dev:37797 TLS: no ObjID: [79bf1d8a:17b14e4e4b0:-7ff8, -8372830402508756097]' - 'http://iinsecure.dev/well-hidden-development-folder/' diff --git a/tests/jdk11/tests/enum.yml b/tests/jdk11/tests/enum.yml index 89a2af9..4c9a78f 100644 --- a/tests/jdk11/tests/enum.yml +++ b/tests/jdk11/tests/enum.yml @@ -30,11 +30,11 @@ tests: ignore_case: True values: - 'ssl-server' - - 'de.qtc.rmg.server.interfaces.ISslServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.ISslServer (unknown class)' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'secure-server' - - 'de.qtc.rmg.server.interfaces.ISecureServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.ISecureServer (unknown class)' - regex: description: |- @@ -76,11 +76,11 @@ tests: ignore_case: True values: - 'plain-server2' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'legacy-service' - - 'de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' + - 'eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' - contains: description: |- @@ -185,13 +185,13 @@ tests: ignore_case: True values: - 'activation-test' - - 'de.qtc.rmg.server.activation.IActivationService (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'activation-test2' - - 'de.qtc.rmg.server.activation.IActivationService2 (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService2 (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' invert: @@ -301,13 +301,13 @@ tests: ignore_case: True values: - 'activation-test' - - 'de.qtc.rmg.server.activation.IActivationService (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'activation-test2' - - 'de.qtc.rmg.server.activation.IActivationService2 (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService2 (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' - 'TLS: yes ObjID:' @@ -423,11 +423,11 @@ tests: ignore_case: True values: - 'plain-server2' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'legacy-service' - - '_de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' + - '_eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' - contains: description: |- diff --git a/tests/jdk8/tests/enum.yml b/tests/jdk8/tests/enum.yml index 44d140d..9105857 100644 --- a/tests/jdk8/tests/enum.yml +++ b/tests/jdk8/tests/enum.yml @@ -30,11 +30,11 @@ tests: ignore_case: True values: - 'ssl-server' - - 'de.qtc.rmg.server.interfaces.ISslServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.ISslServer (unknown class)' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'secure-server' - - 'de.qtc.rmg.server.interfaces.ISecureServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.ISecureServer (unknown class)' - regex: description: |- @@ -79,11 +79,11 @@ tests: ignore_case: True values: - 'plain-server2' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'legacy-service' - - 'de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' + - 'eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' - contains: description: |- @@ -190,13 +190,13 @@ tests: ignore_case: True values: - 'activation-test' - - 'de.qtc.rmg.server.activation.IActivationService (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'activation-test2' - - 'de.qtc.rmg.server.activation.IActivationService2 (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService2 (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' invert: @@ -308,13 +308,13 @@ tests: ignore_case: True values: - 'activation-test' - - 'de.qtc.rmg.server.activation.IActivationService (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'activation-test2' - - 'de.qtc.rmg.server.activation.IActivationService2 (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService2 (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' - 'TLS: yes ObjID:' @@ -432,11 +432,11 @@ tests: ignore_case: True values: - 'plain-server2' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'legacy-service' - - '_de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' + - '_eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' - contains: description: |- diff --git a/tests/jdk9/tests/enum.yml b/tests/jdk9/tests/enum.yml index acd22df..80baca7 100644 --- a/tests/jdk9/tests/enum.yml +++ b/tests/jdk9/tests/enum.yml @@ -30,11 +30,11 @@ tests: ignore_case: True values: - 'ssl-server' - - 'de.qtc.rmg.server.interfaces.ISslServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.ISslServer (unknown class)' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'secure-server' - - 'de.qtc.rmg.server.interfaces.ISecureServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.ISecureServer (unknown class)' - regex: description: |- @@ -79,11 +79,11 @@ tests: ignore_case: True values: - 'plain-server2' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'legacy-service' - - 'de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' + - 'eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' - contains: description: |- @@ -190,13 +190,13 @@ tests: ignore_case: True values: - 'activation-test' - - 'de.qtc.rmg.server.activation.IActivationService (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'activation-test2' - - 'de.qtc.rmg.server.activation.IActivationService2 (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService2 (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' invert: @@ -308,13 +308,13 @@ tests: ignore_case: True values: - 'activation-test' - - 'de.qtc.rmg.server.activation.IActivationService (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'activation-test2' - - 'de.qtc.rmg.server.activation.IActivationService2 (unknown class)' + - 'eu.tneitzel.rmg.server.activation.IActivationService2 (unknown class)' - 'Activator: iinsecure.example:1098 ActivationID:' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' - 'TLS: yes ObjID:' @@ -432,11 +432,11 @@ tests: ignore_case: True values: - 'plain-server2' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'plain-server' - - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' + - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'legacy-service' - - '_de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' + - '_eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)' - contains: description: |- diff --git a/tests/utils/PluginTest.java b/tests/utils/PluginTest.java index f13f761..374fd49 100644 --- a/tests/utils/PluginTest.java +++ b/tests/utils/PluginTest.java @@ -2,11 +2,11 @@ import java.util.HashMap; import java.util.Collection; -import de.qtc.rmg.operations.Operation; -import de.qtc.rmg.plugin.DefaultProvider; -import de.qtc.rmg.plugin.IResponseHandler; -import de.qtc.rmg.plugin.IPayloadProvider; -import de.qtc.rmg.plugin.IArgumentProvider; +import eu.tneitzel.rmg.operations.Operation; +import eu.tneitzel.rmg.plugin.DefaultProvider; +import eu.tneitzel.rmg.plugin.IResponseHandler; +import eu.tneitzel.rmg.plugin.IPayloadProvider; +import eu.tneitzel.rmg.plugin.IArgumentProvider; public class PluginTest implements IResponseHandler, IPayloadProvider, IArgumentProvider { From 2148aaf10fdfa48adbc4b99451a86c2ca5af091a Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sat, 9 Dec 2023 13:16:10 +0100 Subject: [PATCH 28/60] Rename files --- .../src/{de/qtc => eu/tneitzel}/rmg/server/ExampleServer.java | 0 .../tneitzel}/rmg/server/activation/ActivationServer.java | 0 .../tneitzel}/rmg/server/activation/ActivationService.java | 0 .../tneitzel}/rmg/server/activation/ActivationService2.java | 0 .../tneitzel}/rmg/server/activation/IActivationService.java | 0 .../tneitzel}/rmg/server/activation/IActivationService2.java | 0 .../tneitzel}/rmg/server/factory/CustomSocketFactory.java | 0 .../tneitzel}/rmg/server/factory/CustomSocketFactoryServer.java | 0 .../qtc => eu/tneitzel}/rmg/server/interfaces/IPlainServer.java | 0 .../qtc => eu/tneitzel}/rmg/server/interfaces/ISecureServer.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/interfaces/ISslServer.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/legacy/LegacyServer.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/legacy/LegacyService.java | 0 .../qtc => eu/tneitzel}/rmg/server/legacy/LegacyServiceImpl.java | 0 .../qtc => eu/tneitzel}/rmg/server/legacy/StringContainer.java | 0 .../qtc => eu/tneitzel}/rmg/server/operations/PlainServer.java | 0 .../qtc => eu/tneitzel}/rmg/server/operations/SecureServer.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/operations/SslServer.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/utils/CodebaseLogger.java | 0 .../src/{de/qtc => eu/tneitzel}/rmg/server/utils/Logger.java | 0 .../src/{de/qtc => eu/tneitzel}/rmg/server/utils/Utils.java | 0 .../qtc => eu/tneitzel}/rmg/springremoting/ServerOperations.java | 0 .../tneitzel}/rmg/springremoting/SpringRemotingService.java | 0 .../java/{de/qtc => eu/tneitzel}/rmg/springremoting/Starter.java | 0 .../src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/Starter.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/ssrf/http/JarHandler.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/ssrf/http/SSRFHandler.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/ssrf/http/SSRFServer.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/ssrf/rmi/FileManager.java | 0 .../{de/qtc => eu/tneitzel}/rmg/server/ssrf/rmi/IFileManager.java | 0 .../tneitzel}/rmg/server/ssrf/rmi/LocalhostJmxConnector.java | 0 .../tneitzel}/rmg/server/ssrf/rmi/LocalhostSocketFactory.java | 0 .../src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/utils/Logger.java | 0 src/{de/qtc => eu/tneitzel}/rmg/Starter.java | 0 src/{de/qtc => eu/tneitzel}/rmg/endpoints/KnownEndpoint.java | 0 .../qtc => eu/tneitzel}/rmg/endpoints/KnownEndpointHolder.java | 0 src/{de/qtc => eu/tneitzel}/rmg/endpoints/Vulnerability.java | 0 .../tneitzel}/rmg/exceptions/MalformedPluginException.java | 0 src/{de/qtc => eu/tneitzel}/rmg/exceptions/SSRFException.java | 0 .../tneitzel}/rmg/exceptions/UnexpectedCharacterException.java | 0 src/{de/qtc => eu/tneitzel}/rmg/internal/ArgumentHandler.java | 0 src/{de/qtc => eu/tneitzel}/rmg/internal/CodebaseCollector.java | 0 src/{de/qtc => eu/tneitzel}/rmg/internal/ExceptionHandler.java | 0 src/{de/qtc => eu/tneitzel}/rmg/internal/MethodArguments.java | 0 src/{de/qtc => eu/tneitzel}/rmg/internal/MethodCandidate.java | 0 src/{de/qtc => eu/tneitzel}/rmg/internal/Pair.java | 0 src/{de/qtc => eu/tneitzel}/rmg/internal/RMGOption.java | 0 src/{de/qtc => eu/tneitzel}/rmg/internal/RMGOptionGroup.java | 0 src/{de/qtc => eu/tneitzel}/rmg/internal/RMIComponent.java | 0 src/{de/qtc => eu/tneitzel}/rmg/io/DevNullOutputStream.java | 0 src/{de/qtc => eu/tneitzel}/rmg/io/Formatter.java | 0 src/{de/qtc => eu/tneitzel}/rmg/io/Logger.java | 0 src/{de/qtc => eu/tneitzel}/rmg/io/MaliciousOutputStream.java | 0 src/{de/qtc => eu/tneitzel}/rmg/io/RawObjectInputStream.java | 0 src/{de/qtc => eu/tneitzel}/rmg/io/RawObjectOutputStream.java | 0 src/{de/qtc => eu/tneitzel}/rmg/io/SampleWriter.java | 0 src/{de/qtc => eu/tneitzel}/rmg/io/SingleOpOutputStream.java | 0 src/{de/qtc => eu/tneitzel}/rmg/io/WordlistHandler.java | 0 src/{de/qtc => eu/tneitzel}/rmg/networking/DGCClientSocket.java | 0 .../tneitzel}/rmg/networking/DGCClientSocketFactory.java | 0 .../tneitzel}/rmg/networking/DGCClientSslSocketFactory.java | 0 .../qtc => eu/tneitzel}/rmg/networking/DummySocketFactory.java | 0 src/{de/qtc => eu/tneitzel}/rmg/networking/DummyTrustManager.java | 0 .../qtc => eu/tneitzel}/rmg/networking/LimitedSocketFactory.java | 0 .../qtc => eu/tneitzel}/rmg/networking/LoopbackSocketFactory.java | 0 .../tneitzel}/rmg/networking/LoopbackSslSocketFactory.java | 0 src/{de/qtc => eu/tneitzel}/rmg/networking/RMIEndpoint.java | 0 .../qtc => eu/tneitzel}/rmg/networking/RMIRegistryEndpoint.java | 0 .../qtc => eu/tneitzel}/rmg/networking/SSRFResponseSocket.java | 0 .../tneitzel}/rmg/networking/SSRFResponseSocketFactory.java | 0 src/{de/qtc => eu/tneitzel}/rmg/networking/SSRFSocket.java | 0 src/{de/qtc => eu/tneitzel}/rmg/networking/SSRFSocketFactory.java | 0 .../qtc => eu/tneitzel}/rmg/networking/TimeoutSocketFactory.java | 0 .../qtc => eu/tneitzel}/rmg/networking/TrustAllSocketFactory.java | 0 src/{de/qtc => eu/tneitzel}/rmg/operations/ActivationClient.java | 0 src/{de/qtc => eu/tneitzel}/rmg/operations/DGCClient.java | 0 src/{de/qtc => eu/tneitzel}/rmg/operations/Dispatcher.java | 0 src/{de/qtc => eu/tneitzel}/rmg/operations/MethodGuesser.java | 0 src/{de/qtc => eu/tneitzel}/rmg/operations/Operation.java | 0 src/{de/qtc => eu/tneitzel}/rmg/operations/PortScanner.java | 0 src/{de/qtc => eu/tneitzel}/rmg/operations/RegistryClient.java | 0 .../qtc => eu/tneitzel}/rmg/operations/RemoteObjectClient.java | 0 src/{de/qtc => eu/tneitzel}/rmg/operations/ScanAction.java | 0 src/{de/qtc => eu/tneitzel}/rmg/plugin/DefaultProvider.java | 0 src/{de/qtc => eu/tneitzel}/rmg/plugin/GenericPrint.java | 0 src/{de/qtc => eu/tneitzel}/rmg/plugin/IArgumentProvider.java | 0 src/{de/qtc => eu/tneitzel}/rmg/plugin/IPayloadProvider.java | 0 src/{de/qtc => eu/tneitzel}/rmg/plugin/IResponseHandler.java | 0 .../qtc => eu/tneitzel}/rmg/plugin/ISocketFactoryProvider.java | 0 src/{de/qtc => eu/tneitzel}/rmg/plugin/PluginSystem.java | 0 src/{de/qtc => eu/tneitzel}/rmg/plugin/ReturnValueProvider.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/ActivatableWrapper.java | 0 .../qtc => eu/tneitzel}/rmg/utils/DefinitelyNonExistingClass.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/EmptyWrapper.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/ProgressBar.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/RMGUtils.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/RemoteInvocationHolder.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/RemoteObjectWrapper.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/RogueJMX.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/Security.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/SpringRemotingWrapper.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/UnicastWrapper.java | 0 src/{de/qtc => eu/tneitzel}/rmg/utils/YsoIntegration.java | 0 103 files changed, 0 insertions(+), 0 deletions(-) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ExampleServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/activation/ActivationServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/activation/ActivationService.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/activation/ActivationService2.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/activation/IActivationService.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/activation/IActivationService2.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/factory/CustomSocketFactory.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/factory/CustomSocketFactoryServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/interfaces/IPlainServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/interfaces/ISecureServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/interfaces/ISslServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/legacy/LegacyServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/legacy/LegacyService.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/legacy/LegacyServiceImpl.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/legacy/StringContainer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/operations/PlainServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/operations/SecureServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/operations/SslServer.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/utils/CodebaseLogger.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/utils/Logger.java (100%) rename docker/example-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/utils/Utils.java (100%) rename docker/spring-remoting/resources/server/src/main/java/{de/qtc => eu/tneitzel}/rmg/springremoting/ServerOperations.java (100%) rename docker/spring-remoting/resources/server/src/main/java/{de/qtc => eu/tneitzel}/rmg/springremoting/SpringRemotingService.java (100%) rename docker/spring-remoting/resources/server/src/main/java/{de/qtc => eu/tneitzel}/rmg/springremoting/Starter.java (100%) rename docker/ssrf-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/Starter.java (100%) rename docker/ssrf-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/http/JarHandler.java (100%) rename docker/ssrf-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/http/SSRFHandler.java (100%) rename docker/ssrf-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/http/SSRFServer.java (100%) rename docker/ssrf-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/rmi/FileManager.java (100%) rename docker/ssrf-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/rmi/IFileManager.java (100%) rename docker/ssrf-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/rmi/LocalhostJmxConnector.java (100%) rename docker/ssrf-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/rmi/LocalhostSocketFactory.java (100%) rename docker/ssrf-server/resources/server/src/{de/qtc => eu/tneitzel}/rmg/server/ssrf/utils/Logger.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/Starter.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/endpoints/KnownEndpoint.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/endpoints/KnownEndpointHolder.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/endpoints/Vulnerability.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/exceptions/MalformedPluginException.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/exceptions/SSRFException.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/exceptions/UnexpectedCharacterException.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/internal/ArgumentHandler.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/internal/CodebaseCollector.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/internal/ExceptionHandler.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/internal/MethodArguments.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/internal/MethodCandidate.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/internal/Pair.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/internal/RMGOption.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/internal/RMGOptionGroup.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/internal/RMIComponent.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/io/DevNullOutputStream.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/io/Formatter.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/io/Logger.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/io/MaliciousOutputStream.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/io/RawObjectInputStream.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/io/RawObjectOutputStream.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/io/SampleWriter.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/io/SingleOpOutputStream.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/io/WordlistHandler.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/DGCClientSocket.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/DGCClientSocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/DGCClientSslSocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/DummySocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/DummyTrustManager.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/LimitedSocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/LoopbackSocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/LoopbackSslSocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/RMIEndpoint.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/RMIRegistryEndpoint.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/SSRFResponseSocket.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/SSRFResponseSocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/SSRFSocket.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/SSRFSocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/TimeoutSocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/networking/TrustAllSocketFactory.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/operations/ActivationClient.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/operations/DGCClient.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/operations/Dispatcher.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/operations/MethodGuesser.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/operations/Operation.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/operations/PortScanner.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/operations/RegistryClient.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/operations/RemoteObjectClient.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/operations/ScanAction.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/plugin/DefaultProvider.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/plugin/GenericPrint.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/plugin/IArgumentProvider.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/plugin/IPayloadProvider.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/plugin/IResponseHandler.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/plugin/ISocketFactoryProvider.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/plugin/PluginSystem.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/plugin/ReturnValueProvider.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/ActivatableWrapper.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/DefinitelyNonExistingClass.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/EmptyWrapper.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/ProgressBar.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/RMGUtils.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/RemoteInvocationHolder.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/RemoteObjectWrapper.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/RogueJMX.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/Security.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/SpringRemotingWrapper.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/UnicastWrapper.java (100%) rename src/{de/qtc => eu/tneitzel}/rmg/utils/YsoIntegration.java (100%) diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/ExampleServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/ExampleServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/ExampleServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/ActivationServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/ActivationServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/ActivationService.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/ActivationService.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/ActivationService2.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/activation/ActivationService2.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/ActivationService2.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/IActivationService.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/IActivationService.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/IActivationService2.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/activation/IActivationService2.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/activation/IActivationService2.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/factory/CustomSocketFactory.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactory.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/factory/CustomSocketFactory.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/factory/CustomSocketFactoryServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/factory/CustomSocketFactoryServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/factory/CustomSocketFactoryServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/IPlainServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/interfaces/IPlainServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/IPlainServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/interfaces/IPlainServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISecureServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/interfaces/ISecureServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISecureServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/interfaces/ISecureServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISslServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/interfaces/ISslServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/interfaces/ISslServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/interfaces/ISslServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/legacy/LegacyServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/legacy/LegacyServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyService.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/legacy/LegacyService.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyService.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/legacy/LegacyService.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServiceImpl.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/legacy/LegacyServiceImpl.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/LegacyServiceImpl.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/legacy/LegacyServiceImpl.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/StringContainer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/legacy/StringContainer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/legacy/StringContainer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/legacy/StringContainer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/PlainServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/operations/PlainServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/operations/PlainServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/operations/PlainServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SecureServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/operations/SecureServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SecureServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/operations/SecureServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SslServer.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/operations/SslServer.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/operations/SslServer.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/operations/SslServer.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/CodebaseLogger.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/utils/CodebaseLogger.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/utils/CodebaseLogger.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/utils/CodebaseLogger.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Logger.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/utils/Logger.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Logger.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/utils/Logger.java diff --git a/docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java b/docker/example-server/resources/server/src/eu/tneitzel/rmg/server/utils/Utils.java similarity index 100% rename from docker/example-server/resources/server/src/de/qtc/rmg/server/utils/Utils.java rename to docker/example-server/resources/server/src/eu/tneitzel/rmg/server/utils/Utils.java diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java b/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/ServerOperations.java similarity index 100% rename from docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/ServerOperations.java rename to docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/ServerOperations.java diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java b/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/SpringRemotingService.java similarity index 100% rename from docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/SpringRemotingService.java rename to docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/SpringRemotingService.java diff --git a/docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java b/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/Starter.java similarity index 100% rename from docker/spring-remoting/resources/server/src/main/java/de/qtc/rmg/springremoting/Starter.java rename to docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/Starter.java diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/Starter.java b/docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/Starter.java similarity index 100% rename from docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/Starter.java rename to docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/Starter.java diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/JarHandler.java b/docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/http/JarHandler.java similarity index 100% rename from docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/JarHandler.java rename to docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/http/JarHandler.java diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFHandler.java b/docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/http/SSRFHandler.java similarity index 100% rename from docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFHandler.java rename to docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/http/SSRFHandler.java diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFServer.java b/docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/http/SSRFServer.java similarity index 100% rename from docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/http/SSRFServer.java rename to docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/http/SSRFServer.java diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/FileManager.java b/docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/rmi/FileManager.java similarity index 100% rename from docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/FileManager.java rename to docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/rmi/FileManager.java diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/IFileManager.java b/docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/rmi/IFileManager.java similarity index 100% rename from docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/IFileManager.java rename to docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/rmi/IFileManager.java diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostJmxConnector.java b/docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/rmi/LocalhostJmxConnector.java similarity index 100% rename from docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostJmxConnector.java rename to docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/rmi/LocalhostJmxConnector.java diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostSocketFactory.java b/docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/rmi/LocalhostSocketFactory.java similarity index 100% rename from docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/rmi/LocalhostSocketFactory.java rename to docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/rmi/LocalhostSocketFactory.java diff --git a/docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/utils/Logger.java b/docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/utils/Logger.java similarity index 100% rename from docker/ssrf-server/resources/server/src/de/qtc/rmg/server/ssrf/utils/Logger.java rename to docker/ssrf-server/resources/server/src/eu/tneitzel/rmg/server/ssrf/utils/Logger.java diff --git a/src/de/qtc/rmg/Starter.java b/src/eu/tneitzel/rmg/Starter.java similarity index 100% rename from src/de/qtc/rmg/Starter.java rename to src/eu/tneitzel/rmg/Starter.java diff --git a/src/de/qtc/rmg/endpoints/KnownEndpoint.java b/src/eu/tneitzel/rmg/endpoints/KnownEndpoint.java similarity index 100% rename from src/de/qtc/rmg/endpoints/KnownEndpoint.java rename to src/eu/tneitzel/rmg/endpoints/KnownEndpoint.java diff --git a/src/de/qtc/rmg/endpoints/KnownEndpointHolder.java b/src/eu/tneitzel/rmg/endpoints/KnownEndpointHolder.java similarity index 100% rename from src/de/qtc/rmg/endpoints/KnownEndpointHolder.java rename to src/eu/tneitzel/rmg/endpoints/KnownEndpointHolder.java diff --git a/src/de/qtc/rmg/endpoints/Vulnerability.java b/src/eu/tneitzel/rmg/endpoints/Vulnerability.java similarity index 100% rename from src/de/qtc/rmg/endpoints/Vulnerability.java rename to src/eu/tneitzel/rmg/endpoints/Vulnerability.java diff --git a/src/de/qtc/rmg/exceptions/MalformedPluginException.java b/src/eu/tneitzel/rmg/exceptions/MalformedPluginException.java similarity index 100% rename from src/de/qtc/rmg/exceptions/MalformedPluginException.java rename to src/eu/tneitzel/rmg/exceptions/MalformedPluginException.java diff --git a/src/de/qtc/rmg/exceptions/SSRFException.java b/src/eu/tneitzel/rmg/exceptions/SSRFException.java similarity index 100% rename from src/de/qtc/rmg/exceptions/SSRFException.java rename to src/eu/tneitzel/rmg/exceptions/SSRFException.java diff --git a/src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java b/src/eu/tneitzel/rmg/exceptions/UnexpectedCharacterException.java similarity index 100% rename from src/de/qtc/rmg/exceptions/UnexpectedCharacterException.java rename to src/eu/tneitzel/rmg/exceptions/UnexpectedCharacterException.java diff --git a/src/de/qtc/rmg/internal/ArgumentHandler.java b/src/eu/tneitzel/rmg/internal/ArgumentHandler.java similarity index 100% rename from src/de/qtc/rmg/internal/ArgumentHandler.java rename to src/eu/tneitzel/rmg/internal/ArgumentHandler.java diff --git a/src/de/qtc/rmg/internal/CodebaseCollector.java b/src/eu/tneitzel/rmg/internal/CodebaseCollector.java similarity index 100% rename from src/de/qtc/rmg/internal/CodebaseCollector.java rename to src/eu/tneitzel/rmg/internal/CodebaseCollector.java diff --git a/src/de/qtc/rmg/internal/ExceptionHandler.java b/src/eu/tneitzel/rmg/internal/ExceptionHandler.java similarity index 100% rename from src/de/qtc/rmg/internal/ExceptionHandler.java rename to src/eu/tneitzel/rmg/internal/ExceptionHandler.java diff --git a/src/de/qtc/rmg/internal/MethodArguments.java b/src/eu/tneitzel/rmg/internal/MethodArguments.java similarity index 100% rename from src/de/qtc/rmg/internal/MethodArguments.java rename to src/eu/tneitzel/rmg/internal/MethodArguments.java diff --git a/src/de/qtc/rmg/internal/MethodCandidate.java b/src/eu/tneitzel/rmg/internal/MethodCandidate.java similarity index 100% rename from src/de/qtc/rmg/internal/MethodCandidate.java rename to src/eu/tneitzel/rmg/internal/MethodCandidate.java diff --git a/src/de/qtc/rmg/internal/Pair.java b/src/eu/tneitzel/rmg/internal/Pair.java similarity index 100% rename from src/de/qtc/rmg/internal/Pair.java rename to src/eu/tneitzel/rmg/internal/Pair.java diff --git a/src/de/qtc/rmg/internal/RMGOption.java b/src/eu/tneitzel/rmg/internal/RMGOption.java similarity index 100% rename from src/de/qtc/rmg/internal/RMGOption.java rename to src/eu/tneitzel/rmg/internal/RMGOption.java diff --git a/src/de/qtc/rmg/internal/RMGOptionGroup.java b/src/eu/tneitzel/rmg/internal/RMGOptionGroup.java similarity index 100% rename from src/de/qtc/rmg/internal/RMGOptionGroup.java rename to src/eu/tneitzel/rmg/internal/RMGOptionGroup.java diff --git a/src/de/qtc/rmg/internal/RMIComponent.java b/src/eu/tneitzel/rmg/internal/RMIComponent.java similarity index 100% rename from src/de/qtc/rmg/internal/RMIComponent.java rename to src/eu/tneitzel/rmg/internal/RMIComponent.java diff --git a/src/de/qtc/rmg/io/DevNullOutputStream.java b/src/eu/tneitzel/rmg/io/DevNullOutputStream.java similarity index 100% rename from src/de/qtc/rmg/io/DevNullOutputStream.java rename to src/eu/tneitzel/rmg/io/DevNullOutputStream.java diff --git a/src/de/qtc/rmg/io/Formatter.java b/src/eu/tneitzel/rmg/io/Formatter.java similarity index 100% rename from src/de/qtc/rmg/io/Formatter.java rename to src/eu/tneitzel/rmg/io/Formatter.java diff --git a/src/de/qtc/rmg/io/Logger.java b/src/eu/tneitzel/rmg/io/Logger.java similarity index 100% rename from src/de/qtc/rmg/io/Logger.java rename to src/eu/tneitzel/rmg/io/Logger.java diff --git a/src/de/qtc/rmg/io/MaliciousOutputStream.java b/src/eu/tneitzel/rmg/io/MaliciousOutputStream.java similarity index 100% rename from src/de/qtc/rmg/io/MaliciousOutputStream.java rename to src/eu/tneitzel/rmg/io/MaliciousOutputStream.java diff --git a/src/de/qtc/rmg/io/RawObjectInputStream.java b/src/eu/tneitzel/rmg/io/RawObjectInputStream.java similarity index 100% rename from src/de/qtc/rmg/io/RawObjectInputStream.java rename to src/eu/tneitzel/rmg/io/RawObjectInputStream.java diff --git a/src/de/qtc/rmg/io/RawObjectOutputStream.java b/src/eu/tneitzel/rmg/io/RawObjectOutputStream.java similarity index 100% rename from src/de/qtc/rmg/io/RawObjectOutputStream.java rename to src/eu/tneitzel/rmg/io/RawObjectOutputStream.java diff --git a/src/de/qtc/rmg/io/SampleWriter.java b/src/eu/tneitzel/rmg/io/SampleWriter.java similarity index 100% rename from src/de/qtc/rmg/io/SampleWriter.java rename to src/eu/tneitzel/rmg/io/SampleWriter.java diff --git a/src/de/qtc/rmg/io/SingleOpOutputStream.java b/src/eu/tneitzel/rmg/io/SingleOpOutputStream.java similarity index 100% rename from src/de/qtc/rmg/io/SingleOpOutputStream.java rename to src/eu/tneitzel/rmg/io/SingleOpOutputStream.java diff --git a/src/de/qtc/rmg/io/WordlistHandler.java b/src/eu/tneitzel/rmg/io/WordlistHandler.java similarity index 100% rename from src/de/qtc/rmg/io/WordlistHandler.java rename to src/eu/tneitzel/rmg/io/WordlistHandler.java diff --git a/src/de/qtc/rmg/networking/DGCClientSocket.java b/src/eu/tneitzel/rmg/networking/DGCClientSocket.java similarity index 100% rename from src/de/qtc/rmg/networking/DGCClientSocket.java rename to src/eu/tneitzel/rmg/networking/DGCClientSocket.java diff --git a/src/de/qtc/rmg/networking/DGCClientSocketFactory.java b/src/eu/tneitzel/rmg/networking/DGCClientSocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/DGCClientSocketFactory.java rename to src/eu/tneitzel/rmg/networking/DGCClientSocketFactory.java diff --git a/src/de/qtc/rmg/networking/DGCClientSslSocketFactory.java b/src/eu/tneitzel/rmg/networking/DGCClientSslSocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/DGCClientSslSocketFactory.java rename to src/eu/tneitzel/rmg/networking/DGCClientSslSocketFactory.java diff --git a/src/de/qtc/rmg/networking/DummySocketFactory.java b/src/eu/tneitzel/rmg/networking/DummySocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/DummySocketFactory.java rename to src/eu/tneitzel/rmg/networking/DummySocketFactory.java diff --git a/src/de/qtc/rmg/networking/DummyTrustManager.java b/src/eu/tneitzel/rmg/networking/DummyTrustManager.java similarity index 100% rename from src/de/qtc/rmg/networking/DummyTrustManager.java rename to src/eu/tneitzel/rmg/networking/DummyTrustManager.java diff --git a/src/de/qtc/rmg/networking/LimitedSocketFactory.java b/src/eu/tneitzel/rmg/networking/LimitedSocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/LimitedSocketFactory.java rename to src/eu/tneitzel/rmg/networking/LimitedSocketFactory.java diff --git a/src/de/qtc/rmg/networking/LoopbackSocketFactory.java b/src/eu/tneitzel/rmg/networking/LoopbackSocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/LoopbackSocketFactory.java rename to src/eu/tneitzel/rmg/networking/LoopbackSocketFactory.java diff --git a/src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java b/src/eu/tneitzel/rmg/networking/LoopbackSslSocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/LoopbackSslSocketFactory.java rename to src/eu/tneitzel/rmg/networking/LoopbackSslSocketFactory.java diff --git a/src/de/qtc/rmg/networking/RMIEndpoint.java b/src/eu/tneitzel/rmg/networking/RMIEndpoint.java similarity index 100% rename from src/de/qtc/rmg/networking/RMIEndpoint.java rename to src/eu/tneitzel/rmg/networking/RMIEndpoint.java diff --git a/src/de/qtc/rmg/networking/RMIRegistryEndpoint.java b/src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java similarity index 100% rename from src/de/qtc/rmg/networking/RMIRegistryEndpoint.java rename to src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java diff --git a/src/de/qtc/rmg/networking/SSRFResponseSocket.java b/src/eu/tneitzel/rmg/networking/SSRFResponseSocket.java similarity index 100% rename from src/de/qtc/rmg/networking/SSRFResponseSocket.java rename to src/eu/tneitzel/rmg/networking/SSRFResponseSocket.java diff --git a/src/de/qtc/rmg/networking/SSRFResponseSocketFactory.java b/src/eu/tneitzel/rmg/networking/SSRFResponseSocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/SSRFResponseSocketFactory.java rename to src/eu/tneitzel/rmg/networking/SSRFResponseSocketFactory.java diff --git a/src/de/qtc/rmg/networking/SSRFSocket.java b/src/eu/tneitzel/rmg/networking/SSRFSocket.java similarity index 100% rename from src/de/qtc/rmg/networking/SSRFSocket.java rename to src/eu/tneitzel/rmg/networking/SSRFSocket.java diff --git a/src/de/qtc/rmg/networking/SSRFSocketFactory.java b/src/eu/tneitzel/rmg/networking/SSRFSocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/SSRFSocketFactory.java rename to src/eu/tneitzel/rmg/networking/SSRFSocketFactory.java diff --git a/src/de/qtc/rmg/networking/TimeoutSocketFactory.java b/src/eu/tneitzel/rmg/networking/TimeoutSocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/TimeoutSocketFactory.java rename to src/eu/tneitzel/rmg/networking/TimeoutSocketFactory.java diff --git a/src/de/qtc/rmg/networking/TrustAllSocketFactory.java b/src/eu/tneitzel/rmg/networking/TrustAllSocketFactory.java similarity index 100% rename from src/de/qtc/rmg/networking/TrustAllSocketFactory.java rename to src/eu/tneitzel/rmg/networking/TrustAllSocketFactory.java diff --git a/src/de/qtc/rmg/operations/ActivationClient.java b/src/eu/tneitzel/rmg/operations/ActivationClient.java similarity index 100% rename from src/de/qtc/rmg/operations/ActivationClient.java rename to src/eu/tneitzel/rmg/operations/ActivationClient.java diff --git a/src/de/qtc/rmg/operations/DGCClient.java b/src/eu/tneitzel/rmg/operations/DGCClient.java similarity index 100% rename from src/de/qtc/rmg/operations/DGCClient.java rename to src/eu/tneitzel/rmg/operations/DGCClient.java diff --git a/src/de/qtc/rmg/operations/Dispatcher.java b/src/eu/tneitzel/rmg/operations/Dispatcher.java similarity index 100% rename from src/de/qtc/rmg/operations/Dispatcher.java rename to src/eu/tneitzel/rmg/operations/Dispatcher.java diff --git a/src/de/qtc/rmg/operations/MethodGuesser.java b/src/eu/tneitzel/rmg/operations/MethodGuesser.java similarity index 100% rename from src/de/qtc/rmg/operations/MethodGuesser.java rename to src/eu/tneitzel/rmg/operations/MethodGuesser.java diff --git a/src/de/qtc/rmg/operations/Operation.java b/src/eu/tneitzel/rmg/operations/Operation.java similarity index 100% rename from src/de/qtc/rmg/operations/Operation.java rename to src/eu/tneitzel/rmg/operations/Operation.java diff --git a/src/de/qtc/rmg/operations/PortScanner.java b/src/eu/tneitzel/rmg/operations/PortScanner.java similarity index 100% rename from src/de/qtc/rmg/operations/PortScanner.java rename to src/eu/tneitzel/rmg/operations/PortScanner.java diff --git a/src/de/qtc/rmg/operations/RegistryClient.java b/src/eu/tneitzel/rmg/operations/RegistryClient.java similarity index 100% rename from src/de/qtc/rmg/operations/RegistryClient.java rename to src/eu/tneitzel/rmg/operations/RegistryClient.java diff --git a/src/de/qtc/rmg/operations/RemoteObjectClient.java b/src/eu/tneitzel/rmg/operations/RemoteObjectClient.java similarity index 100% rename from src/de/qtc/rmg/operations/RemoteObjectClient.java rename to src/eu/tneitzel/rmg/operations/RemoteObjectClient.java diff --git a/src/de/qtc/rmg/operations/ScanAction.java b/src/eu/tneitzel/rmg/operations/ScanAction.java similarity index 100% rename from src/de/qtc/rmg/operations/ScanAction.java rename to src/eu/tneitzel/rmg/operations/ScanAction.java diff --git a/src/de/qtc/rmg/plugin/DefaultProvider.java b/src/eu/tneitzel/rmg/plugin/DefaultProvider.java similarity index 100% rename from src/de/qtc/rmg/plugin/DefaultProvider.java rename to src/eu/tneitzel/rmg/plugin/DefaultProvider.java diff --git a/src/de/qtc/rmg/plugin/GenericPrint.java b/src/eu/tneitzel/rmg/plugin/GenericPrint.java similarity index 100% rename from src/de/qtc/rmg/plugin/GenericPrint.java rename to src/eu/tneitzel/rmg/plugin/GenericPrint.java diff --git a/src/de/qtc/rmg/plugin/IArgumentProvider.java b/src/eu/tneitzel/rmg/plugin/IArgumentProvider.java similarity index 100% rename from src/de/qtc/rmg/plugin/IArgumentProvider.java rename to src/eu/tneitzel/rmg/plugin/IArgumentProvider.java diff --git a/src/de/qtc/rmg/plugin/IPayloadProvider.java b/src/eu/tneitzel/rmg/plugin/IPayloadProvider.java similarity index 100% rename from src/de/qtc/rmg/plugin/IPayloadProvider.java rename to src/eu/tneitzel/rmg/plugin/IPayloadProvider.java diff --git a/src/de/qtc/rmg/plugin/IResponseHandler.java b/src/eu/tneitzel/rmg/plugin/IResponseHandler.java similarity index 100% rename from src/de/qtc/rmg/plugin/IResponseHandler.java rename to src/eu/tneitzel/rmg/plugin/IResponseHandler.java diff --git a/src/de/qtc/rmg/plugin/ISocketFactoryProvider.java b/src/eu/tneitzel/rmg/plugin/ISocketFactoryProvider.java similarity index 100% rename from src/de/qtc/rmg/plugin/ISocketFactoryProvider.java rename to src/eu/tneitzel/rmg/plugin/ISocketFactoryProvider.java diff --git a/src/de/qtc/rmg/plugin/PluginSystem.java b/src/eu/tneitzel/rmg/plugin/PluginSystem.java similarity index 100% rename from src/de/qtc/rmg/plugin/PluginSystem.java rename to src/eu/tneitzel/rmg/plugin/PluginSystem.java diff --git a/src/de/qtc/rmg/plugin/ReturnValueProvider.java b/src/eu/tneitzel/rmg/plugin/ReturnValueProvider.java similarity index 100% rename from src/de/qtc/rmg/plugin/ReturnValueProvider.java rename to src/eu/tneitzel/rmg/plugin/ReturnValueProvider.java diff --git a/src/de/qtc/rmg/utils/ActivatableWrapper.java b/src/eu/tneitzel/rmg/utils/ActivatableWrapper.java similarity index 100% rename from src/de/qtc/rmg/utils/ActivatableWrapper.java rename to src/eu/tneitzel/rmg/utils/ActivatableWrapper.java diff --git a/src/de/qtc/rmg/utils/DefinitelyNonExistingClass.java b/src/eu/tneitzel/rmg/utils/DefinitelyNonExistingClass.java similarity index 100% rename from src/de/qtc/rmg/utils/DefinitelyNonExistingClass.java rename to src/eu/tneitzel/rmg/utils/DefinitelyNonExistingClass.java diff --git a/src/de/qtc/rmg/utils/EmptyWrapper.java b/src/eu/tneitzel/rmg/utils/EmptyWrapper.java similarity index 100% rename from src/de/qtc/rmg/utils/EmptyWrapper.java rename to src/eu/tneitzel/rmg/utils/EmptyWrapper.java diff --git a/src/de/qtc/rmg/utils/ProgressBar.java b/src/eu/tneitzel/rmg/utils/ProgressBar.java similarity index 100% rename from src/de/qtc/rmg/utils/ProgressBar.java rename to src/eu/tneitzel/rmg/utils/ProgressBar.java diff --git a/src/de/qtc/rmg/utils/RMGUtils.java b/src/eu/tneitzel/rmg/utils/RMGUtils.java similarity index 100% rename from src/de/qtc/rmg/utils/RMGUtils.java rename to src/eu/tneitzel/rmg/utils/RMGUtils.java diff --git a/src/de/qtc/rmg/utils/RemoteInvocationHolder.java b/src/eu/tneitzel/rmg/utils/RemoteInvocationHolder.java similarity index 100% rename from src/de/qtc/rmg/utils/RemoteInvocationHolder.java rename to src/eu/tneitzel/rmg/utils/RemoteInvocationHolder.java diff --git a/src/de/qtc/rmg/utils/RemoteObjectWrapper.java b/src/eu/tneitzel/rmg/utils/RemoteObjectWrapper.java similarity index 100% rename from src/de/qtc/rmg/utils/RemoteObjectWrapper.java rename to src/eu/tneitzel/rmg/utils/RemoteObjectWrapper.java diff --git a/src/de/qtc/rmg/utils/RogueJMX.java b/src/eu/tneitzel/rmg/utils/RogueJMX.java similarity index 100% rename from src/de/qtc/rmg/utils/RogueJMX.java rename to src/eu/tneitzel/rmg/utils/RogueJMX.java diff --git a/src/de/qtc/rmg/utils/Security.java b/src/eu/tneitzel/rmg/utils/Security.java similarity index 100% rename from src/de/qtc/rmg/utils/Security.java rename to src/eu/tneitzel/rmg/utils/Security.java diff --git a/src/de/qtc/rmg/utils/SpringRemotingWrapper.java b/src/eu/tneitzel/rmg/utils/SpringRemotingWrapper.java similarity index 100% rename from src/de/qtc/rmg/utils/SpringRemotingWrapper.java rename to src/eu/tneitzel/rmg/utils/SpringRemotingWrapper.java diff --git a/src/de/qtc/rmg/utils/UnicastWrapper.java b/src/eu/tneitzel/rmg/utils/UnicastWrapper.java similarity index 100% rename from src/de/qtc/rmg/utils/UnicastWrapper.java rename to src/eu/tneitzel/rmg/utils/UnicastWrapper.java diff --git a/src/de/qtc/rmg/utils/YsoIntegration.java b/src/eu/tneitzel/rmg/utils/YsoIntegration.java similarity index 100% rename from src/de/qtc/rmg/utils/YsoIntegration.java rename to src/eu/tneitzel/rmg/utils/YsoIntegration.java From 5fc7b0119f28170f0ce37b6d1f4d2a051af74dff Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 08:05:43 +0100 Subject: [PATCH 29/60] Update test cases --- tests/jdk8/tests/dgc.yml | 2 +- tests/shared/bind.yml | 8 +++---- tests/shared/codebase.yml | 2 +- tests/utils/PluginTest.java | 47 +++++++++++++++++++++++-------------- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/tests/jdk8/tests/dgc.yml b/tests/jdk8/tests/dgc.yml index 4c5df21..e81e475 100644 --- a/tests/jdk8/tests/dgc.yml +++ b/tests/jdk8/tests/dgc.yml @@ -38,7 +38,7 @@ tests: - contains: values: - 'Caught unexpected AccessControlException during deserialization attack' - - 'The servers SecurityManager may refused the operation.' + - "The server's SecurityManager may refused the operation." - title: Gadget Call (SSL) diff --git a/tests/shared/bind.yml b/tests/shared/bind.yml index 8d93039..c63b2f5 100644 --- a/tests/shared/bind.yml +++ b/tests/shared/bind.yml @@ -57,7 +57,7 @@ tests: - contains: values: - Registry rejected bind call - - Localhost bypass was used but failed + - Localhost bypass was used, but failed - title: Bind Call (Activation System localhost bypass) @@ -79,7 +79,7 @@ tests: - contains: values: - Registry rejected bind call - - Localhost bypass was used but failed + - Localhost bypass was used, but failed - title: Rebind Call @@ -122,7 +122,7 @@ tests: ignore_case: True values: - Registry rejected rebind call - - Localhost bypass was used but failed + - Localhost bypass was used, but failed - title: Unbind Call @@ -163,4 +163,4 @@ tests: ignore_case: True values: - Registry rejected unbind call - - Localhost bypass was used but failed + - Localhost bypass was used, but failed diff --git a/tests/shared/codebase.yml b/tests/shared/codebase.yml index 63265fe..ec7c964 100644 --- a/tests/shared/codebase.yml +++ b/tests/shared/codebase.yml @@ -155,7 +155,7 @@ tests: - error: True - contains: values: - - 'The specified aciton requires one of the --component, --objid, --bound-name options' + - 'The specified action requires one of the --component, --objid, --bound-name options' - title: No Class Load diff --git a/tests/utils/PluginTest.java b/tests/utils/PluginTest.java index 374fd49..825f828 100644 --- a/tests/utils/PluginTest.java +++ b/tests/utils/PluginTest.java @@ -9,60 +9,71 @@ import eu.tneitzel.rmg.plugin.IArgumentProvider; -public class PluginTest implements IResponseHandler, IPayloadProvider, IArgumentProvider { - +public class PluginTest implements IResponseHandler, IPayloadProvider, IArgumentProvider +{ private static DefaultProvider defProv = new DefaultProvider(); public void handleResponse(Object responseObject) { - if(responseObject instanceof Collection) { - - for(Object o: (Collection)responseObject) { + if (responseObject instanceof Collection) + { + for (Object o: (Collection)responseObject) + { System.out.println(o.toString()); } + } - } else if(responseObject instanceof Map) { - + else if (responseObject instanceof Map) + { Map map = (Map)responseObject; - for(Object o: map.keySet()) { + for (Object o: map.keySet()) + { System.out.print(o.toString()); System.out.println(" --> " + map.get(o).toString()); } + } - } else if(responseObject.getClass().isArray()) { - - for(Object o: (Object[])responseObject) { + else if (responseObject.getClass().isArray()) + { + for(Object o: (Object[])responseObject) + { System.out.println(o.toString()); } + } - } else { - + else + { System.out.println(responseObject.toString()); } } public Object[] getArgumentArray(String argumentString) { - if( argumentString.equals("login") ) { - + if (argumentString.equals("login")) + { HashMap credentials = new HashMap(); credentials.put("username", "admin"); credentials.put("password", "admin"); return new Object[]{credentials}; + } - } else { + else + { return defProv.getArgumentArray(argumentString); } } public Object getPayloadObject(Operation action, String name, String args) { - if( name.equals("custom") ) { + if (name.equals("custom")) + { return defProv.getPayloadObject(action, "CommonsCollections6", args); + } - } else { + else + { return defProv.getPayloadObject(action, name, args); } } From 399557f7d7dd5696148e27adc9e9ff248b72b463 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 08:09:27 +0100 Subject: [PATCH 30/60] Update dependencies --- pom.xml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index c3e6412..ad26527 100644 --- a/pom.xml +++ b/pom.xml @@ -1,14 +1,12 @@ - - + 4.0.0 eu.tneitzel.rmg remote-method-guesser remote-method-guesser jar - 4.4.1 + 5.0.0 Identify common misconfigurations on Java RMI endpoints @@ -18,7 +16,6 @@ - net.sourceforge.argparse4j argparse4j @@ -28,7 +25,7 @@ commons-io commons-io - 2.11.0 + 2.15.1 @@ -40,7 +37,7 @@ org.yaml snakeyaml - 1.33 + 2.2 @@ -48,11 +45,9 @@ spring-remoting 2.0.8 - - src From 524cbe14d6133580165b12e91d10219dfc497f57 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 08:16:57 +0100 Subject: [PATCH 31/60] Bump version number --- CHANGELOG.md | 9 ++++++++- docs/rmg/dynamic-socket-factories.md | 4 ++-- docs/rmg/inline-gadgets.md | 2 +- src/eu/tneitzel/rmg/internal/CodebaseCollector.java | 4 ++-- tests/tricot.yml | 2 +- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4790346..ee7704d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [4.5.0] - MMM DD, 2023 +## [5.0.0] - MMM DD, 2023 ### Added * Add support for dynamically created socket factory classes ([docs](/docs/rmg/dynamic-socket-factories.md)) +* Add support for method guessing on spring-remoting endpoints ([docs](/docs/rmg/spring-remoting.md)) + +### Changed + +* Changed the namespace of the project from `de.qtc` to `eu.tneitzel` +* Fix leak of local ysoserial path (e30f52c) +* The GenericPrint plugin is now included in *rmg* per default (b09e9a5) ## [4.4.1] - Jun 22, 2023 diff --git a/docs/rmg/dynamic-socket-factories.md b/docs/rmg/dynamic-socket-factories.md index d692a57..143828e 100644 --- a/docs/rmg/dynamic-socket-factories.md +++ b/docs/rmg/dynamic-socket-factories.md @@ -2,7 +2,7 @@ ---- -With version *v4.5.0* support for dynamically created socket factories +With version *v5.0.0* support for dynamically created socket factories were added to *remote-method-guesser*. This basically means the following: *RMI* servers can register a custom socket factory that has to be used @@ -22,7 +22,7 @@ classes often still rely on the default socket implementations. This means that at the end of the day, the socket factory still outputs a regular socket, as it can also be obtained from *Java's* default socket *APIs*. -From version *v4.5.0* on, *remote-method-guesser* attempts to detect +From version *v5.0.0* on, *remote-method-guesser* attempts to detect errors caused by missing socket factory classes. In these cases, *rmg* attempts to create the class dynamically. Since the actual implementation is unknown, the dynamically created socket factory is simply the default diff --git a/docs/rmg/inline-gadgets.md b/docs/rmg/inline-gadgets.md index d579065..0cbb3af 100644 --- a/docs/rmg/inline-gadgets.md +++ b/docs/rmg/inline-gadgets.md @@ -10,7 +10,7 @@ we mean gadgets that are passed e.g. as base64 encoded command line parameter. This would e.g. allow to use serialization based rmg actions without having the *ysoserial* even present. -For version *v4.5.0* of remote-method-guesser, *inline gadgets* were part of the +For version *v5.0.0* of remote-method-guesser, *inline gadgets* were part of the roadmap. However, as it turned out, our considerations on how to implement them were too naive and at the end, this feature was not implemented at all. In this document we want to write down some of the problems we encountered, how they could diff --git a/src/eu/tneitzel/rmg/internal/CodebaseCollector.java b/src/eu/tneitzel/rmg/internal/CodebaseCollector.java index 1015833..1c3c22b 100644 --- a/src/eu/tneitzel/rmg/internal/CodebaseCollector.java +++ b/src/eu/tneitzel/rmg/internal/CodebaseCollector.java @@ -49,7 +49,7 @@ * serialVersionUID. Since changing the serialVersionUID of an already existing class is not possible, we instead * create a new class where the full qualified class name is prefixed with an underscore. * - * From remote-method-guesser v4.5.0, this class has another purpose of handling custom socket factories. When the + * From remote-method-guesser v5.0.0, this class has another purpose of handling custom socket factories. When the * server exposes RMI objects with custom socket factory classes, this usually causes a ClassNotFound error, as * we do not have the associated implementations on the client side. In this case, remote-method-guesser now attempts * to create the socket factory class dynamically. Since the implementation is still unknown, it simply clones the @@ -191,7 +191,7 @@ public ClassLoader getClassLoader(String codebase) throws MalformedURLException * of rmg (which is the MaliciousOutputStream class) allows arbitrary objects and is therefore * more flexible. * - * Since version v4.5.0, this function always returns null instead of invoking the original loaders + * Since version v5.0.0, this function always returns null instead of invoking the original loaders * getClassAnnotation method. This was changed, as the original loaders getClassAnnotation method * leaked the local ysoserial path when using remote-method-guessers ysoserial integration. */ diff --git a/tests/tricot.yml b/tests/tricot.yml index de63a11..6768595 100644 --- a/tests/tricot.yml +++ b/tests/tricot.yml @@ -18,7 +18,7 @@ tester: ge: 1.12.0 variables: - rmg: rmg-4.4.1-jar-with-dependencies.jar + rmg: rmg-5.0.0-jar-with-dependencies.jar volume: /tmp/rmg-tricot-test/ volume-d: /rce/ codebase-class: CodebaseTest From 99ff07860cae8106bb125ea453e08b6d1bab2424 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 08:22:54 +0100 Subject: [PATCH 32/60] Fix snakeyaml constructor --- src/eu/tneitzel/rmg/endpoints/KnownEndpointHolder.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/eu/tneitzel/rmg/endpoints/KnownEndpointHolder.java b/src/eu/tneitzel/rmg/endpoints/KnownEndpointHolder.java index 4a61544..8aab142 100644 --- a/src/eu/tneitzel/rmg/endpoints/KnownEndpointHolder.java +++ b/src/eu/tneitzel/rmg/endpoints/KnownEndpointHolder.java @@ -3,6 +3,7 @@ import java.io.InputStream; import java.util.List; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; @@ -101,7 +102,12 @@ public static KnownEndpointHolder getHolder() { if (instance == null) { - Yaml yaml = new Yaml(new Constructor(KnownEndpointHolder.class)); + LoaderOptions options = new LoaderOptions(); + + options.setAllowDuplicateKeys(false); + options.setAllowRecursiveKeys(false); + + Yaml yaml = new Yaml(new Constructor(KnownEndpointHolder.class, options)); InputStream stream = KnownEndpoint.class.getResourceAsStream(resource); instance = yaml.load(stream); From 5d69627627dad941e3a931ef73585226b5b32e29 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 08:24:28 +0100 Subject: [PATCH 33/60] Small formatting changes --- docker/example-server/CHANGELOG.md | 6 +++--- src/eu/tneitzel/rmg/plugin/GenericPrint.java | 8 ++++---- src/eu/tneitzel/rmg/plugin/PluginSystem.java | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docker/example-server/CHANGELOG.md b/docker/example-server/CHANGELOG.md index 0c4430c..1f6ff59 100644 --- a/docker/example-server/CHANGELOG.md +++ b/docker/example-server/CHANGELOG.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [4.0] - Jan 19, 2023 +## v4.0 - Jan 19, 2023 ### Added @@ -19,14 +19,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Change server certificate -## [3.3] - May 08, 2022 +## v3.3 - May 08, 2022 ### Changed * Fix timestamp for log messages -## [3.2] - May 06, 2022 +## v3.2 - May 06, 2022 ### Changed diff --git a/src/eu/tneitzel/rmg/plugin/GenericPrint.java b/src/eu/tneitzel/rmg/plugin/GenericPrint.java index e13564f..8b4174a 100644 --- a/src/eu/tneitzel/rmg/plugin/GenericPrint.java +++ b/src/eu/tneitzel/rmg/plugin/GenericPrint.java @@ -21,7 +21,7 @@ * * From remote-method-guesser v5.0.0, GenericPrint is included per default and does not need * to be compiled separately. It can be enabled by using the --generic-print option. - * + * * @author Tobias Neitzel (@qtc_de) */ public class GenericPrint implements IResponseHandler @@ -119,13 +119,13 @@ public void handleArray(Object o) { int length = Array.getLength(o); objectArray = new Object[length]; - + for(int ctr = 0; ctr < length; ctr++) { objectArray[ctr] = Array.get(o, ctr); } } - + else { objectArray = (Object[])o; @@ -192,7 +192,7 @@ else if (objectWrapper instanceof ActivatableWrapper) Logger.eprintlnYellow("Unsupported object type."); } } - + catch (Exception e) { ExceptionHandler.unexpectedException(e, "constructing", "RemoteObjectWrapper", true); diff --git a/src/eu/tneitzel/rmg/plugin/PluginSystem.java b/src/eu/tneitzel/rmg/plugin/PluginSystem.java index 40f1baf..a40cf9e 100644 --- a/src/eu/tneitzel/rmg/plugin/PluginSystem.java +++ b/src/eu/tneitzel/rmg/plugin/PluginSystem.java @@ -52,9 +52,9 @@ public static void init(String pluginPath) if (RMGOption.GENERIC_PRINT.getBool()) { - responseHandler = new GenericPrint(); + responseHandler = new GenericPrint(); } - + if (pluginPath != null) { loadPlugin(pluginPath); @@ -99,7 +99,7 @@ private static void loadPlugin(String pluginPath) throw new MalformedPluginException(); } } - + catch (Exception e) { Logger.eprintlnMixedYellow("Caught", e.getClass().getName(), "while reading the Manifest of the specified plugin."); @@ -113,7 +113,7 @@ private static void loadPlugin(String pluginPath) Class pluginClass = Class.forName(pluginClassName, true, ucl); pluginInstance = pluginClass.newInstance(); } - + catch (Exception e) { Logger.eprintMixedYellow("Caught", e.getClass().getName(), "while reading plugin file "); @@ -127,19 +127,19 @@ private static void loadPlugin(String pluginPath) payloadProvider = (IPayloadProvider)pluginInstance; inUse = true; } - + if (pluginInstance instanceof IResponseHandler) { responseHandler = (IResponseHandler)pluginInstance; inUse = true; } - + if(pluginInstance instanceof IArgumentProvider) { argumentProvider = (IArgumentProvider)pluginInstance; inUse = true; } - + if(pluginInstance instanceof ISocketFactoryProvider) { socketFactoryProvider = (ISocketFactoryProvider)pluginInstance; From c17dbdc2859cf3f44351ca2a77a442b126b4a546 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 09:34:22 +0100 Subject: [PATCH 34/60] Update dockerfiles of example-server --- docker/example-server/CHANGELOG.md | 23 ++++++++++++++++--- docker/example-server/Dockerfile-jdk9 | 6 ++--- .../example-server/docker-compose-jdk11.yml | 2 +- docker/example-server/docker-compose-jdk8.yml | 2 +- docker/example-server/docker-compose-jdk9.yml | 2 +- .../resources/server/CHANGELOG.md | 19 --------------- 6 files changed, 25 insertions(+), 29 deletions(-) delete mode 100644 docker/example-server/resources/server/CHANGELOG.md diff --git a/docker/example-server/CHANGELOG.md b/docker/example-server/CHANGELOG.md index 1f6ff59..b935451 100644 --- a/docker/example-server/CHANGELOG.md +++ b/docker/example-server/CHANGELOG.md @@ -6,7 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v4.0 - Jan 19, 2023 +## v5.0.0 - Dec 10, 2023 + +### Added + +* Add `custom-socks` bound name to registry on port `9010` which uses a custom socket factory + +### Changed + +* Changed the servers namespace from `de.qtc` to `eu.tneitzel` + + +## v4.0.0 - Jan 19, 2023 ### Added @@ -19,15 +30,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Change server certificate -## v3.3 - May 08, 2022 +## v3.3.0 - May 08, 2022 ### Changed * Fix timestamp for log messages -## v3.2 - May 06, 2022 +## v3.2.0 - May 06, 2022 ### Changed * Add activation system on port 1098 + + +## v3.1.0 and before + +Changelog entries can be found within the global [CHANGELOG.md](/CHANGELOG.md) file +of remote-method-guesser. diff --git a/docker/example-server/Dockerfile-jdk9 b/docker/example-server/Dockerfile-jdk9 index b77c36d..954c146 100644 --- a/docker/example-server/Dockerfile-jdk9 +++ b/docker/example-server/Dockerfile-jdk9 @@ -9,11 +9,9 @@ RUN mvn clean package ########################################### ### Build Stage 2 ### ########################################### -FROM alpine:latest AS jdk-builder +FROM ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:4.0-jdk9 AS jdk-builder RUN set -ex \ - && apk add --no-cache openjdk9 \ - && /usr/lib/jvm/java-9-openjdk/bin/jlink --add-modules java.rmi,java.management.rmi,jdk.unsupported --verbose --strip-debug --compress 2 \ - --no-header-files --no-man-pages --module-path /usr/lib/jvm/java-9-openjdk/jmods/ --output /jdk + && mv /usr/lib/jvm/java-9-openjdk /jdk ########################################### ### Container Stage ### diff --git a/docker/example-server/docker-compose-jdk11.yml b/docker/example-server/docker-compose-jdk11.yml index 60d7595..1b2389b 100644 --- a/docker/example-server/docker-compose-jdk11.yml +++ b/docker/example-server/docker-compose-jdk11.yml @@ -2,7 +2,7 @@ version: '3.7' services: rmg: - image: ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:4.0-jdk11 + image: ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:5.0-jdk11 build: . environment: - > diff --git a/docker/example-server/docker-compose-jdk8.yml b/docker/example-server/docker-compose-jdk8.yml index 72ce467..a146f67 100644 --- a/docker/example-server/docker-compose-jdk8.yml +++ b/docker/example-server/docker-compose-jdk8.yml @@ -2,7 +2,7 @@ version: '3.7' services: rmg: - image: ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:4.0-jdk8 + image: ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:5.0-jdk8 build: . environment: - > diff --git a/docker/example-server/docker-compose-jdk9.yml b/docker/example-server/docker-compose-jdk9.yml index b0072e6..8231f8b 100644 --- a/docker/example-server/docker-compose-jdk9.yml +++ b/docker/example-server/docker-compose-jdk9.yml @@ -2,7 +2,7 @@ version: '3.7' services: rmg: - image: ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:4.0-jdk9 + image: ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:5.0-jdk9 build: . environment: - > diff --git a/docker/example-server/resources/server/CHANGELOG.md b/docker/example-server/resources/server/CHANGELOG.md deleted file mode 100644 index c7ffed1..0000000 --- a/docker/example-server/resources/server/CHANGELOG.md +++ /dev/null @@ -1,19 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - - -## v4.1.0 - Nov 12, 2023 - -### Added - -* Add an additional RemoteObject using a custom socket factory class - - -## v4.0.0 and before - -Changelog entries can be found within the global [CHANGELOG.md](/CHANGELOG.md) file -of remote-method-guesser. From 9a8dabc6fcd5a3f118bb1312f34a011e5a3f6f83 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 09:37:01 +0100 Subject: [PATCH 35/60] Update spring-remoting container --- docker/spring-remoting/CHANGELOG.md | 11 ++++ docker/spring-remoting/docker-compose.yml | 6 ++ .../rmg/springremoting/ServerOperations.java | 2 +- .../springremoting/SpringRemotingService.java | 66 +++++++++---------- 4 files changed, 51 insertions(+), 34 deletions(-) create mode 100644 docker/spring-remoting/CHANGELOG.md create mode 100644 docker/spring-remoting/docker-compose.yml diff --git a/docker/spring-remoting/CHANGELOG.md b/docker/spring-remoting/CHANGELOG.md new file mode 100644 index 0000000..d8dba1b --- /dev/null +++ b/docker/spring-remoting/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + +## v1.0.0 - Dec 10, 2023 + +Initial Release diff --git a/docker/spring-remoting/docker-compose.yml b/docker/spring-remoting/docker-compose.yml new file mode 100644 index 0000000..97a6fb1 --- /dev/null +++ b/docker/spring-remoting/docker-compose.yml @@ -0,0 +1,6 @@ +version: '3.7' + +services: + spring-remoting: + image: ghcr.io/qtc-de/remote-method-guesser/spring-remoting-server:1.0 + build: . diff --git a/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/ServerOperations.java b/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/ServerOperations.java index 3fa69bb..bb75a60 100644 --- a/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/ServerOperations.java +++ b/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/ServerOperations.java @@ -7,4 +7,4 @@ public interface ServerOperations String system(String cmd, String[] args); String upload(int size, int id, byte[] content); int math(int num1, int num2); -} \ No newline at end of file +} diff --git a/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/SpringRemotingService.java b/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/SpringRemotingService.java index 1f40b03..0a6a789 100644 --- a/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/SpringRemotingService.java +++ b/docker/spring-remoting/resources/server/src/main/java/eu/tneitzel/rmg/springremoting/SpringRemotingService.java @@ -12,36 +12,36 @@ @SuppressWarnings("deprecation") public class SpringRemotingService implements ServerOperations { - Logger logger = LoggerFactory.getLogger(SpringRemotingService.class); - - SpringRemotingService springRemotingService() - { - return new SpringRemotingService(); - } - - @Bean - RmiServiceExporter exporter(SpringRemotingService impl) - { - Class serverInterface = ServerOperations.class; - RmiServiceExporter exporter = new RmiServiceExporter(); - - exporter.setServiceInterface(serverInterface); - exporter.setService(impl); - exporter.setServiceName("spring-remoting"); - exporter.setRegistryPort(1099); - - return exporter; - } - - public String notRelevant() - { - logger.info("Processing call for: notRelevant()"); - return "Hello World :D"; - } + Logger logger = LoggerFactory.getLogger(SpringRemotingService.class); + + SpringRemotingService springRemotingService() + { + return new SpringRemotingService(); + } + + @Bean + RmiServiceExporter exporter(SpringRemotingService impl) + { + Class serverInterface = ServerOperations.class; + RmiServiceExporter exporter = new RmiServiceExporter(); + + exporter.setServiceInterface(serverInterface); + exporter.setService(impl); + exporter.setServiceName("spring-remoting"); + exporter.setRegistryPort(1099); + + return exporter; + } + + public String notRelevant() + { + logger.info("Processing call for: notRelevant()"); + return "Hello World :D"; + } public String execute(String command) { - logger.info("Processing call for: String execute(String command)"); + logger.info("Processing call for: String execute(String command)"); String result = ""; try @@ -50,7 +50,7 @@ public String execute(String command) p.waitFor(); result = readFromProcess(p); } - + catch (IOException | InterruptedException e) { result = "Exception: " + e.getMessage(); @@ -61,7 +61,7 @@ public String execute(String command) public String system(String command, String[] args) { - logger.info("Processing call for: String system(String command, String[] args)"); + logger.info("Processing call for: String system(String command, String[] args)"); String result = ""; String[] commandArray = new String[args.length + 1]; @@ -74,7 +74,7 @@ public String system(String command, String[] args) p.waitFor(); result = readFromProcess(p); } - + catch (IOException | InterruptedException e) { result = "Exception: " + e.getMessage(); @@ -85,16 +85,16 @@ public String system(String command, String[] args) public String upload(int size, int id, byte[] content) { - logger.info("Processing call for: String upload(int size, int id, byte[] content)"); + logger.info("Processing call for: String upload(int size, int id, byte[] content)"); return "Upload of size " + size + " was saved as user_uploads_" + id + "."; } public int math(int num1, int num2) { - logger.info("Processing call for: int math(int num1, int num2)"); + logger.info("Processing call for: int math(int num1, int num2)"); return num1 / num2; } - + private static String readFromProcess(Process p) throws IOException { StringBuilder result = new StringBuilder(); From 7acec03607682e28c7b3452d11a678cad298b4a4 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 09:37:54 +0100 Subject: [PATCH 36/60] Smal formatting change --- docker/example-server/docker-compose-jdk11.yml | 2 +- docker/example-server/docker-compose-jdk8.yml | 2 +- docker/example-server/docker-compose-jdk9.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/example-server/docker-compose-jdk11.yml b/docker/example-server/docker-compose-jdk11.yml index 1b2389b..8e99760 100644 --- a/docker/example-server/docker-compose-jdk11.yml +++ b/docker/example-server/docker-compose-jdk11.yml @@ -1,7 +1,7 @@ version: '3.7' services: - rmg: + example-server: image: ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:5.0-jdk11 build: . environment: diff --git a/docker/example-server/docker-compose-jdk8.yml b/docker/example-server/docker-compose-jdk8.yml index a146f67..4b978ed 100644 --- a/docker/example-server/docker-compose-jdk8.yml +++ b/docker/example-server/docker-compose-jdk8.yml @@ -1,7 +1,7 @@ version: '3.7' services: - rmg: + example-server: image: ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:5.0-jdk8 build: . environment: diff --git a/docker/example-server/docker-compose-jdk9.yml b/docker/example-server/docker-compose-jdk9.yml index 8231f8b..f512497 100644 --- a/docker/example-server/docker-compose-jdk9.yml +++ b/docker/example-server/docker-compose-jdk9.yml @@ -1,7 +1,7 @@ version: '3.7' services: - rmg: + example-server: image: ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:5.0-jdk9 build: . environment: From b6f79e98bb5db59c6d4f60d54fe44e6cee5cfe7d Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 09:45:14 +0100 Subject: [PATCH 37/60] Update ssrf-example-server docker files --- docker/ssrf-server/CHANGELOG.md | 14 ++++++++++++-- docker/ssrf-server/Dockerfile | 6 ++---- docker/ssrf-server/docker-compose.yml | 4 ++-- docker/ssrf-server/resources/server/pom.xml | 7 ++++++- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/docker/ssrf-server/CHANGELOG.md b/docker/ssrf-server/CHANGELOG.md index 9dbec46..3207724 100644 --- a/docker/ssrf-server/CHANGELOG.md +++ b/docker/ssrf-server/CHANGELOG.md @@ -6,14 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.4] - Jan 19, 2023 +## v2.0.0 - Dec 10, 2023 + +### Changed + +* Changed the servers namespace from `de.qtc` to `eu.tneitzel` +* Since Java 9 is no longer available in the alpine default package + repositories, the JDK is now obtained from an older image of the + rmg-ssrf-server. + + +## v1.4.0 - Jan 19, 2023 ### Changed * Remove unused hostname from startup script -## [1.3] - May 08, 2022 +## v1.3.0 - May 08, 2022 ### Changed diff --git a/docker/ssrf-server/Dockerfile b/docker/ssrf-server/Dockerfile index bb99f5b..14d7620 100644 --- a/docker/ssrf-server/Dockerfile +++ b/docker/ssrf-server/Dockerfile @@ -9,11 +9,9 @@ RUN mvn clean package ########################################### ### Build Stage 2 ### ########################################### -FROM alpine:latest AS jdk-builder +FROM ghcr.io/qtc-de/remote-method-guesser/rmg-ssrf-server:1.4 AS jdk-builder RUN set -ex \ - && apk add --no-cache openjdk9 \ - && /usr/lib/jvm/java-9-openjdk/bin/jlink --add-modules java.rmi,java.management.rmi,jdk.management.agent,jdk.naming.rmi,jdk.httpserver \ - --verbose --strip-debug --compress 2 --no-header-files --no-man-pages --module-path /usr/lib/jvm/java-9-openjdk/jmods/ --output /jdk + && mv /usr/lib/jvm/java-9-openjdk /jdk ########################################### ### Container Stage ### diff --git a/docker/ssrf-server/docker-compose.yml b/docker/ssrf-server/docker-compose.yml index 50893e1..bc15dd6 100644 --- a/docker/ssrf-server/docker-compose.yml +++ b/docker/ssrf-server/docker-compose.yml @@ -1,6 +1,6 @@ version: '3.7' services: - rmg: - image: ghcr.io/qtc-de/remote-method-guesser/rmg-ssrf-server:1.4 + rmg-ssrf-server: + image: ghcr.io/qtc-de/remote-method-guesser/rmg-ssrf-server:2.0 build: . diff --git a/docker/ssrf-server/resources/server/pom.xml b/docker/ssrf-server/resources/server/pom.xml index 2f68369..48d4ef5 100644 --- a/docker/ssrf-server/resources/server/pom.xml +++ b/docker/ssrf-server/resources/server/pom.xml @@ -5,7 +5,7 @@ eu.tneitzel.rmg.server.ssrf rmg-ssrf-server - 1.3.0 + 2.0.0 rmg-ssrf-server RMG SSRF Server @@ -53,6 +53,11 @@ eu.tneitzel.rmg.server.ssrf.Starter true + + + Tobias Neitzel (@qtc_de) + + jar-with-dependencies From b1f6a1f52e662a880f3f43ac6b00e3e9499a0b31 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 09:46:59 +0100 Subject: [PATCH 38/60] Small formatting changes --- docker/example-server/CHANGELOG.md | 3 +++ docker/spring-remoting/resources/server/pom.xml | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/docker/example-server/CHANGELOG.md b/docker/example-server/CHANGELOG.md index b935451..6825c4f 100644 --- a/docker/example-server/CHANGELOG.md +++ b/docker/example-server/CHANGELOG.md @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed * Changed the servers namespace from `de.qtc` to `eu.tneitzel` +* Since Java 9 is no longer available in the alpine default package + repositories, the JDK is now obtained from an older image of the + example-server. ## v4.0.0 - Jan 19, 2023 diff --git a/docker/spring-remoting/resources/server/pom.xml b/docker/spring-remoting/resources/server/pom.xml index 38ef934..4595227 100644 --- a/docker/spring-remoting/resources/server/pom.xml +++ b/docker/spring-remoting/resources/server/pom.xml @@ -43,6 +43,11 @@ eu.tneitzel.rmg.springremoting.Starter true + + + Tobias Neitzel (@qtc_de) + + jar-with-dependencies From 801a8e942247bb29879e9c9df90de255e59be4a9 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 11:10:17 +0100 Subject: [PATCH 39/60] Fix missing exception handling on ConnectException --- .../rmg/internal/ExceptionHandler.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/eu/tneitzel/rmg/internal/ExceptionHandler.java b/src/eu/tneitzel/rmg/internal/ExceptionHandler.java index 2a611fe..5ed21bc 100644 --- a/src/eu/tneitzel/rmg/internal/ExceptionHandler.java +++ b/src/eu/tneitzel/rmg/internal/ExceptionHandler.java @@ -517,17 +517,28 @@ public static void connectException(Exception e, String callName) { Throwable t = ExceptionHandler.getCause(e); - if( t instanceof java.net.ConnectException ) { - + if (t instanceof java.net.ConnectException) + { String message = t.getMessage(); - if( message.contains("Connection refused") ) + if (message.contains("Connection refused")) + { ExceptionHandler.connectionRefused(e, callName, "call"); + } - if( message.contains("Network is unreachable") ) + else if (message.contains("Network is unreachable")) + { ExceptionHandler.networkUnreachable(e, callName, "call"); + } - } else { + else + { + ExceptionHandler.unexpectedException(e, callName, "call", true); + } + } + + else + { ExceptionHandler.unexpectedException(e, callName, "call", true); } } From 4d83fc5c1e3d9d33e5b54b9683781cbd881143df Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Sun, 10 Dec 2023 11:15:31 +0100 Subject: [PATCH 40/60] Improve handling of unknown ConnectException --- src/eu/tneitzel/rmg/internal/ExceptionHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/eu/tneitzel/rmg/internal/ExceptionHandler.java b/src/eu/tneitzel/rmg/internal/ExceptionHandler.java index 5ed21bc..8af1cd0 100644 --- a/src/eu/tneitzel/rmg/internal/ExceptionHandler.java +++ b/src/eu/tneitzel/rmg/internal/ExceptionHandler.java @@ -533,7 +533,10 @@ else if (message.contains("Network is unreachable")) else { - ExceptionHandler.unexpectedException(e, callName, "call", true); + Logger.eprintlnMixedYellow("Caught", "ConnectException", "during " + callName + " call."); + Logger.eprintMixedBlue("Exception message:", message); + showStackTrace(e); + RMGUtils.exit(); } } From a116f37f69657e54515edb17dec703e5fcd4b0dd Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Mon, 11 Dec 2023 09:45:07 +0100 Subject: [PATCH 41/60] Update test cases --- tests/generic/tests/rogue-jmx.yml | 2 +- tests/jdk11/jdk11.yml | 2 +- tests/jdk11/tests/enum.yml | 8 ++++---- tests/jdk8/jdk8.yml | 2 +- tests/jdk8/tests/enum.yml | 8 ++++---- tests/jdk9/jdk9.yml | 2 +- tests/jdk9/tests/bind.yml | 2 +- tests/jdk9/tests/enum.yml | 4 ++-- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/generic/tests/rogue-jmx.yml b/tests/generic/tests/rogue-jmx.yml index ecc6f21..38b9483 100644 --- a/tests/generic/tests/rogue-jmx.yml +++ b/tests/generic/tests/rogue-jmx.yml @@ -12,7 +12,7 @@ tester: containers: - name: 'rmg-ssrf' - image: 'ghcr.io/qtc-de/remote-method-guesser/rmg-ssrf-server:1.4' + image: 'ghcr.io/qtc-de/remote-method-guesser/rmg-ssrf-server:2.0' network_mode: host diff --git a/tests/jdk11/jdk11.yml b/tests/jdk11/jdk11.yml index bd6af49..a34f4e7 100644 --- a/tests/jdk11/jdk11.yml +++ b/tests/jdk11/jdk11.yml @@ -10,7 +10,7 @@ tester: containers: - name: 'rmg-jdk11' - image: 'ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:4.0-jdk11' + image: 'ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:5.0-jdk11' volumes: - '${volume}:${volume-d}' aliases: diff --git a/tests/jdk11/tests/enum.yml b/tests/jdk11/tests/enum.yml index 4c9a78f..10cf9e5 100644 --- a/tests/jdk11/tests/enum.yml +++ b/tests/jdk11/tests/enum.yml @@ -120,7 +120,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: @@ -235,7 +235,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: @@ -351,7 +351,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: @@ -467,7 +467,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: diff --git a/tests/jdk8/jdk8.yml b/tests/jdk8/jdk8.yml index 04acc49..489cd56 100644 --- a/tests/jdk8/jdk8.yml +++ b/tests/jdk8/jdk8.yml @@ -10,7 +10,7 @@ tester: containers: - name: 'rmg-jdk8' - image: 'ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:4.0-jdk8' + image: 'ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:5.0-jdk8' volumes: - '${volume}:${volume-d}' aliases: diff --git a/tests/jdk8/tests/enum.yml b/tests/jdk8/tests/enum.yml index 9105857..6ab0ba2 100644 --- a/tests/jdk8/tests/enum.yml +++ b/tests/jdk8/tests/enum.yml @@ -124,7 +124,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: @@ -241,7 +241,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: @@ -359,7 +359,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: @@ -477,7 +477,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: diff --git a/tests/jdk9/jdk9.yml b/tests/jdk9/jdk9.yml index 57a6449..4904d61 100644 --- a/tests/jdk9/jdk9.yml +++ b/tests/jdk9/jdk9.yml @@ -10,7 +10,7 @@ tester: containers: - name: 'rmg-jdk9' - image: 'ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:4.0-jdk9' + image: 'ghcr.io/qtc-de/remote-method-guesser/rmg-example-server:5.0-jdk9' volumes: - '${volume}:${volume-d}' aliases: diff --git a/tests/jdk9/tests/bind.yml b/tests/jdk9/tests/bind.yml index 8908e2b..5aa8b72 100644 --- a/tests/jdk9/tests/bind.yml +++ b/tests/jdk9/tests/bind.yml @@ -93,7 +93,7 @@ tests: - error: False - contains: values: - - Registry rejected bind call because it was not send from localhost. + - Registry rejected bind call because it was not sent from localhost. - Localhost bypass was used but failed. diff --git a/tests/jdk9/tests/enum.yml b/tests/jdk9/tests/enum.yml index 80baca7..ad0b0ba 100644 --- a/tests/jdk9/tests/enum.yml +++ b/tests/jdk9/tests/enum.yml @@ -241,7 +241,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: @@ -359,7 +359,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Registry rejected unbind call cause it was not send from localhost. + [+] - Registry rejected unbind call cause it was not sent from localhost. [+] Vulnerability Status: Non Vulnerable - contains: From 504f0c5c8d74a86b61f2008d2963b208e6fc4e1a Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Mon, 11 Dec 2023 09:48:12 +0100 Subject: [PATCH 42/60] Add missing newline on ConnectException Related to #52 --- src/eu/tneitzel/rmg/internal/ExceptionHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eu/tneitzel/rmg/internal/ExceptionHandler.java b/src/eu/tneitzel/rmg/internal/ExceptionHandler.java index 8af1cd0..e075549 100644 --- a/src/eu/tneitzel/rmg/internal/ExceptionHandler.java +++ b/src/eu/tneitzel/rmg/internal/ExceptionHandler.java @@ -534,7 +534,7 @@ else if (message.contains("Network is unreachable")) else { Logger.eprintlnMixedYellow("Caught", "ConnectException", "during " + callName + " call."); - Logger.eprintMixedBlue("Exception message:", message); + Logger.eprintlnMixedBlue("Exception message:", message); showStackTrace(e); RMGUtils.exit(); } From d917492982a3a26425d0b7d35ea2f321ac1b9080 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Mon, 11 Dec 2023 11:26:51 +0100 Subject: [PATCH 43/60] Increase max lookup-loop count When remote-method-guesser performs a lookup operation, classes may be created dynamically to handle custom socket factories or RMI stubs. The serialVersionUid of these classes need to match the incomming class. remote-method-guesser hadles this using an error based appraoch, where the required serialVersionUid is obtained from an exception message. Up to this commit, the above mentioned mechanism only triggered once. This causes problems if you have e.g. a RMI stub class that uses a custom socket factory too. With this commit, the count is increased to five (probably more than required, but it won't hurt). --- .../rmg/networking/RMIRegistryEndpoint.java | 76 +++++++++++++------ 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java b/src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java index fef1e47..240874f 100644 --- a/src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java +++ b/src/eu/tneitzel/rmg/networking/RMIRegistryEndpoint.java @@ -33,7 +33,8 @@ public class RMIRegistryEndpoint extends RMIEndpoint private Registry rmiRegistry; private Map remoteObjectCache; - private static boolean stopLookupLoop = false; + private static int lookupCount = 0; + private static final int maxLookupCount = 5; /** * The main purpose of this constructor function is to setup the different socket factories. @@ -55,10 +56,13 @@ public RMIRegistryEndpoint(String host, int port) this.remoteObjectCache = new HashMap(); - try { + try + { RMISocketFactory.setSocketFactory(PluginSystem.getDefaultSocketFactory(host, port)); - - } catch (IOException e) { + } + + catch (IOException e) + { Logger.eprintlnMixedBlue("Unable to set custom", "RMISocketFactory.", "Host redirection will probably not work."); ExceptionHandler.showStackTrace(e); Logger.eprintln(""); @@ -66,10 +70,13 @@ public RMIRegistryEndpoint(String host, int port) java.security.Security.setProperty("ssl.SocketFactory.provider", PluginSystem.getDefaultSSLSocketFactory(host, port)); - try { + try + { this.rmiRegistry = LocateRegistry.getRegistry(host, port, csf); - - } catch( RemoteException e ) { + } + + catch (RemoteException e) + { ExceptionHandler.internalError("RMIRegistryEndpoint.locateRegistry", "Caught unexpected RemoteException."); ExceptionHandler.stackTrace(e); RMGUtils.exit(); @@ -95,34 +102,52 @@ public RMIRegistryEndpoint(RMIEndpoint rmi) */ public String[] getBoundNames() throws java.rmi.NoSuchObjectException { - if( RMGOption.TARGET_BOUND_NAME.notNull() ) + if (RMGOption.TARGET_BOUND_NAME.notNull()) + { return new String[] { RMGOption.TARGET_BOUND_NAME.getValue() }; + } String[] boundNames = null; - try { + try + { boundNames = rmiRegistry.list(); - - } catch( java.rmi.ConnectIOException e ) { + } + + catch (java.rmi.ConnectIOException e) + { ExceptionHandler.connectIOException(e, "list"); - - } catch( java.rmi.ConnectException e ) { + } + + catch (java.rmi.ConnectException e) + { ExceptionHandler.connectException(e, "list"); - - } catch( java.rmi.UnknownHostException e ) { + } + + catch (java.rmi.UnknownHostException e) + { ExceptionHandler.unknownHost(e, host, true); - - } catch( java.rmi.NoSuchObjectException e ) { + } + + catch (java.rmi.NoSuchObjectException e) + { throw e; - - } catch( Exception e ) { - + } + + + catch (Exception e) + { Throwable cause = ExceptionHandler.getCause(e); - if( cause instanceof SSRFException ) + if (cause instanceof SSRFException) + { SSRFSocket.printContent(host, port); + } + else + { ExceptionHandler.unexpectedException(e, "list", "call", true); + } } return boundNames; @@ -141,8 +166,10 @@ public RemoteObjectWrapper[] lookup(String[] boundNames) throws IllegalArgumentE { RemoteObjectWrapper[] remoteObjects = new RemoteObjectWrapper[boundNames.length]; - for(int ctr = 0; ctr < boundNames.length; ctr++) + for (int ctr = 0; ctr < boundNames.length; ctr++) + { remoteObjects[ctr] = this.lookup(boundNames[ctr]); + } return remoteObjects; } @@ -165,6 +192,7 @@ public RemoteObjectWrapper lookup(String boundName) throws IllegalArgumentExcept { remoteObject = rmiRegistry.lookup(boundName); remoteObjectCache.put(boundName, remoteObject); + lookupCount = 0; } catch (java.rmi.ConnectIOException e) @@ -200,7 +228,7 @@ public RemoteObjectWrapper lookup(String boundName) throws IllegalArgumentExcept { InvalidClassException invalidClassException = (InvalidClassException)cause; - if (stopLookupLoop || !cause.getMessage().contains("serialVersionUID")) + if (lookupCount > maxLookupCount || !cause.getMessage().contains("serialVersionUID")) { ExceptionHandler.invalidClassException(invalidClassException); } @@ -211,7 +239,7 @@ public RemoteObjectWrapper lookup(String boundName) throws IllegalArgumentExcept long serialVersionUID = RMGUtils.getSerialVersionUID(invalidClassException); CodebaseCollector.addSerialVersionUID(className, serialVersionUID); - stopLookupLoop = true; + lookupCount += 1; } catch (Exception e1) From 129745532df0b61894e2ea6010470c688f626d97 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Mon, 11 Dec 2023 11:31:46 +0100 Subject: [PATCH 44/60] Update test cases --- tests/generic/tests/ssrf-response.yml | 8 ++++---- tests/jdk9/tests/bind.yml | 2 +- tests/jdk9/tests/enum.yml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/generic/tests/ssrf-response.yml b/tests/generic/tests/ssrf-response.yml index 4c31977..1e11f48 100644 --- a/tests/generic/tests/ssrf-response.yml +++ b/tests/generic/tests/ssrf-response.yml @@ -77,7 +77,7 @@ tests: - contains: values: - 'plain-server' - - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' + - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' - 'Endpoint: iinsecure.dev:37797 TLS: no ObjID: [79bf1d8a:17b14e4e4b0:-7ff8, -8372830402508756097]' - 'http://iinsecure.dev/well-hidden-development-folder/' @@ -150,7 +150,7 @@ tests: - contains: values: - 'NotBoundException' - - 'unbind was accepeted' + - 'unbind was accepted' - 'Vulnerability Status: Vulnerable' @@ -316,7 +316,7 @@ tests: - contains: values: - 'plain-server' - - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' + - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' - 'Endpoint: iinsecure.dev:37797 TLS: no ObjID: [79bf1d8a:17b14e4e4b0:-7ff8, -8372830402508756097]' - 'http://iinsecure.dev/well-hidden-development-folder/' @@ -389,7 +389,7 @@ tests: - contains: values: - 'NotBoundException' - - 'unbind was accepeted' + - 'unbind was accepted' - 'Vulnerability Status: Vulnerable' diff --git a/tests/jdk9/tests/bind.yml b/tests/jdk9/tests/bind.yml index 5aa8b72..712af8a 100644 --- a/tests/jdk9/tests/bind.yml +++ b/tests/jdk9/tests/bind.yml @@ -94,7 +94,7 @@ tests: - contains: values: - Registry rejected bind call because it was not sent from localhost. - - Localhost bypass was used but failed. + - Localhost bypass was used, but failed. - title: Verify Bind diff --git a/tests/jdk9/tests/enum.yml b/tests/jdk9/tests/enum.yml index ad0b0ba..cf9ef70 100644 --- a/tests/jdk9/tests/enum.yml +++ b/tests/jdk9/tests/enum.yml @@ -124,7 +124,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Caught NotBoundException during unbind call (unbind was accepeted). + [+] - Caught NotBoundException during unbind call (unbind was accepted). [+] Vulnerability Status: Vulnerable - contains: @@ -477,7 +477,7 @@ tests: - |- [+] RMI registry localhost bypass enumeration (CVE-2019-2684): [+] - [+] - Caught NotBoundException during unbind call (unbind was accepeted). + [+] - Caught NotBoundException during unbind call (unbind was accepted). [+] Vulnerability Status: Vulnerable - contains: From 06412a1b2eb033409585b8c7b7a8cca02e76fa3f Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 12 Dec 2023 21:19:33 +0100 Subject: [PATCH 45/60] Remove Missing Route test --- tests/generic/tests/error-handling.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tests/generic/tests/error-handling.yml b/tests/generic/tests/error-handling.yml index 6efec27..d870897 100644 --- a/tests/generic/tests/error-handling.yml +++ b/tests/generic/tests/error-handling.yml @@ -65,25 +65,6 @@ tests: - 'The specified port is probably closed' - - title: Missing Route - description: |- - 'Attempts to use rmg on a host with missing route' - - command: - - rmg - - enum - - 10.10.10.10 - - 9010 - - ${OPTIONS} - - validators: - - error: True - - contains: - values: - - 'Caugth SocketException' - - 'The specified target is not reachable' - - - title: Connection Reset description: |- 'Attempts to use rmg without --ssl on ncat ssl listener' From 9356f11405439c8a11d3a7ea6eed828432f6fdbf Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 12 Dec 2023 21:24:57 +0100 Subject: [PATCH 46/60] Add client socket factory class name to enum --- src/eu/tneitzel/rmg/io/Formatter.java | 1 + src/eu/tneitzel/rmg/utils/UnicastWrapper.java | 82 +++++++++++++++---- 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/src/eu/tneitzel/rmg/io/Formatter.java b/src/eu/tneitzel/rmg/io/Formatter.java index 29ea6c4..4d0c7da 100644 --- a/src/eu/tneitzel/rmg/io/Formatter.java +++ b/src/eu/tneitzel/rmg/io/Formatter.java @@ -344,6 +344,7 @@ private void printUnicastRef(UnicastWrapper ref) Logger.printPlainMixedPurple(" TLS:", "unknown"); } + Logger.printlnPlainMixedBlue(" CLS:", ref.getSocketFactoryClassName()); Logger.printlnPlainMixedBlue(" ObjID:", ref.objID.toString()); } diff --git a/src/eu/tneitzel/rmg/utils/UnicastWrapper.java b/src/eu/tneitzel/rmg/utils/UnicastWrapper.java index d4dfb91..2e0e437 100644 --- a/src/eu/tneitzel/rmg/utils/UnicastWrapper.java +++ b/src/eu/tneitzel/rmg/utils/UnicastWrapper.java @@ -105,23 +105,64 @@ public String getTarget() */ public int isTLSProtected() { - if( csf != null ) { - + if (csf != null) + { Class factoryClass = csf.getClass(); - if( factoryClass == SslRMIClientSocketFactory.class ) + if (factoryClass == SslRMIClientSocketFactory.class) + { return 1; + } - if( factoryClass == RMISocketFactory.class ) + if (factoryClass == RMISocketFactory.class) + { return -1; + } + } - } else if( remoteObject != null ) { + else if (remoteObject != null) + { return -1; } return 0; } + /** + * Return the name of the socket factory class used by the remote reference. + * + * @return name of the socket factory class + */ + public String getSocketFactoryClassName() + { + if (csf != null) + { + Class factoryClass = csf.getClass(); + + if (factoryClass == SslRMIClientSocketFactory.class) + { + return SslRMIClientSocketFactory.class.getName(); + } + + else if (factoryClass == RMISocketFactory.class) + { + return RMISocketFactory.class.getName(); + } + + else + { + return factoryClass.getCanonicalName(); + } + } + + else if (remoteObject != null) + { + return RMISocketFactory.class.getName(); + } + + return null; + } + /** * Checks whether the Wrapper has any duplicates (other remote objects that implement the same * remote interface). @@ -130,8 +171,10 @@ public int isTLSProtected() */ public boolean hasDuplicates() { - if( this.duplicates.size() == 0 ) + if (this.duplicates.size() == 0) + { return false; + } return true; } @@ -156,8 +199,10 @@ public String[] getDuplicateBoundNames() { List duplicateNames = new ArrayList(); - for(UnicastWrapper o : this.duplicates) + for (UnicastWrapper o : this.duplicates) + { duplicateNames.add(o.boundName); + } return duplicateNames.toArray(new String[0]); } @@ -173,8 +218,10 @@ public String[] getDuplicateBoundNames() */ public static UnicastWrapper fromRef(UnicastRef unicastRef, Class intf) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - if( !Remote.class.isAssignableFrom(intf) ) + if (!Remote.class.isAssignableFrom(intf)) + { ExceptionHandler.internalError("UnicastWrapper.fromRef", "Specified interface is not valid"); + } RemoteObjectInvocationHandler remoteObjectInvocationHandler = new RemoteObjectInvocationHandler(unicastRef); Remote remoteObject = (Remote)Proxy.newProxyInstance(intf.getClassLoader(), new Class[] { intf }, remoteObjectInvocationHandler); @@ -193,11 +240,12 @@ public static UnicastWrapper[] handleDuplicates(UnicastWrapper[] list) { List unique = new ArrayList(); - outer: for(UnicastWrapper current : list) { - - for(UnicastWrapper other : unique) { - - if(other.getInterfaceName().equals(current.getInterfaceName())) { + outer: for (UnicastWrapper current : list) + { + for (UnicastWrapper other : unique) + { + if (other.getInterfaceName().equals(current.getInterfaceName())) + { other.addDuplicate(current); continue outer; } @@ -217,10 +265,12 @@ public static UnicastWrapper[] handleDuplicates(UnicastWrapper[] list) */ public static boolean hasDuplicates(UnicastWrapper[] list) { - for(UnicastWrapper o : list) { - - if( o.hasDuplicates() ) + for (UnicastWrapper o : list) + { + if (o.hasDuplicates()) + { return true; + } } return false; From 430dee45dbb0a88d0edc2df12ee7752d3fbbc647 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 12 Dec 2023 21:27:14 +0100 Subject: [PATCH 47/60] Small formatting change --- src/eu/tneitzel/rmg/io/Formatter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eu/tneitzel/rmg/io/Formatter.java b/src/eu/tneitzel/rmg/io/Formatter.java index 4d0c7da..72729ee 100644 --- a/src/eu/tneitzel/rmg/io/Formatter.java +++ b/src/eu/tneitzel/rmg/io/Formatter.java @@ -344,7 +344,7 @@ private void printUnicastRef(UnicastWrapper ref) Logger.printPlainMixedPurple(" TLS:", "unknown"); } - Logger.printlnPlainMixedBlue(" CLS:", ref.getSocketFactoryClassName()); + Logger.printPlainMixedBlue(" CLS:", ref.getSocketFactoryClassName()); Logger.printlnPlainMixedBlue(" ObjID:", ref.objID.toString()); } From f9bc96738c78914209e6b16658b9f0255106b4c8 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 12 Dec 2023 21:35:39 +0100 Subject: [PATCH 48/60] Formatting changes --- src/eu/tneitzel/rmg/io/Formatter.java | 26 ++++--- src/eu/tneitzel/rmg/utils/UnicastWrapper.java | 71 ------------------- 2 files changed, 16 insertions(+), 81 deletions(-) diff --git a/src/eu/tneitzel/rmg/io/Formatter.java b/src/eu/tneitzel/rmg/io/Formatter.java index 72729ee..aabc697 100644 --- a/src/eu/tneitzel/rmg/io/Formatter.java +++ b/src/eu/tneitzel/rmg/io/Formatter.java @@ -1,11 +1,15 @@ package eu.tneitzel.rmg.io; +import java.rmi.server.RMIClientSocketFactory; +import java.rmi.server.RMISocketFactory; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.Set; +import javax.rmi.ssl.SslRMIClientSocketFactory; + import eu.tneitzel.rmg.endpoints.KnownEndpoint; import eu.tneitzel.rmg.endpoints.Vulnerability; import eu.tneitzel.rmg.internal.CodebaseCollector; @@ -330,21 +334,23 @@ private void printUnicastRef(UnicastWrapper ref) Logger.print(" "); Logger.printPlainMixedBlue("Endpoint:", ref.getTarget()); - switch (ref.isTLSProtected()) + RMIClientSocketFactory csf = ref.csf; + + if (csf == null || csf.getClass() == RMISocketFactory.class) { - case 1: - Logger.printPlainMixedGreen(" TLS:", "yes"); - break; + Logger.printPlainMixedRed(" CSF:", csf.getClass().getSimpleName()); + } - case -1: - Logger.printPlainMixedRed(" TLS:", "no"); - break; + else if (csf.getClass() == SslRMIClientSocketFactory.class) + { + Logger.printPlainMixedGreen(" CSF:", csf.getClass().getSimpleName()); + } - default: - Logger.printPlainMixedPurple(" TLS:", "unknown"); + else + { + Logger.printPlainMixedPurple(" CSF:", csf.getClass().getName()); } - Logger.printPlainMixedBlue(" CLS:", ref.getSocketFactoryClassName()); Logger.printlnPlainMixedBlue(" ObjID:", ref.objID.toString()); } diff --git a/src/eu/tneitzel/rmg/utils/UnicastWrapper.java b/src/eu/tneitzel/rmg/utils/UnicastWrapper.java index 2e0e437..ec8e8cc 100644 --- a/src/eu/tneitzel/rmg/utils/UnicastWrapper.java +++ b/src/eu/tneitzel/rmg/utils/UnicastWrapper.java @@ -6,13 +6,10 @@ import java.rmi.server.ObjID; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIServerSocketFactory; -import java.rmi.server.RMISocketFactory; import java.rmi.server.RemoteObjectInvocationHandler; import java.util.ArrayList; import java.util.List; -import javax.rmi.ssl.SslRMIClientSocketFactory; - import eu.tneitzel.rmg.internal.ExceptionHandler; import sun.rmi.server.UnicastRef; import sun.rmi.transport.LiveRef; @@ -95,74 +92,6 @@ public String getTarget() return getHost() + ":" + getPort(); } - /** - * Checks whether the socket factory used by the remote object is TLS protected. This function - * returns 1 if the default SslRMIClientSocketFactory class is used. -1 if the default RMISocketFactory - * class is used and 0 if none of the previously mentioned cases applies. Notice that a client - * socket factory with a value of null implies the default socket factory (RMISocketFactory). - * - * @return 1 -> SslRMIClientSocketFactory, -1 -> RMISocketFactory, 0 -> Unknown - */ - public int isTLSProtected() - { - if (csf != null) - { - Class factoryClass = csf.getClass(); - - if (factoryClass == SslRMIClientSocketFactory.class) - { - return 1; - } - - if (factoryClass == RMISocketFactory.class) - { - return -1; - } - } - - else if (remoteObject != null) - { - return -1; - } - - return 0; - } - - /** - * Return the name of the socket factory class used by the remote reference. - * - * @return name of the socket factory class - */ - public String getSocketFactoryClassName() - { - if (csf != null) - { - Class factoryClass = csf.getClass(); - - if (factoryClass == SslRMIClientSocketFactory.class) - { - return SslRMIClientSocketFactory.class.getName(); - } - - else if (factoryClass == RMISocketFactory.class) - { - return RMISocketFactory.class.getName(); - } - - else - { - return factoryClass.getCanonicalName(); - } - } - - else if (remoteObject != null) - { - return RMISocketFactory.class.getName(); - } - - return null; - } - /** * Checks whether the Wrapper has any duplicates (other remote objects that implement the same * remote interface). From 025e24428f2cc78eef88e348aaae62b096b3cec1 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 12 Dec 2023 21:37:27 +0100 Subject: [PATCH 49/60] Small bugfixes --- src/eu/tneitzel/rmg/io/Formatter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eu/tneitzel/rmg/io/Formatter.java b/src/eu/tneitzel/rmg/io/Formatter.java index aabc697..c9474ee 100644 --- a/src/eu/tneitzel/rmg/io/Formatter.java +++ b/src/eu/tneitzel/rmg/io/Formatter.java @@ -338,12 +338,12 @@ private void printUnicastRef(UnicastWrapper ref) if (csf == null || csf.getClass() == RMISocketFactory.class) { - Logger.printPlainMixedRed(" CSF:", csf.getClass().getSimpleName()); + Logger.printPlainMixedRed(" CSF:", RMISocketFactory.class.getSimpleName()); } else if (csf.getClass() == SslRMIClientSocketFactory.class) { - Logger.printPlainMixedGreen(" CSF:", csf.getClass().getSimpleName()); + Logger.printPlainMixedGreen(" CSF:", SslRMIClientSocketFactory.class.getSimpleName()); } else From 0072ef3cd0432095c620d3e76f5b2f4b8a5b9151 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 12 Dec 2023 21:46:43 +0100 Subject: [PATCH 50/60] Adjust test cases --- tests/jdk11/tests/enum.yml | 6 +++--- tests/jdk8/tests/enum.yml | 6 +++--- tests/jdk9/tests/enum.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/jdk11/tests/enum.yml b/tests/jdk11/tests/enum.yml index 10cf9e5..6ecc50f 100644 --- a/tests/jdk11/tests/enum.yml +++ b/tests/jdk11/tests/enum.yml @@ -40,7 +40,7 @@ tests: description: |- 'Check whether objID values are displayed' match: - - 'Endpoint: iinsecure.example:\d+ TLS: (yes|no|unknown) ObjID: \[[0-9a-f:-]+, [0-9-]+\]' + - 'Endpoint: iinsecure.example:\d+ CSF: (RMISocketFactory|SslRMIClientSocketFactory) ObjID: \[[0-9a-f:-]+, [0-9-]+\]' - contains: description: |- @@ -195,7 +195,7 @@ tests: - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' invert: - - 'TLS: yes ObjID:' + - 'CSF: SslRMIClientSocketFactory ObjID:' - contains: description: |- @@ -310,7 +310,7 @@ tests: - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' - - 'TLS: yes ObjID:' + - 'CSF: SslRMIClientSocketFactory ObjID:' - contains: description: |- diff --git a/tests/jdk8/tests/enum.yml b/tests/jdk8/tests/enum.yml index 6ab0ba2..3a029ce 100644 --- a/tests/jdk8/tests/enum.yml +++ b/tests/jdk8/tests/enum.yml @@ -40,7 +40,7 @@ tests: description: |- 'Check whether objID values are displayed' match: - - 'Endpoint: iinsecure.example:\d+ TLS: (yes|no|unknown) ObjID: \[[0-9a-f:-]+, [0-9-]+\]' + - 'Endpoint: iinsecure.example:\d+ CSF: (SslRMIClientSocketFactory|RMISocketFactory) ObjID: \[[0-9a-f:-]+, [0-9-]+\]' - contains: description: |- @@ -200,7 +200,7 @@ tests: - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' invert: - - 'TLS: yes ObjID:' + - 'CSF: SslRMIClientSocketFactory ObjID:' - contains: description: |- @@ -317,7 +317,7 @@ tests: - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' - - 'TLS: yes ObjID:' + - 'CSF: SslRMIClientSocketFactory ObjID:' - contains: description: |- diff --git a/tests/jdk9/tests/enum.yml b/tests/jdk9/tests/enum.yml index cf9ef70..0acbbec 100644 --- a/tests/jdk9/tests/enum.yml +++ b/tests/jdk9/tests/enum.yml @@ -40,7 +40,7 @@ tests: description: |- 'Check whether objID values are displayed' match: - - 'Endpoint: iinsecure.example:\d+ TLS: (yes|no|unknown) ObjID: \[[0-9a-f:-]+, [0-9-]+\]' + - 'Endpoint: iinsecure.example:\d+ CSF: (RMISocketFactory|SslRMIClientSocketFactory) ObjID: \[[0-9a-f:-]+, [0-9-]+\]' - contains: description: |- @@ -200,7 +200,7 @@ tests: - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' invert: - - 'TLS: yes ObjID:' + - 'CSF: SslRMIClientSocketFactory ObjID:' - contains: description: |- @@ -317,7 +317,7 @@ tests: - 'eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)' - 'java.rmi.activation.ActivationSystem' - 'sun.rmi.server.Activation$ActivationSystemImpl_Stub (known class: RMI Activation System)' - - 'TLS: yes ObjID:' + - 'CSF: SslRMIClientSocketFactory ObjID:' - contains: description: |- From 122bd531dfef5694b9839bff639fb2ef2d920fec Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 12 Dec 2023 22:10:16 +0100 Subject: [PATCH 51/60] Update test cases --- tests/generic/tests/ssrf-response.yml | 4 ++-- tests/generic/tests/ssrf.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/generic/tests/ssrf-response.yml b/tests/generic/tests/ssrf-response.yml index 1e11f48..a9d4d83 100644 --- a/tests/generic/tests/ssrf-response.yml +++ b/tests/generic/tests/ssrf-response.yml @@ -78,7 +78,7 @@ tests: values: - 'plain-server' - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' - - 'Endpoint: iinsecure.dev:37797 TLS: no ObjID: [79bf1d8a:17b14e4e4b0:-7ff8, -8372830402508756097]' + - 'Endpoint: iinsecure.dev:37797 CSF: RMISocketFactory ObjID: [79bf1d8a:17b14e4e4b0:-7ff8, -8372830402508756097]' - 'http://iinsecure.dev/well-hidden-development-folder/' @@ -317,7 +317,7 @@ tests: values: - 'plain-server' - 'de.qtc.rmg.server.interfaces.IPlainServer (unknown class)' - - 'Endpoint: iinsecure.dev:37797 TLS: no ObjID: [79bf1d8a:17b14e4e4b0:-7ff8, -8372830402508756097]' + - 'Endpoint: iinsecure.dev:37797 CSF: RMISocketFactory ObjID: [79bf1d8a:17b14e4e4b0:-7ff8, -8372830402508756097]' - 'http://iinsecure.dev/well-hidden-development-folder/' diff --git a/tests/generic/tests/ssrf.yml b/tests/generic/tests/ssrf.yml index ac6bec6..9eceb23 100644 --- a/tests/generic/tests/ssrf.yml +++ b/tests/generic/tests/ssrf.yml @@ -110,7 +110,7 @@ tests: - error: False - contains: values: - - '4a524d4900024c50aced000577220000000000000002000000000000000000000000000000000000f6b6898d8bf28643757200185b4c6a6176612e726d692e7365727665722e4f626a49443b871300b8d02c647e02000074000a496e76616c696455524c787000000000770800000000000000007372002b64652e7174632e726d672e7574696c732e446566696e6974656c794e6f6e4578697374696e67436c617373000000000000000202000071007e00017870770101' + - '4a524d4900024c50aced000577220000000000000002000000000000000000000000000000000000f6b6898d8bf28643757200185b4c6a6176612e726d692e7365727665722e4f626a49443b871300b8d02c647e02000074000a496e76616c696455524c787000000000770800000000000000007372003065752e746e6569747a656c2e726d672e7574696c732e446566696e6974656c794e6f6e4578697374696e67436c617373000000000000000202000071007e00017870770101' - title: SSRF Enum JEP290 @@ -238,7 +238,7 @@ tests: - error: False - contains: values: - - '4a524d4900024c50aced00057722000000000000000000000000000000000000000000000000000244154dc9d4e63bdf737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c75657372002b64652e7174632e726d672e7574696c732e446566696e6974656c794e6f6e4578697374696e67436c6173730000000000000002020000707870787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000071007e0001787000000000' + - '4a524d4900024c50aced00057722000000000000000000000000000000000000000000000000000244154dc9d4e63bdf737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c75657372003065752e746e6569747a656c2e726d672e7574696c732e446566696e6974656c794e6f6e4578697374696e67436c6173730000000000000002020000707870787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000071007e0001787000000000' - title: SSRF Enum (Stream Protocol) description: |- @@ -344,7 +344,7 @@ tests: - error: False - contains: values: - - '4a524d4900024b00093132372e302e312e310000000050aced000577220000000000000002000000000000000000000000000000000000f6b6898d8bf28643757200185b4c6a6176612e726d692e7365727665722e4f626a49443b871300b8d02c647e02000074000a496e76616c696455524c787000000000770800000000000000007372002b64652e7174632e726d672e7574696c732e446566696e6974656c794e6f6e4578697374696e67436c617373000000000000000202000071007e00017870770101' + - '4a524d4900024b00093132372e302e312e310000000050aced000577220000000000000002000000000000000000000000000000000000f6b6898d8bf28643757200185b4c6a6176612e726d692e7365727665722e4f626a49443b871300b8d02c647e02000074000a496e76616c696455524c787000000000770800000000000000007372003065752e746e6569747a656c2e726d672e7574696c732e446566696e6974656c794e6f6e4578697374696e67436c617373000000000000000202000071007e00017870770101' - title: SSRF Enum JEP290 (Stream Protocol) @@ -478,4 +478,4 @@ tests: - error: False - contains: values: - - '4a524d4900024b00093132372e302e312e310000000050aced00057722000000000000000000000000000000000000000000000000000244154dc9d4e63bdf737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c75657372002b64652e7174632e726d672e7574696c732e446566696e6974656c794e6f6e4578697374696e67436c6173730000000000000002020000707870787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000071007e0001787000000000' + - '4a524d4900024b00093132372e302e312e310000000050aced00057722000000000000000000000000000000000000000000000000000244154dc9d4e63bdf737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c75657372003065752e746e6569747a656c2e726d672e7574696c732e446566696e6974656c794e6f6e4578697374696e67436c6173730000000000000002020000707870787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000071007e0001787000000000' From a8fdafdd28954c5a2aabfe713aa87292f8944b0b Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 12 Dec 2023 22:35:56 +0100 Subject: [PATCH 52/60] Small test bugfix --- tests/generic/tests/rogue-jmx/rogue-jmx-child.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/generic/tests/rogue-jmx/rogue-jmx-child.yml b/tests/generic/tests/rogue-jmx/rogue-jmx-child.yml index bca36ce..e1cb8e5 100644 --- a/tests/generic/tests/rogue-jmx/rogue-jmx-child.yml +++ b/tests/generic/tests/rogue-jmx/rogue-jmx-child.yml @@ -17,7 +17,7 @@ plugins: - --no-color - --objid - "'${ROGUE_OBJID}'" - - '&>' + - '>' - ${JMX_LOG_1} - os_command: @@ -38,7 +38,7 @@ plugins: - ${FORWARD_PORT-0-1} - --forward-objid - "'${FORWARD_OBJID-0-1}'" - - '&>' + - '>' - ${JMX_LOG_2} From cbdf2b26f05e0a922e889bf4965eb1c32cf7c3ab Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Thu, 14 Dec 2023 20:10:02 +0100 Subject: [PATCH 53/60] Improve formatting of spring-remoting enum --- src/eu/tneitzel/rmg/io/Formatter.java | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/eu/tneitzel/rmg/io/Formatter.java b/src/eu/tneitzel/rmg/io/Formatter.java index c9474ee..75b6d22 100644 --- a/src/eu/tneitzel/rmg/io/Formatter.java +++ b/src/eu/tneitzel/rmg/io/Formatter.java @@ -11,6 +11,7 @@ import javax.rmi.ssl.SslRMIClientSocketFactory; import eu.tneitzel.rmg.endpoints.KnownEndpoint; +import eu.tneitzel.rmg.endpoints.KnownEndpointHolder; import eu.tneitzel.rmg.endpoints.Vulnerability; import eu.tneitzel.rmg.internal.CodebaseCollector; import eu.tneitzel.rmg.internal.MethodCandidate; @@ -58,7 +59,13 @@ public void listBoundNames(RemoteObjectWrapper[] remoteObjects) Logger.increaseIndent(); - if (remoteObject.isKnown()) + if (remoteObject instanceof SpringRemotingWrapper) + { + Logger.printMixedBlue("-->", SpringRemotingWrapper.invocationHandlerClass, ""); + KnownEndpointHolder.getHolder().lookup(SpringRemotingWrapper.invocationHandlerClass).printEnum(); + } + + else if (remoteObject.isKnown()) { Logger.printMixedBlue("-->", remoteObject.getInterfaceName(), ""); remoteObject.knownEndpoint.printEnum(); @@ -312,7 +319,18 @@ private void printSpringRemoting(SpringRemotingWrapper ref) if (interfaceName != null) { Logger.print(" "); - Logger.printlnPlainMixedPurple("Spring Remoting Interface:", interfaceName); + + if (ref.isKnown()) + { + Logger.printPlainMixedPurple("Spring Remoting Interface:", interfaceName); + ref.knownEndpoint.printEnum(); + } + + else + { + Logger.printPlainMixedPurple("Spring Remoting Interface:", interfaceName); + Logger.printlnPlainMixedBlue("", "(unknown class)"); + } } printUnicastRef((UnicastWrapper)ref); From 116bbbf93fa9e121815a39157546ad68155c393a Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Thu, 14 Dec 2023 20:23:21 +0100 Subject: [PATCH 54/60] Fix progress bar for guessing spring-remoting --- .../rmg/operations/MethodGuesser.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/eu/tneitzel/rmg/operations/MethodGuesser.java b/src/eu/tneitzel/rmg/operations/MethodGuesser.java index d6b7915..238677f 100644 --- a/src/eu/tneitzel/rmg/operations/MethodGuesser.java +++ b/src/eu/tneitzel/rmg/operations/MethodGuesser.java @@ -53,6 +53,7 @@ public class MethodGuesser private List clientList; private List knownClientList; private List> candidateSets; + private Set invocationHolders; private List> invocationHolderSets; /** @@ -77,7 +78,7 @@ public MethodGuesser(UnicastWrapper[] remoteObjects, Set candid if (SpringRemotingWrapper.containsSpringRemotingClient(remoteObjects)) { - Set invocationHolders = SpringRemotingWrapper.getInvocationHolders(candidates); + invocationHolders = SpringRemotingWrapper.getInvocationHolders(candidates); invocationHolderSets = RMGUtils.splitSet(invocationHolders, RMGOption.THREADS.getValue()); } @@ -87,7 +88,22 @@ public MethodGuesser(UnicastWrapper[] remoteObjects, Set candid } this.clientList = initClientList(remoteObjects); - this.progressBar = new ProgressBar(candidates.size() * clientList.size(), 37); + int workCount = 0; + + for (RemoteObjectClient client : clientList) + { + if (client.remoteObject instanceof SpringRemotingWrapper) + { + workCount += invocationHolders.size(); + } + + else + { + workCount += candidates.size(); + } + } + + this.progressBar = new ProgressBar(workCount, 37); } /** From f24fb734c207f8b2a451ae017783511fcadaebfb Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Thu, 14 Dec 2023 20:32:38 +0100 Subject: [PATCH 55/60] Add test cases for Spring Remoting --- tests/spring/spring.yml | 22 +++++++++++++ tests/spring/tests/call.yml | 60 ++++++++++++++++++++++++++++++++++++ tests/spring/tests/enum.yml | 35 +++++++++++++++++++++ tests/spring/tests/guess.yml | 31 +++++++++++++++++++ tests/tricot.yml | 4 +++ 5 files changed, 152 insertions(+) create mode 100644 tests/spring/spring.yml create mode 100644 tests/spring/tests/call.yml create mode 100644 tests/spring/tests/enum.yml create mode 100644 tests/spring/tests/guess.yml diff --git a/tests/spring/spring.yml b/tests/spring/spring.yml new file mode 100644 index 0000000..f57ebf3 --- /dev/null +++ b/tests/spring/spring.yml @@ -0,0 +1,22 @@ +tester: + title: Spring Remoting Tests + description: |- + 'Launches some tests for Spring Remoting based endpoints' + + id: '005' + groups: + - spring + + +containers: + - name: 'spring-remoting-server' + image: 'ghcr.io/qtc-de/remote-method-guesser/spring-remoting-server:1.0' + volumes: + - '${volume}:${volume-d}' + aliases: + DOCKER-spring-remoting-server-IP: DOCKER-IP + DOCKER-spring-remoting-server-GATEWAY: DOCKER-GW + + +testers: + - ./tests/* diff --git a/tests/spring/tests/call.yml b/tests/spring/tests/call.yml new file mode 100644 index 0000000..0c4679d --- /dev/null +++ b/tests/spring/tests/call.yml @@ -0,0 +1,60 @@ +tester: + title: Calling Tests + description: |- + Perform tests for calling methods on Spring Remoting + + id: '005-003' + groups: + - call + id_pattern: '005-003-{:03}' + + +variables: + file-exec: spring-remoting-execute.txt + file-system: spring-remoting-system.txt + + +tests: + - title: Execute Call + description: |- + Invokes the execute function on the spring remoting interface + + command: + - rmg + - call + - ${TARGET-SPRING} + - '"touch ${volume-d}/${file-exec}"' + - --bound-name + - spring-remoting + - --signature + - 'void execute(String dummy)' + - ${OPTIONS} + + validators: + - error: False + - file_exists: + cleanup: True + files: + - '${volume}/${file-exec}' + + - title: System Call + description: |- + Invokes the system function on the spring remoting interface + + command: + - rmg + - call + - ${TARGET-SPRING} + - '"touch", new String[] { "${volume-d}/${file-system}" }' + - --bound-name + - spring-remoting + - --signature + - 'void system(String command, String[] args)' + - ${OPTIONS} + + validators: + - error: False + - file_exists: + cleanup: True + files: + - '${volume}/${file-system}' diff --git a/tests/spring/tests/enum.yml b/tests/spring/tests/enum.yml new file mode 100644 index 0000000..50b3468 --- /dev/null +++ b/tests/spring/tests/enum.yml @@ -0,0 +1,35 @@ +tester: + title: Enumeration Tests + description: |- + Perform tests on the enum action for Spring Remoting + + id: '005-001' + groups: + - enum + id_pattern: '005-001-{:03}' + + +tests: + - title: RMI Server Enumeration + description: |- + Plain enum call. This call should detect that spring remoting is used + and should display the actual implemented interface instead of the + Spring Remoting interface + + command: + - rmg + - enum + - ${TARGET-SPRING} + - ${OPTIONS} + + validators: + - error: False + + - contains: + description: |- + Check whether Spring Remoting is detected and whether the real + interface class is correctly dispalyed + values: + - 'spring-remoting' + - 'org.springframework.remoting.rmi.RmiInvocationHandler (known class: Spring RmiInvocationHandler)' + - 'Spring Remoting Interface: eu.tneitzel.rmg.springremoting.ServerOperations (unknown class)' diff --git a/tests/spring/tests/guess.yml b/tests/spring/tests/guess.yml new file mode 100644 index 0000000..6ce81a1 --- /dev/null +++ b/tests/spring/tests/guess.yml @@ -0,0 +1,31 @@ +tester: + title: Guessing Tests + description: |- + Test method guessing on Spring Remoting endpoints + + id: '005-002' + groups: + - guess + id_pattern: '005-002-{:03}' + + +tests: + - title: Plain Guess + description: |- + Perform method guessing on a Spring Remoting endpoint + + command: + - rmg + - guess + - ${TARGET-SPRING} + - --verbose + - ${OPTIONS} + + validators: + - error: False + - contains: + values: + - '[ spring-remoting ] HIT! Method with signature ??? system(String dummy, String[] dummy2) exists!' + - '[ spring-remoting ] HIT! Method with signature ??? execute(String dummy) exists!' + - '--> ??? system(String dummy, String[] dummy2)' + - '--> ??? execute(String dummy)' diff --git a/tests/tricot.yml b/tests/tricot.yml index 6768595..faf25cb 100644 --- a/tests/tricot.yml +++ b/tests/tricot.yml @@ -29,6 +29,9 @@ variables: - ${DOCKER-IP} - 1090 - --ssl + TARGET-SPRING: + - ${DOCKER-IP} + - 1099 TARGET-ACT: - ${DOCKER-IP} - 1098 @@ -59,3 +62,4 @@ testers: - ./jdk9/jdk9.yml - ./jdk11/jdk11.yml - ./generic/generic.yml + - ./spring/spring.yml From 779e4b0b319bccdb0c79caa53aa44e5248f6270c Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Thu, 14 Dec 2023 21:05:08 +0100 Subject: [PATCH 56/60] Improve exception handling during method guessing In some configurations, stream corruptions can occur during method guessing with multiple threads. This behavior seems to be non deterministically and was not fully understood yet. However, even on affected configurations, the miss rate is roughly at 1/3000 methods that fail. For this reason, we catch the resulting exceptions for now and only display warnings if running in verbose mode. --- .../rmg/operations/MethodGuesser.java | 69 +++++++++++++++++-- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/src/eu/tneitzel/rmg/operations/MethodGuesser.java b/src/eu/tneitzel/rmg/operations/MethodGuesser.java index 238677f..da4737f 100644 --- a/src/eu/tneitzel/rmg/operations/MethodGuesser.java +++ b/src/eu/tneitzel/rmg/operations/MethodGuesser.java @@ -440,6 +440,25 @@ public void run() } } + catch (java.rmi.UnmarshalException e) + { + /* + * When running with multiple threads, from time to time, stream corruption can be observed. + * This seems to be non deterministically and only appears in certain setups. In my current + * setup, it seems always to break on the "String selectSurname(String email)" method. In + * future, this should be debugged. However, as in a run of 3000 methods this only occurs one + * or two times, it is probably not that important. + */ + if (RMGOption.GLOBAL_VERBOSE.getBool()) + { + String info = "Caught unexpected " + e.getClass().getName() + " while guessing the " + candidate.getSignature() + "method.\n" + +"[-]" + Logger.getIndent() + "This occurs sometimes when guessing with multiple threads.\n" + +"[-]" + Logger.getIndent() + "You can retry with --threads 1 or just ignore the exception."; + Logger.eprintlnBlue(info); + ExceptionHandler.showStackTrace(e); + } + } + catch(Exception e) { /* @@ -449,11 +468,11 @@ public void run() e.printStackTrace(new PrintWriter(writer)); String info = "Caught unexpected " + e.getClass().getName() + " during method guessing.\n" - +"Please report this to improve rmg :)\n" - +"Stack-Trace:\n" + +"[-]" + Logger.getIndent() + "Please report this to improve rmg :)\n" + +"[-]" + Logger.getIndent() + "Stack-Trace:\n" +writer.toString(); - Logger.println(info); + Logger.eprintlnBlue(info); } finally @@ -557,6 +576,25 @@ public void run() */ } + else if (cause instanceof java.rmi.UnmarshalException) + { + /* + * When running with multiple threads, from time to time, stream corruption can be observed. + * This seems to be non deterministically and only appears in certain setups. In my current + * setup, it seems always to break on the "String selectSurname(String email)" method. In + * future, this should be debugged. However, as in a run of 3000 methods this only occurs one + * or two times, it is probably not that important. + */ + if (RMGOption.GLOBAL_VERBOSE.getBool()) + { + String info = "Caught unexpected " + e.getClass().getName() + " while guessing the " + SpringRemotingWrapper.getSignature(invocationHolder.getCandidate()) + " method.\n" + +"[-]" + Logger.getIndent() + "This occurs sometimes when guessing with multiple threads.\n" + +"[-]" + Logger.getIndent() + "You can retry with --threads 1 or just ignore the exception."; + Logger.eprintlnBlue(info); + ExceptionHandler.showStackTrace(e); + } + } + else { /* @@ -566,6 +604,25 @@ public void run() } } + catch (java.rmi.UnmarshalException e) + { + /* + * When running with multiple threads, from time to time, stream corruption can be observed. + * This seems to be non deterministically and only appears in certain setups. In my current + * setup, it seems always to break on the "String selectSurname(String email)" method. In + * future, this should be debugged. However, as in a run of 3000 methods this only occurs one + * or two times, it is probably not that important. + */ + if (RMGOption.GLOBAL_VERBOSE.getBool()) + { + String info = "Caught unexpected " + e.getClass().getName() + " while guessing the " + SpringRemotingWrapper.getSignature(invocationHolder.getCandidate()) + " method.\n" + +"[-]" + Logger.getIndent() + "This occurs sometimes when guessing with multiple threads.\n" + +"[-]" + Logger.getIndent() + "You can retry with --threads 1 or just ignore the exception."; + Logger.eprintlnBlue(info); + ExceptionHandler.showStackTrace(e); + } + } + catch(Exception e) { /* @@ -600,8 +657,8 @@ private void unexpectedError(RemoteInvocationHolder invoHolder, Exception e) e.printStackTrace(new PrintWriter(writer)); info = "Caught unexpected " + e.getClass().getName() + " during method guessing.\n" - +"Please report this to improve rmg :)\n" - +"Stack-Trace:\n" + +"[-]" + Logger.getIndent() + "Please report this to improve rmg :)\n" + +"[-]" + Logger.getIndent() + "Stack-Trace:\n" +writer.toString(); } @@ -610,7 +667,7 @@ private void unexpectedError(RemoteInvocationHolder invoHolder, Exception e) info = "Spring Remoting call did not cause an exception. This is not expected."; } - Logger.println(info); + Logger.eprintlnBlue(info); } } } From ddb5102a238908b12c0726c447943bc257fc518e Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Thu, 14 Dec 2023 21:16:09 +0100 Subject: [PATCH 57/60] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee7704d..4855130 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,12 +12,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Add support for dynamically created socket factory classes ([docs](/docs/rmg/dynamic-socket-factories.md)) * Add support for method guessing on spring-remoting endpoints ([docs](/docs/rmg/spring-remoting.md)) +* Add a *Spring Remoting* example server ([src](docker/spring-remoting/), [package](https://github.com/qtc-de/remote-method-guesser/pkgs/container/remote-method-guesser%2Fspring-remoting-server)) ### Changed * Changed the namespace of the project from `de.qtc` to `eu.tneitzel` * Fix leak of local ysoserial path (e30f52c) * The GenericPrint plugin is now included in *rmg* per default (b09e9a5) +* Stream corruption errors during method guessing are only displayed if `--verbose` is used ## [4.4.1] - Jun 22, 2023 From a1e270aee5856af6667a4eb3580210289947a5c4 Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Thu, 14 Dec 2023 21:25:57 +0100 Subject: [PATCH 58/60] Add README.md for spring-remoting server --- docker/spring-remoting/README.md | 92 ++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 docker/spring-remoting/README.md diff --git a/docker/spring-remoting/README.md b/docker/spring-remoting/README.md new file mode 100644 index 0000000..9a58128 --- /dev/null +++ b/docker/spring-remoting/README.md @@ -0,0 +1,92 @@ +### Spring Remoting Example Server + +---- + +The *Spring Remoting* example server provided by this repository can be used to test the +*Spring Remoting* related features of *remote-method-guesser*. You can either build the +container from source or pull it from [GitHub Packages](https://github.com/qtc-de/remote-method-guesser/pkgs/container/remote-method-guesser%2Fspring-remoting-server). + +* To build from source, just clone the repository, switch to the [docker directory](/docker/spring-remoting) and run `docker build .`. +* To load the container from the *GitHub Container Registry* just use the corresponding pull command: + ```console + [user@host ~]$ docker pull ghcr.io/qtc-de/remote-method-guesser/spring-remoting-server:1.0 + ``` + + +### Configuration Details + +---- + +The *Spring Remoting* example server exposes an *RMI* registry port on `tcp/1099`. Scanning this +port with *remote-method-guesser* version *v5.0.0* or higher should provide the following results: + +```console +[user@host ~]$ rmg enum 172.17.0.2 1099 +[+] RMI registry bound names: +[+] +[+] - spring-remoting +[+] --> org.springframework.remoting.rmi.RmiInvocationHandler (known class: Spring RmiInvocationHandler) +[+] Spring Remoting Interface: eu.tneitzel.rmg.springremoting.ServerOperations (unknown class) +[+] Endpoint: iinsecure.example:33779 CSF: RMISocketFactory ObjID: [43861eb7:18c69d6d219:-7fff, 8901450872606600476] +[+] +[+] RMI server codebase enumeration: +[+] +[+] - The remote server does not expose any codebases. +[+] +[+] RMI server String unmarshalling enumeration: +[+] +[+] - Server complained that object cannot be casted to java.lang.String. +[+] --> The type java.lang.String is unmarshalled via readString(). +[+] Configuration Status: Current Default +[+] +[+] RMI server useCodebaseOnly enumeration: +[+] +[+] - RMI registry uses readString() for unmarshalling java.lang.String. +[+] This prevents useCodebaseOnly enumeration from remote. +[+] +[+] RMI registry localhost bypass enumeration (CVE-2019-2684): +[+] +[+] - Registry rejected unbind call cause it was not sent from localhost. +[+] Vulnerability Status: Non Vulnerable +[+] +[+] RMI Security Manager enumeration: +[+] +[+] - Caught Exception containing 'no security manager' during RMI call. +[+] --> The server does not use a Security Manager. +[+] Configuration Status: Current Default +[+] +[+] RMI server JEP290 enumeration: +[+] +[+] - DGC rejected deserialization of java.util.HashMap (JEP290 is installed). +[+] Vulnerability Status: Non Vulnerable +[+] +[+] RMI registry JEP290 bypass enumeration: +[+] +[+] - RMI registry uses readString() for unmarshalling java.lang.String. +[+] This prevents JEP 290 bypass enumeration from remote. +[+] +[+] RMI ActivationSystem enumeration: +[+] +[+] - Caught NoSuchObjectException during activate call (activator not present). +[+] Configuration Status: Current Default +``` + +As one can see in the output above, the actual exposed remote object implements `org.springframework.remoting.rmi.RmiInvocationHandler`, +as it is always the case for *Spring Remoting*. The underlying interface type however is `eu.tneitzel.rmg.springremoting.ServerOperations`. +This interface supports the following methods: + +```java +package eu.tneitzel.rmg.springremoting; + +public interface ServerOperations +{ + String notRelevant(); + String execute(String cmd); + String system(String cmd, String[] args); + String upload(int size, int id, byte[] content); + int math(int num1, int num2); +} +``` + +If you want to learn more about *Spring Remoting* and the associated features of *remote-method-guesser*, +it is recommended to read the corresponding [documentation article](/docs/rmg/spring-remoting.md). From b82bf6f3d21ffa9e5dbd4790f608e4b07062fa5b Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 19 Dec 2023 12:33:34 +0100 Subject: [PATCH 59/60] Make pom.xml maven compliant --- pom.xml | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index ad26527..d0479ab 100644 --- a/pom.xml +++ b/pom.xml @@ -4,10 +4,34 @@ eu.tneitzel.rmg remote-method-guesser - remote-method-guesser - jar 5.0.0 - Identify common misconfigurations on Java RMI endpoints + jar + + ${project.artifactId} + Java RMI Vulnerability Scanner + https://github.com/qtc-de/remote-method-guesser + + + + GPL-v3.0 + http://www.gnu.org/licenses/gpl-3.0.txt + + + + + + qtc-de + Tobias Neitzel + secure@tneitzel.eu + https://tneitzel.eu/ + + + + + scm:git:git://github.com/qtc-de/remote-method-guesser.git + scm:git:ssh://github.com:qtc-de/remote-method-guesser.git + https://github.com/qtc-de/remote-method-guesser/tree/master + UTF-8 From f6ea9b02c267ace4835f615181e53fcdd05a491b Mon Sep 17 00:00:00 2001 From: Tobias Neitzel Date: Tue, 19 Dec 2023 12:58:40 +0100 Subject: [PATCH 60/60] Adjust group ID --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d0479ab..5232c95 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 - eu.tneitzel.rmg + eu.tneitzel remote-method-guesser 5.0.0 jar