Die siberas GmbH ein auf Sicherheitsanalysen und Penetrationstests spezialisiertes Beratungsunternehmen, welches Sie herstellerunabhängig und kompetent im Bereich IT-Sicherheit berät.
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!
Usage
sJET provides different “modes” which are described briefly here.
Install mode
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”
JavaScript mode
If you want do some more advanced stuff, the JavaScript mode is for you. sJET allows you to invoke the JavaScript implementation that comes with JDK (Nashorn for JDK8 or Rhino for JDK6/7) with a custom script. As you can invoke arbitrary Java methods from here, the JavaScript mode provides RCE without touching disk.
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:
The next thing we need is a small JavaScript stager that loads the JAR file from the remote web server and invokes the main method of the “metasploit.payload” class. Let’s look how this is done in Java:
And here the “Java based JavaScript” version which you can find in the “scripts” directory of sJET:
Of course, it would also be possible to directly load Meterpreter from JavaScript and avoiding the call to an external URL. However, the attacker should be able to access an external URL via JMX, otherwise he wouldn’t be able to install the malicious MBean in the first place.
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.
Future ideas
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.
Matthias Kaiser pointed out that it would be possible to implement everything in JavaScript, removing the Jython dependency.
That’s all for now. If you have any questions, feel free to contact me on Twitter.