Before I joined siberas, I created a tool with the name “MJET” (Mogwai JMX Exploitation Toolkit) that allowed an easy exploitation of insecure configured Java JMX (Java Management Extensions) services. If you need some additional background information about JMX exploitation I recommend to take a look at this blog post by Braden Thomas and the slides from my OWASP presentation from 2015.
MJET consisted of two parts:
A Metasploit module which starts a web server that provides the payload.
A Java based command line tool that connects to the JMX service and invokes the loading/execution of the payload.
Time moves on, but insecurely configured JMX services are still quite a common thing that we regularly encounter during engagements. Unfortunately, it is no longer possible to use MJET, mainly because certain parts in the Metasploit framework have changed since I developed the tool.
Additionally, Metasploit now provides its own JMX exploit module. The Metasploit version is a 100% Ruby implementation that uses the Java Object Serialization implementation from Juan Vazquez. This basically rendered MJET obsolete.
The Metasploit module, however, has a serious drawback: It seems to work well for Linux/Unix targets, but Windows systems can’t be exploited reliably. The payload gets deployed, however the call to execute it on the target fails. I was not able to identify what caused this, I assume it has someting to do with timing.
This is why I decided to rewrite MJET, with these additional goals:
Remove dependencies on other tools/frameworks like Metasploit
Provide a flexible payload as Java JAR archive that can be used to execute arbitrary code/commands
Use a scripting language so that it can be modified without recompilation
The new version is called sJET (siberas JMX Exploitation Toolkit), obviously. sJET can be found on our Github account.
For sJET we used Jython 2.7, an implementation of the Python language for the Java platform. This allows us to use directly call the necessary Java classes/methods while keeping the advantages of having an editable Python script. The MBean that gets installed on the target is still written in Java.
The main implementation/testing work on sJET was done by our intern Patricio Reller who did an awesome job!
sJET provides different “modes” which are described briefly here.
The “install” mode is used to deploy the payload on the target and must be executed first. Installing the payload includes the following steps:
Start a web server that will host the payload and a short HTML snippet
Connect to the JMX service
Load the existing MBean “javax.management.loading.MLet”. This MBean provides methods to load additional code from a web server
Invoke “javax.management.loading.MLet.getMBeansFromURL” with the URL of the previously started web server. The JMX service will fetch the JAR from our server and deploy it.
Load the payload MBean.
Change the initial password to the value that was provided on the command line.
In the following example, the vulnerable target JMX service runs on 192.168.11.136, TCP port 9991. The attacker has the IP address 192.168.11.132. The web service will be started on port 8000. The password is set to “super_secret”
Command and shell mode
After we successfully installed the payload MBean, we can directly invoke OS commands on the target via command mode:
We can also use the shell mode to get a interactive shell. This is faster as you don’t need to start Jython every time you want to enter a command. You can exit the shell mode by typing “exit_shell”
The following basic example displays the Java environment variables:
You can invoke the script on the target as follows:
If you want to have a Meterpreter shell on the target, you need to provide the payload as a JAR file on a web server first. You can use “msfvenom” to generate the JAR file:
For example, you can use Python’s “SimpleHTTPServer” module to spin up a minimal web server in the payload directory:
As it is not possible to “unload” a previously loaded class in the Java Classloader, a successful attacker will leave some traces on the system. They can easily be identified by using the “jconsole” GUI.
You can see two interesting MBeans here:
The actual payload MBean. Keep in mind that an attacker can use a different, more stealthy name for his payload MBean.
The system MBean that was used to load the payload from an external server. This MBean is not loaded by default and its name can’t be changed by the attacker. The existence of this MBean is a strong indicator that the system has been compromised.
Please take into account that the attacker might be able to restart the Java service on a compromised machine, removing all previously loaded MBeans. Hence you should also check existing logs for unexpected service restarts.
JMX can be secured via username/password however, there is no brute force tool available (yet).
The JMX protocol is based on Java RMI. Thus it might be possible to compromise a JMX service via deserialization attacks, even with enabled authentication. This mainly depends on the available Java gadgets and Java version (CVE-2016-3427). Pierre Ernst already demonstrated this in his presentation at Hackfest 2016, including a small PoC.
That’s all for now. If you have any questions, feel free to contact me on Twitter.