Broken Access Control in Cassandra
How Broken Access Control Manifests in Cassandra
Broken Access Control in Cassandra typically stems from misconfigured role‑based access control (RBAC) or from application code that trusts user‑supplied input when constructing CQL statements. When authentication is disabled or when overly permissive roles are granted, an attacker can read, modify, or delete data without authorization.
- Excessive role permissions: Granting
ALLpermissions on a keyspace to thepublicrole or to a generic service account gives any authenticated user full control. Example of a misconfiguration:
-- Dangerous: gives everyone full access
GRANT ALL ON KEYSPACE myapp TO public;
authenticator setting in cassandra.yaml is left at org.apache.cassandra.auth.AllowAllAuthenticator, anyone who can reach the TCP port (9042) can connect without credentials.// Vulnerable: string concatenation opens the door to unauthorized reads
String cql = "SELECT * FROM users WHERE user_id = '" + userId + "';";
Session session = cluster.connect();
ResultSet rs = session.execute(cql);
An attacker could supply userId = ' OR '1'='1 to retrieve every row, bypassing any application‑level checks. Similar techniques can be used to issue INSERT, UPDATE, or DROP statements if the associated role has write permissions.
These patterns map directly to the OWASP API Security Top 10 item Broken Object Level Authorization (BOLA) and the broader Broken Access Control category. Real‑world incidents, such as CVE‑2019‑10099 (authentication bypass in Apache Cassandra), illustrate how weak access controls can be exploited at the protocol level.
Cassandra‑Specific Detection — Including middleBrick
middleBrick performs unauthenticated, black‑box scanning of the API surface that fronts a Cassandra cluster (e.g., REST/GraphQL wrappers, gRPC services, or direct native protocol endpoints). Because it does not require agents or credentials, it can discover misconfigurations that would be invisible to internal scanners.
- Authentication probing attempts to connect to the Cassandra native port (9042) using the
AllowAllAuthenticatorhandshake. If the server responds with a successfulREADYframe without requesting credentials, the scanner flags the endpoint as No authentication required. - Role‑privilege enumeration: After establishing a session (whether authenticated with a default credential or anonymously if allowed), middleBrick issues a series of read‑only CQL statements against system tables such as
system.role_permissionsandsystem_schema.keyspaces. Successful retrieval of permission rows indicates that the connected role has at leastDESCRIBEvisibility, which often correlates with excessive grants. - Write‑access testing: The scanner tries a benign
INSERTinto a test table (if one exists) or attempts to create a temporary table. If the operation succeeds, the finding is reported as Unauthorized write capability with severity high. - Injection detection: By sending payloads like
' OR 1=1--in user‑controlled parameters of the front‑end API, middleBrick watches for changes in response size, status codes, or error messages that indicate the payload altered the executed CQL. Positive results are logged as Potential CQL injection leading to access bypass.
All checks run in parallel and complete within the advertised 5‑15 second window. Findings are presented with a CVSS‑based severity, a short description, and remediation guidance that references Cassandra’s native features.
Cassandra‑Specific Remediation — Using Native Features
Fixing broken access control in Cassandra involves three layers: protocol‑level authentication, least‑privilege role design, and safe query construction in application code.
- Enable authentication and encryption: Set
authenticator: PasswordAuthenticatorandauthorizer: CassandraAuthorizerincassandra.yaml. Then restart the node. Additionally, enable client‑to‑node encryption (server_encryption_options) to prevent credential sniffing. - Create minimal‑privilege roles: Avoid granting
ALLor assigning permissions to thepublicrole. Instead, define a role per service or microservice and grant only the needed operations on the specific keyspaces and tables.
-- Create a role for the inventory service
CREATE ROLE inventory_service WITH PASSWORD = 'Str0ngP@ss!' AND LOGIN = true;
-- Grant only read/write on the tables it needs
GRANT SELECT, MODIFY ON KEYSPACE inventory TO inventory_service;
GRANT SELECT ON KEYSPACE system_schema TO inventory_service; -- optional for metadata
// Safe: prepared statement with bound variable
PreparedStatement ps = session.prepare(
"SELECT * FROM users WHERE user_id = ?");
BoundStatement bs = ps.bind(userId);
ResultSet rs = session.execute(bs);
audit_logging_options) to capture authentication attempts and CQL statements. Periodically review the logs for unexpected SELECT or MODIFY actions from roles that should not have them.By combining these measures — turning on strong authentication, applying the principle of least privilege via Cassandra’s RBAC, and using parameterized queries — you eliminate the most common vectors for broken access control in Cassandra environments.