-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 6748098
Showing
21 changed files
with
3,705 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/build/ | ||
/.gradle/ | ||
/.idea/ | ||
*.class |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2020 BishopFox | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<p align="center"> | ||
<img src="assets/RMIScout.png" width=600/> | ||
</p> | ||
|
||
# | ||
|
||
|
||
|
||
![License](https://img.shields.io/badge/license-MIT-lightgrey.svg) | ||
![Python version](https://img.shields.io/badge/java-8%2b-blue.svg) | ||
|
||
### Description | ||
|
||
RMIScout performs wordlist and bruteforce attacks against exposed Java RMI interfaces to safely guess method signatures without invocation. | ||
|
||
On misconfigured servers, any known RMI signature using non-primitive types (e.g., `java.lang.String`), 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](https://i.blackhat.com/eu-19/Wednesday/eu-19-An-Far-Sides-Of-Java-Remote-Protocols.pdf). | ||
|
||
RMIScout integrates with [ysoserial](https://github.com/frohoff/ysoserial/) and [GadgetProbe](https://github.com/bishopfox/gadgetprobe) to perform deserialization attacks against services incorrectly configuring process-wide serialization filters ([JEP 290](https://openjdk.java.net/jeps/290)). | ||
|
||
<p align="center"> | ||
<img src="assets/wordlist_attack.png" width=800/> | ||
</p> | ||
|
||
### Motivation | ||
|
||
I wanted a tool to do the following tasks: | ||
1. Provide wordlist and text-based bruteforce strategies instead of bruteforcing a 64-bit method hash. | ||
2. Identify RMI methods without invoking them. | ||
3. Provide a simple way to exploit the known issue of unsafe RMI parameter unmarshalling and integrate with ysoserial or payloads implementing `ysoserial.payloads.ObjectPayload`. | ||
4. Integrate GadgetProbe to identify remote classes to help identify relevant software and construct gadget chains. | ||
|
||
To start off your search, the included `lists/prototypes.txt` wordlist is a deduplicated wordlist from 15,000 RMI prototypes found in OSS projects across GitHub. Feel free to submit a PR to include more :) | ||
|
||
### How it works | ||
|
||
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. | ||
|
||
Read a [full technical writeup here](https://know.bishopfox.com/research/rmiscout). | ||
|
||
### Usage | ||
|
||
``` | ||
# Perform wordlist-attack against remote RMI service using wordlist of function prototypes | ||
./rmiscout.sh wordlist -i prototypes.txt <host> <port> | ||
# Bruteforce using method wordlist and other options | ||
./rmiscout.sh bruteforce -i lists/methods.txt -r void,boolean,long -p String,int -l 1,4 <host> <port> | ||
# Swap object-derived types with the specified ysoserial payload and payload parameter | ||
./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> | ||
# Use GadgetProbe and a known signature to bruteforce classes on the remote classpath | ||
./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> | ||
``` | ||
|
||
|
||
### Building and Running | ||
|
||
Use the included `rmiscout.sh` script to automatically build the project and as a convenient wrapper around `java -jar` syntax: | ||
```bash | ||
./rmiscout.sh wordlist -i prototypes.txt <host> <port> | ||
``` | ||
|
||
Alternatively, build the project manually and use traditional `java -jar` syntax: | ||
|
||
```bash | ||
# Manually build JAR | ||
./gradlew shadowJar | ||
|
||
java -jar build/libs/rmiscout-1.0-SNAPSHOT-all.jar wordlist -i prototypes.txt <host> <port> | ||
``` | ||
|
||
|
||
### Try It out | ||
Run the demo RMI server. Try out the included `demo/wordlist.txt`. | ||
```bash | ||
cd demo | ||
./start.sh | ||
``` | ||
### Author | ||
|
||
Twitter: [@BumbleSec](https://twitter.com/theBumbleSec) | ||
|
||
GitHub: [the-bumble](https://github.com/the-bumble/) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
plugins { | ||
id 'java' | ||
id 'application' | ||
id 'com.github.johnrengelman.shadow' version '2.0.4' | ||
} | ||
|
||
group 'com.bishopfox.rmiscout' | ||
version '1.0-SNAPSHOT' | ||
|
||
mainClassName = 'com.bishopfox.rmiscout.RMIScout' | ||
|
||
tasks.withType(JavaCompile) { | ||
options.warnings = false | ||
} | ||
|
||
repositories { | ||
mavenCentral() | ||
maven { url "https://jitpack.io" } | ||
maven { url "https://repo.spring.io/plugins-release/" } | ||
} | ||
|
||
dependencies { | ||
testCompile group: 'junit', name: 'junit', version: '4.12' | ||
compile group: 'org.javassist', name: 'javassist', version: '3.27.0-GA' | ||
compile group: 'net.sourceforge.argparse4j', name: 'argparse4j', version: '0.8.1' | ||
|
||
implementation 'com.github.frohoff:ysoserial:master-SNAPSHOT' | ||
implementation 'com.github.BishopFox:GadgetProbe:master-SNAPSHOT' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import java.rmi.Remote; | ||
import java.rmi.RemoteException; | ||
import java.util.*; | ||
|
||
public interface Hello extends Remote { | ||
String restart() throws RemoteException; | ||
String sayHello(String name) throws RemoteException; | ||
String sayNumber(int name) throws RemoteException; | ||
boolean login(String email, String password) throws RemoteException; | ||
|
||
String sayTest1(int name) throws RemoteException; | ||
String sayTest2(byte name) throws RemoteException; | ||
String sayTest3(short name) throws RemoteException; | ||
String sayTest4(long name) throws RemoteException; | ||
String sayTest5(char name) throws RemoteException; | ||
String sayTest6(boolean name) throws RemoteException; | ||
String sayTest7(float name) throws RemoteException; | ||
String sayTest8(double name) throws RemoteException; | ||
String sayTest9(Map name) throws RemoteException; | ||
String sayTest10(HashMap name) throws RemoteException; | ||
String sayTest11(List name) throws RemoteException; | ||
String sayTest12(Object name) throws RemoteException; | ||
|
||
ArrayList<String> say2things(String name, int test) throws RemoteException; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import java.rmi.registry.Registry; | ||
import java.rmi.registry.LocateRegistry; | ||
import java.rmi.RemoteException; | ||
import java.rmi.server.UnicastRemoteObject; | ||
import java.util.*; | ||
|
||
public class Server implements Hello { | ||
|
||
public Server() {} | ||
|
||
public String sayHello() { return "Remote Executed!"; } | ||
public String restart() { return "Remote Executed!"; } | ||
public boolean login(String email, String password) { return true; } | ||
public String sayHello(String name) { return "Remote Executed!"; } | ||
public String sayNumber(int name) { return "Remote Executed!"; } | ||
public String sayTest1(int name) { return "Remote Executed!"; } | ||
public String sayTest2(byte name) { return "Remote Executed!"; } | ||
public String sayTest3(short name) { return "Remote Executed!"; } | ||
public String sayTest4(long name) { return "Remote Executed!"; } | ||
public String sayTest5(char name) { return "Remote Executed!"; } | ||
public String sayTest6(boolean name) { return "Remote Executed!"; } | ||
public String sayTest7(float name) { return "Remote Executed!"; } | ||
public String sayTest8(double name) { return "Remote Executed!"; } | ||
public String sayTest9(Map name) { return "Remote Executed!"; } | ||
public String sayTest10(HashMap name) { return "Remote Executed!"; } | ||
public String sayTest11(List name) { return "Remote Executed!"; } | ||
public String sayTest12(Object name) { return "Remote Executed!"; } | ||
public ArrayList<String> say2things(String name, int test) { return new ArrayList<String>(); } | ||
|
||
public static void main(String args[]) { | ||
|
||
try { | ||
Server obj = new Server(); | ||
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0); | ||
|
||
Registry registry = LocateRegistry.getRegistry(); | ||
registry.bind("Hello", stub); | ||
|
||
System.err.println("Server ready"); | ||
} catch (Exception e) { | ||
System.err.println("Server exception: " + e.toString()); | ||
e.printStackTrace(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/bin/bash | ||
|
||
rmiregistry & | ||
PID=$! | ||
|
||
javac *.java && java -classpath ./ -Djava.rmi.server.codebase=file:$PWD Server | ||
kill $PID |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
java.util.ArrayList say2things(String test, int test) | ||
String sayTest(Object test) | ||
String sayTest1(int name) | ||
String sayTest2(byte name) | ||
String sayTest3(short name) | ||
String sayTest4(long name) | ||
String sayTest5(char name) | ||
String sayTest6(boolean name) | ||
String sayTest7(float name) | ||
String sayTest8(double name) | ||
String sayTest9(java.util.Map name) | ||
String sayTest10(java.util.HashMap name) | ||
String sayTest11(java.util.List name) | ||
String sayTest12(Object name) | ||
String doesNotExist(String name) | ||
String restart() |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
distributionBase=GRADLE_USER_HOME | ||
distributionPath=wrapper/dists | ||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip | ||
zipStoreBase=GRADLE_USER_HOME | ||
zipStorePath=wrapper/dists |
Oops, something went wrong.