Information Disclosure in Cassandra
How Information Disclosure Manifests in Cassandra
Apache Cassandra is a distributed NoSQL store that optimizes for write throughput and eventual consistency. When authentication, authorization, or query‑level controls are misconfigured, attackers can retrieve data that was never intended for external consumption. The most common disclosure vectors are:
- Unauthenticated access to system tables. If the
authenticatoris set toAllowAllAuthenticator(the default in many quick‑start installations), any client can connect without credentials and query tables such assystem_schema.keyspaces,system_schema.tables,system.local, orsystem.peers. These tables expose the full schema, node topology, and version information, which attackers use to map the cluster and plan further attacks. - Over‑broad SELECT queries. A CQL statement like
SELECT * FROM keyspace.tablewithout aWHEREclause or pagination limit can cause the coordinator to stream the entire partition set. In a large cluster this may return gigabytes of data in a single response, leaking sensitive rows that were meant to be accessed only via specific primary‑key lookups. - Error messages and trace output. When
traceis enabled (e.g., via theTRONcommand in cqlsh) or when the driver is configured to propagate query traces, stack traces and internal details can be returned in the response body. These messages may reveal table names, column types, or even parts of the query plan that assist an attacker in crafting injection or bypass attempts. - Exposure of JMX or thrift interfaces. Although not part of CQL, leaving the JMX port (
7199) or the legacy Thrift service (9160) open without authentication allows remote clients to invoke MBeans that dump configuration, snapshot data, or trigger node operations, indirectly leading to data disclosure.
These patterns map to OWASP API Security Top 10 2023 category A1: Broken Object Level Authorization (BOLA/IDOR) and A3: Excessive Data Exposure, as well as to the Cassandra‑specific risk of leaking schema and topology information.
Cassandra-Specific Detection
Detecting information disclosure in a Cassandra deployment can be done manually with cqlsh or programmatically with a driver, but a black‑box scanner like middleBrick automates the check for unauthenticated exposure. middleBrick performs the following steps when scanning a Cassandra endpoint (exposed via the native binary protocol on port 9042 or via HTTP‑based APIs that proxy CQL):
- Unauthenticated connection attempt. The scanner opens a socket to the target host:port and sends a
STARTUPmessage with no credentials. If the server responds with aREADYframe, authentication is effectively disabled. - System table probing. Upon successful unauthenticated auth, middleBrick issues a series of read‑only CQL queries such as:
SELECT * FROM system_schema.keyspaces;
SELECT * FROM system_schema.tables WHERE keyspace_name = 'system_auth';
SELECT * FROM system.local;
SELECT * FROM system.peers;
- If any of these queries return rows without an error, the scanner flags the finding as Information Disclosure – System Table Exposure with a severity of
high(based on the potential to reveal cluster topology and version). - Unbounded query detection. middleBrick also sends a query without a
WHEREclause and with a deliberately small page size (e.g.,PAGE SIZE 1) to see whether the server honors paging limits. If the response contains more rows than the requested page size, the scanner notes a potential for excessive data exposure. - Error message inspection. The scanner deliberately triggers a malformed query (e.g.,
SELECT * FROM nonexistent_table) and checks whether the response includes a stack trace or detailed error message. Presence of such details results in a medium‑severity finding.
Because middleBrick works purely from the network perspective, it requires no agents, no credentials, and no prior knowledge of the Cassandra configuration. The scan completes within the advertised 5–15 second window, returning a JSON report that includes the raw CQL responses, the severity rating, and remediation guidance.
Cassandra-Specific Remediation
Addressing information disclosure in Cassandra involves tightening authentication, applying fine‑grained authorization, and limiting what queries can return. The following steps are recommended and can be verified with a rescan using middleBrick or the CLI tool.
- Enable authentication and authorization. Set the
authenticator incassandra.yaml toPasswordAuthenticator and theauthorizer toCassandraAuthorizer. Then create roles and assign permissions:
# cqlsh -u cassandra -p cassandra
CREATE ROLE app_user WITH PASSWORD = 'strong_password' AND LOGIN = true;
GRANT SELECT ON KEYSPACE myapp TO app_user;
GRANT MODIFY ON TABLE myapp.users TO app_user;
# Revoke default permissions on system tables
REVOKE ALL ON system_schema.keyspaces FROM app_user;
REVOKE ALL ON system.local FROM app_user;
REVOKE ALL ON system.peers FROM app_user;
- Restrict access to system tables. Even with authentication enabled, the default
CassandraAuthorizer still allows any authenticated user to read system tables. Explicitly revoke those permissions as shown above, or create a custom role that omits system‑table access and assign all application users to that role. - Enforce query limits. Use driver‑side pagination and enforce a maximum page size. In the DataStax Java driver, you can set:
// Java driver 4.x
CqlSession session = CqlSession.builder()
.addContactPoint(new InetSocketAddress("cassandra-node", 9042))
.withAuthCredentials("app_user", "strong_password")
.withDefaultPageSize(1000) // limits rows per page
.build();
// Example query with explicit limit
ResultSet rs = session.execute(
SimpleStatement.newInstance(
"SELECT * FROM myapp.events WHERE tenant_id = ?",
Values.valueOf(tenantId)
)
);
- Disable tracing and verbose error messages in production. Set
trace_probability to0.0 incassandra.yaml and configure the driver to not propagate traces:
// Java driver
.sessionBuilder()
.withProtocolVersion(ProtocolVersion.V4)
.withTimestampGenerator(TimestampGenerator.MONOTONIC)
.build();
// Ensure trace is not requested
session.execute(SimpleStatement.newInstance("SELECT * FROM myapp.table").setPageSize(500));
- Secure JMX and Thrift. If JMX is required, bind it to localhost or protect it with authentication and TLS. Disable the Thrift interface unless legacy clients truly need it:
# cassandra.yaml rpc_address: localhost start_rpc: false # disables Thrift # JMX via JVM options, e.g. # -Dcom.sun.management.jmxremote.authenticate=true # -Dcom.sun.management.jmxremote.ssl=trueAfter applying these changes, run a fresh scan with middleBrick (e.g.,
middlebrick scan https://api.example.com/cql) to verify that the information‑disclosure findings are resolved. The scanner will now report authentication failures for unauthenticated attempts and will no longer receive rows from system tables, confirming that the exposure surface has been reduced.