Skip to content

Commit

Permalink
Initial release.
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicky Bloor committed Sep 24, 2017
1 parent fe72ba3 commit 28b8762
Show file tree
Hide file tree
Showing 79 changed files with 9,199 additions and 23 deletions.
50 changes: 28 additions & 22 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
/nbproject/
/build.xml
/manifest.mf
/build/
/dist/
/test/
101 changes: 100 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,101 @@
# BaRMIe
Java RMI enumeration and attack tool.
BaRMIe is a tool for enumerating and attacking Java RMI (Remote Method Invocation) services.

RMI services often expose dangerous functionality without adequate security controls, however RMI services tend to pass under the radar during security assessments due to the lack of effective testing tools. In 2008 Adam Boulton spoke at AppSec USA ([YouTube](https://www.youtube.com/watch?v=owN9EnoLsFY)) and released some RMI attack tools which disappeared soon after, however even with those tools a successful zero-knowledge attack relies on a significant brute force attack (~64-bits/9 quintillion possibilities) being performed over the network.

The goal of BaRMIe is to enable security professionals to identify, attack, and secure insecure RMI services. Using partial RMI interfaces from existing software, BaRMIe can interact directly with those services without first brute forcing 64-bits over the network.

### Disclaimer
BaRMIe was written to aid security professionals in identifying insecure RMI services on systems which the user has prior permission to attack. Unauthorised access to computer systems is illegal and BaRMIe must be used in accordance with all relevant laws. Failure to do so could lead to you being prosecuted. The developers of BaRMIe assume no liability and are not responsible for any misuse or damage caused by this program.

## Usage
Use of BaRMIe is straightforward. Run BaRMIe with no parameters for usage information.

$ java -jar BaRMIe.jar
▄▄▄▄ ▄▄▄ ██▀███ ███▄ ▄███▓ ██▓▓█████
▓█████▄ ▒████▄ ▓██ ▒ ██▒▓██▒▀█▀ ██▒▓██▒▓█ ▀
▒██▒ ▄██▒██ ▀█▄ ▓██ ░▄█ ▒▓██ ▓██░▒██▒▒███
▒██░█▀ ░██▄▄▄▄██ ▒██▀▀█▄ ▒██ ▒██ ░██░▒▓█ ▄
░▓█ ▀█▓ ▓█ ▓██▒░██▓ ▒██▒▒██▒ ░██▒░██░░▒████▒
░▒▓███▀▒ ▒▒ ▓▒█░░ ▒▓ ░▒▓░░ ▒░ ░ ░░▓ ░░ ▒░ ░
▒░▒ ░ ▒ ▒▒ ░ ░▒ ░ ▒░░ ░ ░ ▒ ░ ░ ░ ░
░ ░ ░ ▒ ░░ ░ ░ ░ ▒ ░ ░
░ ░ ░ ░ ░ ░ ░ ░
░ v1.0
Java RMI enumeration tool.
Written by Nicky Bloor (@NickstaDB)

Warning: BaRMIe was written to aid security professionals in identifying the
insecure use of RMI services on systems which the user has prior
permission to attack. BaRMIe must be used in accordance with all
relevant laws. Failure to do so could lead to your prosecution.
The developers assume no liability and are not responsible for any
misuse or damage caused by this program.

Usage:
BaRMIe -enum [options] [host] [port]
Enumerate RMI services on the given endpoint(s).
Note: if -enum is not specified, this is the default mode.
BaRMIe -attack [options] [host] [port]
Enumerate and attack the given target(s).
Options:
--threads The number of threads to use for enumeration (default 10).
--timeout The timeout for blocking socket operations (default 5,000ms).
--targets A file containing targets to scan.
The file should contain a single host or space-separated
host and port pair per line.
Alternatively, all nmap output formats are supported, BaRMIe will
parse nmap output for port 1099, 'rmiregistry', or 'Java RMI'
services to target.
Note: [host] [port] not supported when --targets is used.
Reliability:
A +/- system is used to indicate attack reliability as follows:
[+ ]: Indicates an application-specific attack
[- ]: Indicates a JRE attack
[ + ]: Attack insecure methods (such as 'writeFile' without auth)
[ - ]: Attack Java deserialization (i.e. Object parameters)
[ +]: Does not require non-default dependencies
[ -]: Non-default dependencies are required

Enumeration mode (-enum) extracts details of objects that are exposed through an RMI registry service and lists any known attacks that affect the endpoint.

Attack mode (-attack) first enumerates the given targets, then provides a menu system for launching known attacks against RMI services.

A single target can be specified on the command line. Alternatively BaRMIe can extract targets from a simple text file or nmap output.

## No Vulnerable Targets Identified?
Great! This is your opportunity to help improve BaRMIe! BaRMIe relies on *some* knowledge of the classes exposed over RMI so contributions will go a long way in improving BaRMIe and the security of RMI services.

If you have access to JAR files or source code for the target application then producing an attack is as simple as compiling code against the relevant JAR files. Retrieve the relevant remote object using the *LocateRegistry* and *Registry* classes and call the desired methods. Alternatively look for remote methods that accept arbitrary objects or otherwise non-primitive parameters as these can be used to deliver deserialization payloads. More documentation on attacking RMI and producing attacks for BaRMIe will be made available in the near future.

Alternatively, [get in touch](https://nickbloor.co.uk/contact/), and provide as much detail as possible including BaRMIe -enum output and ideally the relevant JAR files.

## Attack Types
BaRMIe is capable of performing three types of attacks against RMI services. A brief description of each follows. Further technical details will be published in the near future at [https://nickbloor.co.uk/](https://nickbloor.co.uk/). In addition to this, I presented the results of my research at 44CON 2017 and the slides can be found here: [BaRMIe - Poking Java's Back Door](https://www.slideshare.net/NickBloor3/nicky-bloor-barmie-poking-javas-back-door-44con-2017).

### 1. Attacking Insecure Methods
The first and most straightforward method of attacking insecure RMI services is to simply call insecure remote methods. Often dangerous functionality is exposed over RMI which can be triggered by simply retrieving the remote object reference and calling the dangerous method. The following code is an example of this:

//Get a reference to the remote RMI registry service
Registry reg = LocateRegistry.getRegistry(targetHost, targetPort);

//Get a reference to the target RMI object
Foo bar = (Foo)reg.lookup(objectName);

//Call the remote executeCommand() method
bar.executeCommand(cmd);

### 2. Deserialization via Object-type Paraeters
Some RMI services do not expose dangerous functionality, or they implement security controls such as authentication and session management. If the RMI service exposes a method that accepts an arbitrary Object as a parameter then the method can be used as an entry point for deserialization attacks. Some examples of such methods can be seen below:

public void setOption(String name, Object value);
public void addAll(List values);

### 3. Deserialization via Illegal Method Invocation
Due to the use of serialization, and insecure handling of method parameters on the server, it is possible to use any method with non-primitive parameter types as an entry point for deserialization attacks. BaRMIe achieves this by using TCP proxies to modify method parameters at the network level, essentially triggering illegal method invocations. Some examples of vulnerable methods can be seen below:

public void setName(String name);
public Long add(Integer i1, Integer i2);
public void sum(int[] values);

The parameters to each of these methods can be replaced with a deserialization payload as the method invocation passes through a proxy. This attack is possible because Java does not attempt to verify that remote method parameters received over the network are compatible with the actual parameter types before deserializing them.
18 changes: 18 additions & 0 deletions src/axiomsl/server/rmi/FileBrowserStub.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package axiomsl.server.rmi;

import java.io.IOException;
import java.rmi.Remote;
import java.rmi.RemoteException;

/***********************************************************
* FileBrowserStub for AxiomSL attacks.
*
* Written by Nicky Bloor (@NickstaDB).
**********************************************************/
public abstract interface FileBrowserStub extends Remote {
public abstract FileInformation[] listFilesOnServer(String paramString) throws RemoteException;
public abstract byte[] readFile(String paramString, long paramLong, int paramInt) throws IOException;
public abstract void writeFile(String paramString, byte[] paramArrayOfByte) throws IOException;
public abstract boolean deleteFile(String paramString, boolean paramBoolean) throws RemoteException;
public abstract FileInformation getFileInformation(String paramString) throws RemoteException;
}
19 changes: 19 additions & 0 deletions src/axiomsl/server/rmi/FileInformation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package axiomsl.server.rmi;

import java.io.Serializable;

/***********************************************************
* FileInformation class for AxiomSL attacks.
*
* Written by Nicky Bloor (@NickstaDB).
**********************************************************/
public class FileInformation implements Serializable {
public static final long serialVersionUID = -1757023938083597173L;
public String sAbsolutePath;
public String sFileName;
public String sPath;
public boolean bExists;
public long lLastModified;
public long lSize;
public boolean bIsDirectory;
}
112 changes: 112 additions & 0 deletions src/nb/barmie/BaRMIe.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package nb.barmie;

import nb.barmie.exceptions.BaRMIeIllegalArgumentException;
import nb.barmie.exceptions.BaRMIeInvalidPortException;
import nb.barmie.modes.attack.AttackMode;
import nb.barmie.modes.enumeration.EnumerationMode;
import nb.barmie.util.ProgramOptions;

/***********************************************************
* Java RMI enumeration and attack tool.
**********************************************************
* v1.0
* -> Initial release with several attacks and
* deserialization payloads.
**********************************************************
* Written by Nicky Bloor (@NickstaDB).
**********************************************************/
public class BaRMIe {
/*******************
* Entry point - parse command line params, validate, and run the selected
* mode.
******************/
public static void main(String[] args) {
ProgramOptions options;

//Print a banner 'cause leet and stuff.
System.out.println("\n ▄▄▄▄ ▄▄▄ ██▀███ ███▄ ▄███▓ ██▓▓█████ \n" +
" ▓█████▄ ▒████▄ ▓██ ▒ ██▒▓██▒▀█▀ ██▒▓██▒▓█ ▀ \n" +
" ▒██▒ ▄██▒██ ▀█▄ ▓██ ░▄█ ▒▓██ ▓██░▒██▒▒███ \n" +
" ▒██░█▀ ░██▄▄▄▄██ ▒██▀▀█▄ ▒██ ▒██ ░██░▒▓█ ▄ \n" +
" ░▓█ ▀█▓ ▓█ ▓██▒░██▓ ▒██▒▒██▒ ░██▒░██░░▒████▒\n" +
" ░▒▓███▀▒ ▒▒ ▓▒█░░ ▒▓ ░▒▓░░ ▒░ ░ ░░▓ ░░ ▒░ ░\n" +
" ▒░▒ ░ ▒ ▒▒ ░ ░▒ ░ ▒░░ ░ ░ ▒ ░ ░ ░ ░\n" +
" ░ ░ ░ ▒ ░░ ░ ░ ░ ▒ ░ ░ \n" +
" ░ ░ ░ ░ ░ ░ ░ ░\n" +
" ░ v1.0\n" +
" Java RMI enumeration tool.\n" +
" Written by Nicky Bloor (@NickstaDB)\n\n" +
"Warning: BaRMIe was written to aid security professionals in identifying the\n" +
" insecure use of RMI services on systems which the user has prior\n" +
" permission to attack. BaRMIe must be used in accordance with all\n" +
" relevant laws. Failure to do so could lead to your prosecution.\n" +
" The developers assume no liability and are not responsible for any\n" +
" misuse or damage caused by this program.\n");

//Just print usage if command line is empty
if(args.length == 0) {
printUsage("");
return;
}

//Parse command line options
try {
options = new ProgramOptions(args);
} catch(BaRMIeIllegalArgumentException|BaRMIeInvalidPortException ex) {
//Something wrong with the command line
printUsage(ex.getMessage());
return;
}

//Delegate to the relevant program mode
switch(options.getExecutionMode()) {
case "-enum":
//Enumerate RMI endpoints
new EnumerationMode(options).run();
break;

case "-attack":
//Attack RMI endpoints
new AttackMode(options).run();
break;

default:
//Shouldn't happen, whatever...
printUsage("Invalid mode specified.");
}
}

/*******************
* Print a usage message.
*
* @param error Error message, e.g. if there was an issue with command line options.
******************/
private static void printUsage(String error) {
System.out.println((error.equals("") ? "" : "Error: " + error + "\n\n") +
"Usage:\n" +
" BaRMIe -enum [options] [host] [port]\n" +
" Enumerate RMI services on the given endpoint(s).\n" +
" Note: if -enum is not specified, this is the default mode.\n" +
" BaRMIe -attack [options] [host] [port]\n" +
" Enumerate and attack the given target(s).\n" +
"Options:\n" +
" --threads The number of threads to use for enumeration (default 10).\n" +
" --timeout The timeout for blocking socket operations (default 5,000ms).\n" +
" --targets A file containing targets to scan.\n" +
" The file should contain a single host or space-separated\n" +
" host and port pair per line.\n" +
" Alternatively, all nmap output formats are supported, BaRMIe will\n" +
" parse nmap output for port 1099, 'rmiregistry', or 'Java RMI'\n" +
" services to target.\n" +
" Note: [host] [port] not supported when --targets is used.\n" +
"Reliability:\n" +
" A +/- system is used to indicate attack reliability as follows:\n" +
" [+ ]: Indicates an application-specific attack\n" +
" [- ]: Indicates a JRE attack\n" +
" [ + ]: Attack insecure methods (such as 'writeFile' without auth)\n" +
" [ - ]: Attack Java deserialization (i.e. Object parameters)\n" +
" [ +]: Does not require non-default dependencies\n" +
" [ -]: Non-default dependencies are required"
);
}
}
12 changes: 12 additions & 0 deletions src/nb/barmie/exceptions/BaRMIeAttackException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package nb.barmie.exceptions;

/***********************************************************
* Exception thrown if an attack fails for some reason.
*
* Written by Nicky Bloor (@NickstaDB).
**********************************************************/
public class BaRMIeAttackException extends BaRMIeException {
public BaRMIeAttackException(String message, Throwable cause) {
super(message, cause);
}
}
13 changes: 13 additions & 0 deletions src/nb/barmie/exceptions/BaRMIeDeserAttackException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nb.barmie.exceptions;

/***********************************************************
* Exception thrown if a deserialization attack fails for
* some reason.
*
* Written by Nicky Bloor (@NickstaDB).
**********************************************************/
public class BaRMIeDeserAttackException extends BaRMIeException {
public BaRMIeDeserAttackException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nb.barmie.exceptions;

/***********************************************************
* Exception thrown if there is a problem generating a
* deserialization payload.
*
* Written by Nicky Bloor (@NickstaDB).
**********************************************************/
public class BaRMIeDeserPayloadGenerationException extends BaRMIeException {
public BaRMIeDeserPayloadGenerationException(String message, Throwable cause) {
super(message, cause);
}
}
16 changes: 16 additions & 0 deletions src/nb/barmie/exceptions/BaRMIeException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package nb.barmie.exceptions;

/***********************************************************
* Base class for exceptions thrown by BaRMIe.
*
* Written by Nicky Bloor (@NickstaDB).
**********************************************************/
public abstract class BaRMIeException extends Exception {
public BaRMIeException(String message) {
super(message);
}

public BaRMIeException(String message, Throwable cause) {
super(message, cause);
}
}
13 changes: 13 additions & 0 deletions src/nb/barmie/exceptions/BaRMIeGetObjectException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nb.barmie.exceptions;

/***********************************************************
* Exception thrown if there was a problem getting an
* object from an RMI registry during an attack.
*
* Written by Nicky Bloor (@NickstaDB).
**********************************************************/
public class BaRMIeGetObjectException extends BaRMIeException {
public BaRMIeGetObjectException(String message, Throwable cause) {
super(message, cause);
}
}
17 changes: 17 additions & 0 deletions src/nb/barmie/exceptions/BaRMIeIllegalArgumentException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package nb.barmie.exceptions;

/***********************************************************
* Exception thrown if invalid command line arguments are
* passed in.
*
* Written by Nicky Bloor (@NickstaDB).
**********************************************************/
public class BaRMIeIllegalArgumentException extends BaRMIeException {
public BaRMIeIllegalArgumentException(String message) {
super(message);
}

public BaRMIeIllegalArgumentException(String message, Throwable cause) {
super(message, cause);
}
}
Loading

0 comments on commit 28b8762

Please sign in to comment.