VYPR
High severityNVD Advisory· Published May 30, 2023· Updated Oct 9, 2024

Apache Cassandra: Privilege escalation when enabling FQL/Audit logs

CVE-2023-30601

Description

Privilege escalation when enabling FQL/Audit logs allows user with JMX access to run arbitrary commands as the user running Apache Cassandra This issue affects Apache Cassandra: from 4.0.0 through 4.0.9, from 4.1.0 through 4.1.1.

WORKAROUND The vulnerability requires nodetool/JMX access to be exploitable, disable access for any non-trusted users.

MITIGATION Upgrade to 4.0.10 or 4.1.2 and leave the new FQL/Auditlog configuration property allow_nodetool_archive_command as false.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Privilege escalation in Apache Cassandra allows users with JMX access to execute arbitrary commands when FQL/Audit logs are enabled.

Vulnerability

Overview

CVE-2023-30601 is a privilege escalation vulnerability in Apache Cassandra that affects versions 4.0.0 through 4.0.9 and 4.1.0 through 4.1.1. The issue arises when the Full Query Logging (FQL) or Audit Logging feature is enabled. A user with JMX (Java Management Extensions) access can exploit this flaw to run arbitrary commands as the user running Apache Cassandra [1].

Exploitation

Details

To exploit this vulnerability, an attacker must have network access to the JMX port (typically 7199) and valid credentials to authenticate to the JMX service. The vulnerability is triggered by sending a crafted command through JMX that causes the database to execute an arbitrary command during the audit log archival process. No additional privileges beyond JMX access are required to execute the exploit [1] [2].

Impact

Successful exploitation allows an attacker with JMX access to execute arbitrary operating system commands with the same privileges as the Apache Cassandra process. This could lead to full compromise of the database server, including data exfiltration, modification, or destruction, as well as lateral movement within the network [1] [2].

Mitigation

Apache has released versions 4.0.10 and 4.1.2, which include a configuration property allow_nodetool_archive_command (defaulting to false) that prevents this exploitation. Users are strongly advised to upgrade to these patched versions. As a workaround, administrators should disable JMX access for any non-trusted users or restrict network access to the JMX port [1] [2].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.apache.cassandra:cassandra-allMaven
>= 4.1.0, < 4.1.24.1.2
org.apache.cassandra:cassandra-allMaven
>= 4.0.0, < 4.0.104.0.10

Affected products

4

Patches

2
22d74c711658

Merge branch 'cassandra-4.0' into cassandra-4.1

https://github.com/apache/cassandraMick Semb WeverMay 26, 2023via ghsa
1 file changed · +2 0
  • test/unit/org/apache/cassandra/fql/FullQueryLoggerTest.java+2 0 modified
    @@ -680,6 +680,7 @@ public void testJMXArchiveCommand()
     
             try
             {
    +            DatabaseDescriptor.getFullQueryLogOptions().allow_nodetool_archive_command = false;
                 StorageService.instance.enableFullQueryLogger(options.log_dir, options.roll_cycle, false, 1000, 1000, "/xyz/not/null", 0);
                 fail("not allowed");
             }
    @@ -688,6 +689,7 @@ public void testJMXArchiveCommand()
                 assertTrue(e.getMessage().contains("Can't enable full query log archiving via nodetool"));
             }
     
    +        options.allow_nodetool_archive_command = true;
             options.archive_command = "/xyz/not/null";
             options.log_dir = "/tmp/abc";
             DatabaseDescriptor.setFullQueryLogOptions(options);
    
aafb4d19448f

Improve nodetool enable{audit,fullquery}log

https://github.com/apache/cassandraMarcus ErikssonApr 12, 2023via ghsa
7 files changed · +46 2
  • CHANGES.txt+1 0 modified
    @@ -1,4 +1,5 @@
     4.0.10
    + * Improve nodetool enable{audit,fullquery}log (CASSANDRA-18550)
      * Report network cache info in nodetool (CASSANDRa-18400)
      * Partial compaction can resurrect deleted data (CASSANDRA-18507)
      * Allow internal address to change with reconnecting snitches (CASSANDRA-16718)
    
  • conf/cassandra.yaml+2 0 modified
    @@ -1360,6 +1360,8 @@ audit_logging_options:
         # max_log_size: 17179869184 # 16 GiB
         ## archive command is "/path/to/script.sh %path" where %path is replaced with the file being rolled:
         # archive_command:
    +    ## note that enabling this allows anyone with JMX/nodetool access to run local shell commands as the user running cassandra
    +    # allow_nodetool_archive_command: false
         # max_archive_retries: 10
     
     # validate tombstones on reads and compaction
    
  • src/java/org/apache/cassandra/config/DatabaseDescriptor.java+5 0 modified
    @@ -3140,6 +3140,11 @@ public static FullQueryLoggerOptions getFullQueryLogOptions()
             return  conf.full_query_logging_options;
         }
     
    +    public static void setFullQueryLogOptions(FullQueryLoggerOptions options)
    +    {
    +        conf.full_query_logging_options = options;
    +    }
    +
         public static boolean getBlockForPeersInRemoteDatacenters()
         {
             return conf.block_for_peers_in_remote_dcs;
    
  • src/java/org/apache/cassandra/service/StorageService.java+2 0 modified
    @@ -6081,6 +6081,8 @@ public void enableFullQueryLogger(String path, String rollCycle, Boolean blockin
             blocking = blocking != null ? blocking : fqlOptions.block;
             maxQueueWeight = maxQueueWeight != Integer.MIN_VALUE ? maxQueueWeight : fqlOptions.max_queue_weight;
             maxLogSize = maxLogSize != Long.MIN_VALUE ? maxLogSize : fqlOptions.max_log_size;
    +        if (archiveCommand != null && !fqlOptions.allow_nodetool_archive_command)
    +            throw new ConfigurationException("Can't enable full query log archiving via nodetool unless full_query_logging_options.allow_nodetool_archive_command is set to true");
             archiveCommand = archiveCommand != null ? archiveCommand : fqlOptions.archive_command;
             maxArchiveRetries = maxArchiveRetries != Integer.MIN_VALUE ? maxArchiveRetries : fqlOptions.max_archive_retries;
     
    
  • src/java/org/apache/cassandra/tools/nodetool/EnableFullQueryLog.java+2 1 modified
    @@ -42,7 +42,8 @@ public class EnableFullQueryLog extends NodeToolCmd
         private String path = null;
     
         @Option(title = "archive_command", name = {"--archive-command"}, description = "Command that will handle archiving rolled full query log files." +
    -                                                                                   " Format is \"/path/to/script.sh %path\" where %path will be replaced with the file to archive")
    +                                                                                   " Format is \"/path/to/script.sh %path\" where %path will be replaced with the file to archive" +
    +                                                                                   " Enable this by setting the full_query_logging_options.allow_nodetool_archive_command: true in the config.")
         private String archiveCommand = null;
     
         @Option(title = "archive_retries", name = {"--max-archive-retries"}, description = "Max number of archive retries.")
    
  • src/java/org/apache/cassandra/utils/binlog/BinLogOptions.java+7 0 modified
    @@ -23,6 +23,13 @@
     public class BinLogOptions
     {
         public String archive_command = StringUtils.EMPTY;
    +
    +    /**
    +     * enable if a user should be able to set the archive command via nodetool/jmx
    +     *
    +     * do not make this a hotprop.
    +     */
    +    public boolean allow_nodetool_archive_command = false;
         /**
          * How often to roll BinLog segments so they can potentially be reclaimed. Available options are:
          * MINUTELY, HOURLY, DAILY, LARGE_DAILY, XLARGE_DAILY, HUGE_DAILY.
    
  • test/unit/org/apache/cassandra/fql/FullQueryLoggerTest.java+27 1 modified
    @@ -32,7 +32,6 @@
     
     import org.apache.commons.lang3.StringUtils;
     import org.junit.After;
    -import org.junit.Before;
     import org.junit.BeforeClass;
     import org.junit.Test;
     
    @@ -44,15 +43,18 @@
     import net.openhft.chronicle.wire.ValueIn;
     import net.openhft.chronicle.wire.WireOut;
     import org.apache.cassandra.Util;
    +import org.apache.cassandra.config.DatabaseDescriptor;
     import org.apache.cassandra.cql3.CQLTester;
     import org.apache.cassandra.cql3.QueryOptions;
     import org.apache.cassandra.cql3.statements.BatchStatement;
    +import org.apache.cassandra.exceptions.ConfigurationException;
     import org.apache.cassandra.fql.FullQueryLogger.Query;
     import org.apache.cassandra.fql.FullQueryLogger.Batch;
     import org.apache.cassandra.cql3.statements.BatchStatement.Type;
     import org.apache.cassandra.io.util.FileUtils;
     import org.apache.cassandra.service.ClientState;
     import org.apache.cassandra.service.QueryState;
    +import org.apache.cassandra.service.StorageService;
     import org.apache.cassandra.transport.ProtocolVersion;
     import org.apache.cassandra.utils.ObjectSizes;
     import org.apache.cassandra.utils.binlog.BinLogTest;
    @@ -74,6 +76,7 @@
     import static org.apache.cassandra.fql.FullQueryLogger.TYPE;
     import static org.apache.cassandra.fql.FullQueryLogger.VALUES;
     import static org.apache.cassandra.fql.FullQueryLogger.VERSION;
    +import static org.junit.Assert.fail;
     
     public class FullQueryLoggerTest extends CQLTester
     {
    @@ -670,6 +673,29 @@ public void testLogQueryNegativeTime() throws Exception
             logQuery("", QueryOptions.DEFAULT, queryState(), -1);
         }
     
    +    @Test
    +    public void testJMXArchiveCommand()
    +    {
    +        FullQueryLoggerOptions options = new FullQueryLoggerOptions();
    +
    +        try
    +        {
    +            StorageService.instance.enableFullQueryLogger(options.log_dir, options.roll_cycle, false, 1000, 1000, "/xyz/not/null", 0);
    +            fail("not allowed");
    +        }
    +        catch (ConfigurationException e)
    +        {
    +            assertTrue(e.getMessage().contains("Can't enable full query log archiving via nodetool"));
    +        }
    +
    +        options.archive_command = "/xyz/not/null";
    +        options.log_dir = "/tmp/abc";
    +        DatabaseDescriptor.setFullQueryLogOptions(options);
    +        StorageService.instance.enableFullQueryLogger(options.log_dir, options.roll_cycle, false, 1000, 1000, null, 0);
    +        assertTrue(FullQueryLogger.instance.isEnabled());
    +        assertEquals("/xyz/not/null", FullQueryLogger.instance.getFullQueryLoggerOptions().archive_command);
    +    }
    +
         private static void compareQueryOptions(QueryOptions a, QueryOptions b)
         {
             assertEquals(a.getClass(), b.getClass());
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.