From 7e3a75903159153c877daeb2952a552701e38044 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Thu, 11 Jun 2026 08:34:19 +0000
Subject: [PATCH] CVE-2026-46495 OpenDJ Unauthenticated RCE via Java Deserialization in JMX RMI
---
opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java | 37 +++++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java
index 33a9ba6..1a418b9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/jmx/RmiConnector.java
@@ -13,6 +13,7 @@
*
* Copyright 2006-2009 Sun Microsystems, Inc.
* Portions Copyright 2013-2015 ForgeRock AS.
+ * Portions Copyright 2023-2026 3A Systems, LLC.
*/
package org.opends.server.protocols.jmx;
@@ -22,6 +23,7 @@
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;
+import java.util.Map;
import java.util.SortedSet;
import javax.net.ssl.KeyManager;
@@ -63,6 +65,29 @@
{
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+ static final String JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES =
+ "jmx.remote.rmi.server.credential.types";
+
+ /**
+ * JDK 10+ JMX environment property scoping a JEP 290 deserialization
+ * filter to the credentials object passed during {@code newClient()}.
+ * Using the credentials-scoped filter (instead of the connector-wide
+ * {@code jmx.remote.rmi.server.serial.filter.pattern}) avoids breaking
+ * legitimate JMX traffic such as MBean invocations and notifications,
+ * which may legitimately carry non-String types.
+ */
+ static final String JMX_REMOTE_RMI_SERVER_CREDENTIALS_FILTER_PATTERN =
+ "jmx.remote.rmi.server.credentials.filter.pattern";
+
+ private static final String[] JMX_CREDENTIAL_TYPES =
+ {
+ String.class.getName(),
+ String[].class.getName()
+ };
+
+ private static final String JMX_CREDENTIAL_SERIAL_FILTER =
+ "maxdepth=3;maxarray=2;java.lang.String;!*";
+
/**
* The MBean server used to handle JMX interaction.
@@ -253,6 +278,7 @@
{
// Environment map
HashMap<String, Object> env = new HashMap<>();
+ configureJmxDeserializationProtection(env);
// ---------------------
// init an ssl context
@@ -364,6 +390,17 @@
}
+ static void configureJmxDeserializationProtection(Map<String, Object> env)
+ {
+ env.put(JMX_REMOTE_RMI_SERVER_CREDENTIAL_TYPES,
+ JMX_CREDENTIAL_TYPES.clone());
+ // Scope the JEP 290 deserialization filter to the credentials object
+ // only, so legitimate JMX RMI traffic (MBean operations, notifications,
+ // etc.) is not affected by the restrictive allowlist.
+ env.put(JMX_REMOTE_RMI_SERVER_CREDENTIALS_FILTER_PATTERN,
+ JMX_CREDENTIAL_SERIAL_FILTER);
+ }
+
/**
* Closes this connection handler so that it will no longer accept new
* client connections. It may or may not disconnect existing client
--
Gitblit v1.10.0