Administrative portals remain one of the top “low hanging fruit” categories to be on the lookout for when performing bug bounties, penetration tests, or red teams. In this post, I will introduce you to another administrative portal that I believe may be quite overlooked.

On several bug hunts and penetration tests, I’ve encountered the Open Services Gateway (OSGi) console. What is OSGi? Think of it as a service handler for Java applications. Applications come in the form of bundles that can be deployed via the web interface. These applications can then be remotely installed, started, or stopped without requiring reboots of the web service itself.

OSGi consoles can come with many features, including a scripting console. I’ve covered abusing the OSGi scripting console in a previous post. This post, however, will cover how to create and deploy a “malicious” bundle that we can invoke through the web interface. Let’s get started.

If you would like to setup your own test environment, I suggest following this great tutorial.

Finding OSGi

First, we need a console to target. If you’ve found something that looks like the console below, you’re on the right track.

The OSGi console is typically located at /system/console. Though port 8080 is the default during install, the console may be hosted on other ports such as 80 and 443 commonly.

There are several methods I use when searching for this console. My favorite is the “http-enum” script with nmap. Just replace /usr/share/nmap/nselib/data/http-fingerprints.lua with the new version. Also, if you’re using PowerShell, you can try my Find-Fruit script, which is basically a simple threaded version of dirbuster for PowerShell.

As common with default installs, the username and password is admin:admin. Once logged in, you’ll be presented with the Apache Felix Web Console Bundles page as seen below.

This dashboard may look different on each install, depending on what bundles are installed. There’s not much to this dashboard and you can see how easy it is to install and start or stop a bundle. We’ll need to create a custom bundle to install via this web console.

Creating and compiling a bundle

Next, we’ll need the Felix framework in order to assist compiling our payload. You may download the latest Felix Framework Distribution and all required dependencies from http://felix.apache.org/downloads.cgi

I suggest creating a project folder to house your Felix Framework and other parts of your payload. For this exercise, let’s create a folder structure like so:

The “lib” folder will contain “felix.jar”, which you should have in the bin/ directory after extracting the Felix Framework Distribution.

The “classes” folder will eventually contain your compiled class.

The “AFBundle” folder should contain the follow this structure unless you modify the manifest: “AFBundle/com/rvrsh3ll/osgi/shellme/Activator.java”

Activator.java is the main code that will run your payload on the remote system. Let’s take a look at that.

We could use something as simple as the exec function to execute a system command like so:

java.lang.Runtime.getRuntime().exec(“id”);

This does not handle errors well or operate very gracefully with the console. If your command is wrong or hangs, you’ll crash Apache Felix. In this instance, we’re going to use Java’s ProcessBuilder to execute a system command on the remote target in a stable manner. We want this code to tell that system to start a reverse shell with us and not crash the web console. I found this very handy Java reverse shell that I forked from caseydunham, which does the trick very nicely. Of course, you could modify ProcessBuilder to execute whatever you like, but I highly suggest testing first.

So, we need a bundle template to get started. Fortunately, there’s not much to a basic bundle. We really only need three imports to get started.

The first import should look familiar. It’s our directory structure we created earlier pointing to where this Activator.java file is. The next two imports are pretty simple. The BundleActivator interface customizes the starting and stopping of bundles. The BundleContext interface allows the bundle to interact with the framework. That’s it! Now, we can modify this to handle our Java reverse shell rather easily.

Now that that is done, we’ll need one more file that provides Felix the bundle details needed when we compile. This is our MANIFEST.MF file located in the root of your folder structure. If you’ve been following along that’s the AFBundle/MANIFEST.MF location.

The MANIFEST.MF file is rather simple. The most important two are the Import-Package instruction, which is a list of packages required by our bundle. This is simply the org.osgi.framework package for what we are doing. The Bundle-Activator contains the fully qualified name of our activator class. Again, in the form of our directory structure. For more information on what makes a bundle, readme.

Now, we can build our bundle! Two easy compile commands is all that this process takes.

Deploying

Now that our rvrsh3ll.jar file is complete, we can set up our listener and deploy the bundle. A simple netcat listener will do and it’s as easy as following the Install/Update button prompts.

Wrapping Up

That’s all there is to it! As always, management interfaces with default credentials remain one of the top dangers, both externally and internally, for organizations large or small. Simply changing the default password goes a long way in preventing this attack. Although, defenders should be aware that this portal has no lockout threshold or logging that I am aware of.

Administrative portals should be kept behind two-factor VPN’s when possible. For defenders, knowing what portals lurk on the Internet or even internally is crucial. Using these same tools, defenders can analyze their security posture for low hanging fruit and notify system owners of any unsecured administrative portals.

In this post, we’ve learned how to find the OSGi console, build and compile a bundle, and deploy it. I hope this blog post brings some awareness to another potentially dangerous interface if not secured correctly.