You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by "Cyl (Jira)" <ji...@apache.org> on 2026/03/18 06:47:00 UTC

[jira] [Updated] (CASSANDRA-21232) Authenticated DoS via `ALTER ROLE ... WITH HASHED PASSWORD`

     [ https://issues.apache.org/jira/browse/CASSANDRA-21232?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Cyl updated CASSANDRA-21232:
----------------------------
    Component/s: Feature/Authorization
                 Feature/Rate Limiting
         Labels: dos performance security  (was: )

> Authenticated DoS via `ALTER ROLE ... WITH HASHED PASSWORD`
> -----------------------------------------------------------
>
>                 Key: CASSANDRA-21232
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-21232
>             Project: Apache Cassandra
>          Issue Type: Bug
>          Components: Feature/Authorization, Feature/Rate Limiting
>            Reporter: Cyl
>            Priority: Normal
>              Labels: dos, performance, security
>
> # Authenticated DoS via `ALTER ROLE ... WITH HASHED PASSWORD`
> ## 1. Vulnerability Description
> **Name**: Authenticated DoS via `ALTER ROLE ... WITH HASHED PASSWORD`
> **Overview**:
> The `ALTER ROLE` and `CREATE ROLE` statements support a `HASHED PASSWORD` option, which allows setting a password by providing its bcrypt hash directly. To validate the provided hash, Cassandra calls `BCrypt.checkpw("dummy", hash)` in `org.apache.cassandra.auth.RoleOptions.validate()`. This validation occurs synchronously on the main request executor thread (`Dispatcher.requestExecutor`).
> An attacker can provide a bcrypt hash with an extremely high cost factor (e.g., `$2a$30$...`). `BCrypt.checkpw` will attempt to hash the string "dummy" using the provided salt and cost factor. A cost factor of 30 means $2^{30}$ iterations, which takes an impractical amount of time to complete. Even a cost factor of 24 (16 million iterations) can block a thread for minutes. By sending multiple such requests concurrently, an authenticated attacker can exhaust the request executor thread pool, causing a complete denial of service.
> **Affected Configurations**:
> - Clusters running `PasswordAuthenticator`.
> - Any authenticated account that can `ALTER` a role (including their own) or `CREATE` a role.
> **Impact**:
> - Complete denial of service.
> - The server becomes unresponsive to all CQL requests.
> - CPU usage spikes to 100% on all cores if enough requests are sent.
> ## 2. Proof-of-Concept
> The file `poc_hashed_dos.py` demonstrates the attack:
> 1.  Start a Cassandra instance.
> 2.  Launch 200 concurrent threads that run `ALTER ROLE target_role WITH HASHED PASSWORD '<high_cost_hash>'`.
> 3.  The hash used has a cost factor of 24 (`$2a$24$...`), which causes `BCrypt.checkpw` to run for a very long time.
> 4.  Monitor the latency of a simple `SELECT now()` query.
> **Observed Output**:
> ```
> [Victim] Query latency: 0.0599s
> [Victim] Query latency: 0.1278s
> [Victim] Query latency: 1.2976s
> [Victim] Query failed/timed out: ...
> ```
> The server quickly becomes unresponsive.
> ## 3. Problematic Code Reference
> In `src/java/org/apache/cassandra/auth/RoleOptions.java`:
> ```java
>                 case HASHED_PASSWORD:
>                     // ...
>                     try
>                     {
>                         // This runs on the request thread
>                         BCrypt.checkpw("dummy", (String) option.getValue());
>                     }
>                     catch (Exception e)
>                     {
>                         throw new InvalidRequestException("Invalid hashed password value. Please use jBcrypt.");
>                     }
>                     break;
> ```
> In `src/java/org/apache/cassandra/cql3/statements/AlterRoleStatement.java`:
> ```java
>     public void validate(ClientState state) throws RequestValidationException
>     {
>         opts.validate(); // Calls RoleOptions.validate()
>         // ...
>     }
> ```
> ## 4. Recommended Fixes
> 1.  **Limit Cost Factor**: Enforce a maximum allowed cost factor for `HASHED_PASSWORD` (e.g., 12 or matches the server configuration). Reject hashes with higher cost factors immediately without calling `BCrypt.checkpw`.
> 2.  **Offload Validation**: Perform the validation on a separate thread pool (like `authExecutor` introduced in CASSANDRA-17812) or asynchronously.
> 3.  **Rate Limiting**: Apply rate limiting to `ALTER ROLE` and `CREATE ROLE` statements.
> ## 5. Comparison with Previous Vulnerability
> This is related to the vulnerability described in `README.md` (DoS via `ALTER ROLE ... WITH PASSWORD`), but it is more severe because:
> 1.  The attacker controls the cost factor via the hash string. In the `PASSWORD` case, the cost factor is determined by the server configuration (`auth_bcrypt_gensalt_log2_rounds`), which is typically low (default 4-10).
> 2.  A single request with a high cost factor (e.g., 30) can block a thread effectively forever, whereas the `PASSWORD` attack requires many requests to saturate the CPU with lower-cost hashes.



--
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