You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by "Stefan Miklosovic (Jira)" <ji...@apache.org> on 2026/03/18 07:09:00 UTC
[jira] [Commented] (CASSANDRA-21228) ALTER ROLE Password Hash DoS Vulnerability
[ https://issues.apache.org/jira/browse/CASSANDRA-21228?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18066504#comment-18066504 ]
Stefan Miklosovic commented on CASSANDRA-21228:
-----------------------------------------------
I believe this was addressed in CASSANDRA-21202
> ALTER ROLE Password Hash DoS Vulnerability
> ------------------------------------------
>
> Key: CASSANDRA-21228
> URL: https://issues.apache.org/jira/browse/CASSANDRA-21228
> Project: Apache Cassandra
> Issue Type: Bug
> Components: Feature/Authorization, Feature/Rate Limiting
> Reporter: Cyl
> Priority: Normal
> Labels: dos, performance, security
>
> h2. Vulnerability Description
> *Name*: Authenticated DoS via {{ALTER ROLE}} Password Hashing
> *Overview*:
> In current Cassandra builds, {{ALTER ROLE ... WITH PASSWORD}} executes {{BCrypt.hashpw}} synchronously on the standard request executor ({{Dispatcher.requestExecutor}}). When an authenticated user issues many password changes, the expensive bcrypt work monopolizes that pool, starving all other CQL requests and producing an authenticated denial of service. This is the same root problem addressed by CASSANDRA-17812 for {{AUTH_RESPONSE}}, but the trigger has moved to {{ALTER ROLE}}.
> *Affected Configurations*:
> * Clusters running {{PasswordAuthenticator}}.
> * Any authenticated account that may alter its own password (default behavior for non-superusers).
> * Attackers that can reach the native CQL port.
> *Impact*:
> * Legitimate query latency inflates dramatically (observed increase from ~2 ms to >1 s).
> * Attack threads hit numerous {{OperationTimedOut}} errors, demonstrating thread-pool exhaustion.
> * Service recovers immediately once the attack stops, indicating a classic CPU-starvation DoS.
> h2. Proof-of-Concept Steps
> The file {{poc_dos.py}} automates the scenario:
> # Start a single-node Cassandra instance with {{PasswordAuthenticator}} and {{CassandraAuthorizer}}.
> # With the superuser, create a victim role named {{target_role}}.
> # Launch 200 concurrent threads that run {{ALTER ROLE target_role WITH PASSWORD '<random>'}} in a tight loop.
> # Start a monitor thread executing {{SELECT now()}} once per second to record latency.
> Run the following command:
> {code:bash}
> python3 poc_dos.py
> {code}
> *Observed Output*:
> {code}
> Starting attack with 200 threads...
> [Victim] Query latency: 0.3743s
> [Victim] Query latency: 0.9145s
> Worker failed: ('Unable to connect ... OperationTimedOut ...')
> [Victim] Query latency: 1.0181s
> ...
> {code}
> Immediately after the attack begins, the monitor reports 300 ms–1 s latency along with repeated {{OperationTimedOut}} errors. Once the attack stops, latency returns to ~2 ms, proving the DoS is reproducible.
> h2. Problematic Code Reference
> The vulnerable path sits in {{CassandraRoleManager.optionsToAssignments(...)}} and ultimately in {{hashpw(...)}}, both under {{src/java/org/apache/cassandra/auth/}}:
> {code:java}
> private String optionsToAssignments(Map<Option, Object> options)
> {
> return options.entrySet()
> .stream()
> .map(entry ->
> {
> switch (entry.getKey())
> {
> case PASSWORD:
> // bcrypt runs on Dispatcher.requestExecutor
> return String.format("salted_hash = '%s'", escape(hashpw((String) entry.getValue())));
> // other options elided
> }
> })
> .filter(Objects::nonNull)
> .collect(Collectors.joining(","));
> }
> private static String hashpw(String password)
> {
> return BCrypt.hashpw(password, PasswordSaltSupplier.get());
> }
> {code}
> Because every {{ALTER ROLE ... WITH PASSWORD}} is processed on the shared {{Dispatcher.requestExecutor}}, each invocation above performs bcrypt hashing on threads that also handle standard queries, leading to starvation.
> h2. Related Issue and Root Cause
> * *Related Fix*: [CASSANDRA-17812] “Rate-limit new client connection auth setup to avoid overwhelming bcrypt”.
> * Mitigation: route {{AUTH_RESPONSE}} (and similar) to {{authExecutor}}.
> * Gap: {{ALTER ROLE}} / {{CREATE ROLE}} continue to run on {{requestExecutor}}.
> * *Shared Root Cause*: heavyweight bcrypt hashing without rate limiting or pool isolation leads to CPU starvation.
> h2. Recommended Fixes
> # *Execution Isolation*: Dispatch password hashing work ({{ALTER ROLE ... PASSWORD}}, {{CREATE ROLE ... PASSWORD}}, etc.) to a constrained executor similar to {{authExecutor}}.
> # *Rate Limiting*: Enforce per-role, per-connection, or global throttles (e.g., token bucket) on password modifications.
> # *Asynchronous Hashing*: Optionally compute bcrypt off-thread and update the system tables once ready, returning an “operation queued” response (requires protocol changes, higher complexity).
> # *Operational Mitigations* (until a code fix ships):
> * Monitor CPU saturation closely; adjusting {{auth_bcrypt_gensalt_log2_rounds}} does not solve the issue but may highlight abuse sooner.
> * Tighten credential/role cache TTLs ({{roles_validity_in_ms}}, {{credentials_validity_in_ms}}) though this cannot block an active attacker.
> h2. Conclusion
> This vulnerability belongs to the same family as CASSANDRA-17812—bcrypt computations starving the main request pool. Because any authenticated account can trigger it with repeated {{ALTER ROLE}} statements, the risk is high. We recommend extending the rate limiting / dedicated executor strategy to all password-hashing pathways as soon as possible.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org