Java Remote Method Invocation, or Java RMI, є об'єктно-орієнтованим RPC механізмом, який дозволяє об'єкту, розташованому в одній Java віртуальній машині, викликати методи на об'єкті, розташованому в іншій Java віртуальній машині. Це дозволяє розробникам писати розподілені програми, використовуючи об'єктно-орієнтовану парадигму. Коротке введення в Java RMI з наступальної перспективи можна знайти в цьому виступі на blackhat.
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 Registry та Activation System) прив'язані до загальних портів. Віддалені об'єкти, які реалізують фактичний RMI додаток, зазвичай прив'язані до випадкових портів, як показано у виведенні вище.
nmap іноді має проблеми з ідентифікацією SSL захищених RMI сервісів. Якщо ви натрапите на невідомий ssl сервіс на загальному RMI порту, вам слід провести подальше розслідування.
Компоненти RMI
Простими словами, Java RMI дозволяє розробнику зробити Java об'єкт доступним в мережі. Це відкриває TCP порт, до якого клієнти можуть підключатися та викликати методи на відповідному об'єкті. Незважаючи на те, що це звучить просто, існує кілька викликів, які Java RMI потрібно вирішити:
Щоб надіслати виклик методу через Java RMI, клієнти повинні знати IP-адресу, порт прослуховування, реалізований клас або інтерфейс та ObjID цільового об'єкта ( ObjID - це унікальний та випадковий ідентифікатор, який створюється, коли об'єкт стає доступним в мережі. Він потрібен, оскільки Java RMI дозволяє кільком об'єктам прослуховувати один і той же TCP порт).
Віддалені клієнти можуть виділяти ресурси на сервері, викликаючи методи на відкритому об'єкті. Java віртуальна машина повинна відстежувати, які з цих ресурсів все ще використовуються, а які можуть бути зібрані сміттям.
Перший виклик вирішується RMI реєстром, який в основному є службою імен для Java RMI. Сам RMI реєстр також є RMI сервісом, але реалізований інтерфейс та ObjID є фіксованими та відомими всім RMI клієнтам. Це дозволяє RMI клієнтам використовувати RMI реєстр, просто знаючи відповідний TCP порт.
Коли розробники хочуть зробити свої Java об'єкти доступними в мережі, вони зазвичай прив'язують їх до RMI реєстру. Реєстр зберігає всю інформацію, необхідну для підключення до об'єкта (IP-адреса, порт прослуховування, реалізований клас або інтерфейс та значення ObjID) і робить її доступною під зрозумілим ім'ям ( прив'язане ім'я). Клієнти, які хочуть використовувати RMI сервіс, запитують RMI реєстр про відповідне прив'язане ім'я, і реєстр повертає всю необхідну інформацію для підключення. Таким чином, ситуація в основному така ж, як і з звичайною DNS службою. Наступний список показує невеликий приклад:
importjava.rmi.registry.Registry;importjava.rmi.registry.LocateRegistry;importlab.example.rmi.interfaces.RemoteService;publicclassExampleClient {privatestaticfinalString remoteHost ="172.17.0.2";privatestaticfinalString boundName ="remote-service";publicstaticvoidmain(String[] args){try {Registry registry =LocateRegistry.getRegistry(remoteHost); // Connect to the RMI registryRemoteService ref = (RemoteService)registry.lookup(boundName); // Lookup the desired bound nameString response =ref.remoteMethod(); // Call a remote method} catch( Exception e) {e.printStackTrace();}}}
Другий з вищезгаданих викликів вирішується за допомогою Distributed Garbage Collector (DGC). Це ще одна RMI service з відомим значенням ObjID і вона доступна на практично кожному RMI endpoint. Коли RMI client починає використовувати RMI service, він надсилає інформацію до DGC, що відповідний remote object використовується. DGC може відстежувати кількість посилань і здатний очищати невикористовувані об'єкти.
Разом з застарілою Activation System, це три стандартні компоненти Java RMI:
RMI Registry (ObjID = 0)
Activation System (ObjID = 1)
Distributed Garbage Collector (ObjID = 2)
Стандартні компоненти Java RMI відомі як вектори атак протягом досить тривалого часу, і в застарілих версіях Java існує кілька вразливостей. З точки зору атакуючого, ці стандартні компоненти є цікавими, оскільки вони реалізують відомі класи / інтерфейси, і з ними легко взаємодіяти. Ця ситуація відрізняється для кастомних RMI services. Щоб викликати метод на remote object, вам потрібно заздалегідь знати відповідний підпис методу. Без знання існуючого підпису методу немає способу зв'язатися з RMI service.
RMI Enumeration
remote-method-guesser є сканером вразливостей Java RMI, який здатний автоматично виявляти загальні RMI vulnerabilities. Коли ви виявляєте RMI endpoint, вам слід спробувати:
$ 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, можна використовувати для визначення часу безперервної роботи служби. Це може дозволити виявити інші вразливості:
Навіть коли під час перерахунку не було виявлено вразливостей, доступні RMI сервіси все ще можуть відкривати небезпечні функції. Більше того, незважаючи на те, що RMI зв'язок з RMI компонентами за замовчуванням захищений фільтрами десеріалізації, при спілкуванні з користувацькими RMI сервісами такі фільтри зазвичай відсутні. Знання дійсних підписів методів на RMI сервісах є, отже, цінним.
На жаль, Java RMI не підтримує перерахунок методів на віддалених об'єктах. Тим не менш, можливо здійснити брутфорс підписів методів за допомогою інструментів, таких як remote-method-guesser або rmiscout:
Окрім вгадування, вам також слід шукати в пошукових системах або GitHub інтерфейс або навіть реалізацію зустрінутого RMI сервісу. Bound name та назва реалізованого класу або інтерфейсу можуть бути корисними тут.
Відомі інтерфейси
remote-method-guesser позначає класи або інтерфейси як known, якщо вони перераховані в внутрішній базі даних інструменту відомих RMI services. У цих випадках ви можете використовувати дію known, щоб отримати більше інформації про відповідний RMI service:
$ 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
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, щоб легко створювати та автоматизувати робочі процеси, які підтримуються найсучаснішими інструментами спільноти.
Отримайте доступ сьогодні: