Merge branch 'cassandra-4.1' into trunk

* cassandra-4.1:
  Fix JMX security vulnerabilities
This commit is contained in:
Mick Semb Wever 2022-10-18 22:56:53 +02:00
commit b0ae3de1c9
No known key found for this signature in database
GPG Key ID: E91335D77E3E87CB
3 changed files with 72 additions and 1 deletions

View File

@ -124,6 +124,7 @@ Merged from 3.11:
* Creating of a keyspace on insufficient number of replicas should filter out gosspping-only members (CASSANDRA-17759)
* Suppress CVE-2022-25857 and other snakeyaml CVEs (CASSANDRA-17907)
Merged from 3.0:
* Harden JMX by resolving beanshooter issues (CASSANDRA-17921)
* Suppress CVE-2019-2684 (CASSANDRA-17965)
* Fix auto-completing "WITH" when creating a materialized view (CASSANDRA-17879)
* Improve libjemalloc resolution in bin/cassandra (CASSANDRA-15767)

View File

@ -187,7 +187,7 @@
<configuration default="false" name="Cassandra" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" value="org.apache.cassandra.service.CassandraDaemon" />
<option name="VM_PARAMETERS" value="-Dcassandra-foreground=yes -Dcassandra.config=file://$PROJECT_DIR$/conf/cassandra.yaml -Dcassandra.storagedir=$PROJECT_DIR$/data -Dlogback.configurationFile=file://$PROJECT_DIR$/conf/logback.xml -Dcassandra.logdir=$PROJECT_DIR$/data/logs -Djava.library.path=$PROJECT_DIR$/lib/sigar-bin -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=7199 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -ea -Xmx1G -Dcassandra.reads.thresholds.coordinator.defensive_checks_enabled=true -XXHeapDumpPath=build/test" />
<option name="VM_PARAMETERS" value="-Dcassandra-foreground=yes -Dcassandra.config=file://$PROJECT_DIR$/conf/cassandra.yaml -Dcassandra.storagedir=$PROJECT_DIR$/data -Dlogback.configurationFile=file://$PROJECT_DIR$/conf/logback.xml -Dcassandra.logdir=$PROJECT_DIR$/data/logs -Djava.library.path=$PROJECT_DIR$/lib/sigar-bin -Dcassandra.jmx.local.port=7199 -ea -Xmx1G -Dcassandra.reads.thresholds.coordinator.defensive_checks_enabled=true -XX:HeapDumpPath=build/test" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />

View File

@ -28,6 +28,7 @@ import java.util.function.BooleanSupplier;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
@ -148,6 +149,10 @@ public class AuthorizationProxy implements InvocationHandler
if ("getMBeanServer".equals(methodName))
throw new SecurityException("Access denied");
// Corresponds to MBeanServer.invoke
if (methodName.equals("invoke") && args.length == 4)
checkVulnerableMethods(args);
// Retrieve Subject from current AccessControlContext
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
@ -478,6 +483,71 @@ public class AuthorizationProxy implements InvocationHandler
.collect(Collectors.toSet());
}
private void checkVulnerableMethods(Object args[])
{
assert args.length == 4;
ObjectName name;
String operationName;
Object[] params;
String[] signature;
try
{
name = (ObjectName) args[0];
operationName = (String) args[1];
params = (Object[]) args[2];
signature = (String[]) args[3];
}
catch (ClassCastException cce)
{
logger.warn("Could not interpret arguments to check vulnerable MBean invocations; did the MBeanServer interface change?", cce);
return;
}
// When adding compiler directives from a file, most JDKs will log the file contents if invalid, which
// leads to an arbitrary file read vulnerability
checkCompilerDirectiveAddMethods(name, operationName);
// Loading arbitrary (JVM and native) libraries from remotes
checkJvmtiLoad(name, operationName);
checkMLetMethods(name, operationName);
}
private void checkCompilerDirectiveAddMethods(ObjectName name, String operation)
{
if (name.getCanonicalName().equals("com.sun.management:type=DiagnosticCommand")
&& operation.equals("compilerDirectivesAdd"))
throw new SecurityException("Access is denied!");
}
private void checkJvmtiLoad(ObjectName name, String operation)
{
if (name.getCanonicalName().equals("com.sun.management:type=DiagnosticCommand")
&& operation.equals("jvmtiAgentLoad"))
throw new SecurityException("Access is denied!");
}
private void checkMLetMethods(ObjectName name, String operation)
{
// Inspired by MBeanServerAccessController, but that class ignores check if a SecurityManager is installed,
// which we don't want
if (operation == null)
return;
try
{
if (!mbs.isInstanceOf(name, "javax.management.loading.MLet"))
return;
}
catch (InstanceNotFoundException infe)
{
return;
}
if (operation.equals("addURL") || operation.equals("getMBeansFromURL"))
throw new SecurityException("Access is denied!");
}
public static final class JmxPermissionsCache extends AuthCache<RoleResource, Set<PermissionDetails>>
implements JmxPermissionsCacheMBean
{