L'invocazione remota di metodi Java, o Java RMI, è un meccanismo RPC orientato agli oggetti che consente a un oggetto situato in una macchina virtuale Java di chiamare metodi su un oggetto situato in un'altra macchina virtuale Java. Questo consente agli sviluppatori di scrivere applicazioni distribuite utilizzando un paradigma orientato agli oggetti. Un'introduzione breve a Java RMI da una prospettiva offensiva può essere trovata in questo talk di blackhat.
Porta predefinita: 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
Di solito, solo i componenti predefiniti Java RMI (il RMI Registry e il Activation System) sono associati a porte comuni. Gli oggetti remoti che implementano l'applicazione RMI effettiva sono solitamente associati a porte casuali come mostrato nell'output sopra.
nmap ha a volte problemi nell'identificare i servizi RMI protetti da SSL. Se incontri un servizio ssl sconosciuto su una porta RMI comune, dovresti indagare ulteriormente.
Componenti RMI
Per dirla in termini semplici, Java RMI consente a uno sviluppatore di rendere un oggetto Java disponibile sulla rete. Questo apre una porta TCP a cui i client possono connettersi e chiamare metodi sull'oggetto corrispondente. Anche se sembra semplice, ci sono diverse sfide che Java RMI deve affrontare:
Per inviare una chiamata di metodo tramite Java RMI, i client devono conoscere l'indirizzo IP, la porta in ascolto, la classe o interfaccia implementata e l'ObjID dell'oggetto target (l'ObjID è un identificatore unico e casuale che viene creato quando l'oggetto viene reso disponibile sulla rete. È necessario perché Java RMI consente a più oggetti di ascoltare sulla stessa porta TCP).
I client remoti possono allocare risorse sul server invocando metodi sull'oggetto esposto. La Java virtual machine deve tenere traccia di quali di queste risorse sono ancora in uso e quali possono essere raccolte come spazzatura.
La prima sfida è risolta dal RMI registry, che è fondamentalmente un servizio di denominazione per Java RMI. Il RMI registry stesso è anche un servizio RMI, ma l'interfaccia implementata e l'ObjID sono fissi e conosciuti da tutti i client RMI. Questo consente ai client RMI di consumare il RMI registry semplicemente conoscendo la corrispondente porta TCP.
Quando gli sviluppatori vogliono rendere i loro oggetti Java disponibili all'interno della rete, di solito li associano a un RMI registry. Il registry memorizza tutte le informazioni necessarie per connettersi all'oggetto (indirizzo IP, porta in ascolto, classe o interfaccia implementata e valore ObjID) e le rende disponibili sotto un nome leggibile dall'uomo (il bound name). I client che vogliono consumare il servizio RMI chiedono al RMI registry il corrispondente bound name e il registry restituisce tutte le informazioni necessarie per connettersi. Pertanto, la situazione è fondamentalmente la stessa di un normale servizio DNS. Il seguente elenco mostra un piccolo esempio:
importjava.rmi.registry.Registry;importjava.rmi.registry.LocateRegistry;importlab.example.rmi.interfaces.RemoteService;publicclassExampleClient {privatestaticfinalString remoteHost ="172.17.0.2";privatestaticfinalString boundName ="remote-service";publicstaticvoidmain(String[] args){try {Registry registry =LocateRegistry.getRegistry(remoteHost); // Connect to the RMI registryRemoteService ref = (RemoteService)registry.lookup(boundName); // Lookup the desired bound nameString response =ref.remoteMethod(); // Call a remote method} catch( Exception e) {e.printStackTrace();}}}
La seconda delle sfide sopra menzionate è risolta dal Distributed Garbage Collector (DGC). Questo è un altro RMI service con un valore ObjID ben noto ed è disponibile praticamente su ogni RMI endpoint. Quando un RMI client inizia a utilizzare un RMI service, invia un'informazione al DGC che il corrispondente remote object è in uso. Il DGC può quindi tenere traccia del conteggio dei riferimenti ed è in grado di pulire gli oggetti non utilizzati.
Insieme al deprecato Activation System, questi sono i tre componenti predefiniti di Java RMI:
Il RMI Registry (ObjID = 0)
L' Activation System (ObjID = 1)
Il Distributed Garbage Collector (ObjID = 2)
I componenti predefiniti di Java RMI sono stati noti vettori di attacco per un bel po' di tempo e esistono più vulnerabilità nelle versioni obsolete di Java. Dal punto di vista di un attaccante, questi componenti predefiniti sono interessanti, perché implementano classi / interfacce note ed è facilmente possibile interagire con essi. Questa situazione è diversa per i RMI services personalizzati. Per chiamare un metodo su un remote object, è necessario conoscere in anticipo la corrispondente firma del metodo. Senza conoscere una firma di metodo esistente, non c'è modo di comunicare con un RMI service.
RMI Enumeration
remote-method-guesser è un Java RMI vulnerability scanner che è in grado di identificare automaticamente le comuni RMI vulnerabilities. Ogni volta che identifichi un RMI endpoint, dovresti provarlo:
$ 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
L'output dell'azione di enumerazione è spiegato in maggior dettaglio nelle pagine di documentazione del progetto. A seconda dell'esito, dovresti cercare di verificare le vulnerabilità identificate.
I valori ObjID visualizzati da remote-method-guesser possono essere utilizzati per determinare il tempo di attività del servizio. Questo può consentire di identificare altre vulnerabilità:
Anche quando non sono state identificate vulnerabilità durante l'enumerazione, i servizi RMI disponibili potrebbero comunque esporre funzioni pericolose. Inoltre, nonostante la comunicazione RMI con i componenti predefiniti RMI sia protetta da filtri di deserializzazione, quando si parla con servizi RMI personalizzati, tali filtri di solito non sono presenti. Conoscere le firme dei metodi validi sui servizi RMI è quindi prezioso.
Sfortunatamente, Java RMI non supporta l'enumerazione dei metodi sugli oggetti remoti. Detto ciò, è possibile forzare le firme dei metodi con strumenti come remote-method-guesser o rmiscout:
Apart from guessing, you should also look in search engines or GitHub for the interface or even the implementation of an encountered RMI service. The bound name and the name of the implemented class or interface can be helpful here.
Interfacce Conosciute
remote-method-guesser segna classi o interfacce come known se sono elencate nel database interno dello strumento dei RMI services conosciuti. In questi casi puoi usare l'azione known per ottenere ulteriori informazioni sul corrispondente RMI service:
$ 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
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}
Usa Trickest per costruire e automatizzare flussi di lavoro alimentati dagli strumenti della comunità più avanzati al mondo.
Accedi oggi: