Nadav Har'El created CASSANDRA-21744:
----------------------------------------

             Summary: CREATE ROLE ... WITH HASHED PASSWORD accepts a bcrypt 
hash with missing or extra characters
                 Key: CASSANDRA-21744
                 URL: https://issues.apache.org/jira/browse/CASSANDRA-21744
             Project: Apache Cassandra
          Issue Type: Bug
            Reporter: Nadav Har'El


Since CASSANDRA-17334, {{RoleOptions.validate()}} validates a {{HASHED 
PASSWORD}} by calling {{BCrypt.checkpw("dummy", hash)}}. It rejects a string 
like {{'this_is_an_invalid_hash'}} with "Invalid hashed password value. Please 
use jBcrypt.".

However, {{BCrypt.checkpw()}} parses only the setting at the beginning of the 
hash: {{$2a$}}, the two-digit cost, {{$}} and the 22-character salt. It ignores 
the rest. When the rest is wrong, it returns false instead of throwing. So a 
string which starts with a valid bcrypt setting is accepted even if it is 
truncated, has an extra character, or has no hash part at all. No password can 
ever match such a string, so the role can never log in.

For example, {{$2a$04$PoiUnv/9OZ5nYjlN087uIe5KLMV6yJfDkgKAAHO0pRVTEvB3UQU/i}} 
is a valid bcrypt hash of the password "super_secret_thing". All of the 
following statements succeed:

{code:sql}
-- one character missing:
CREATE ROLE r1 WITH LOGIN = true AND HASHED PASSWORD = 
'$2a$04$PoiUnv/9OZ5nYjlN087uIe5KLMV6yJfDkgKAAHO0pRVTEvB3UQU/';
-- one extra character:
CREATE ROLE r2 WITH LOGIN = true AND HASHED PASSWORD = 
'$2a$04$PoiUnv/9OZ5nYjlN087uIe5KLMV6yJfDkgKAAHO0pRVTEvB3UQU/ix';
-- only the setting and salt, no hash:
CREATE ROLE r3 WITH LOGIN = true AND HASHED PASSWORD = 
'$2a$04$PoiUnv/9OZ5nYjlN087uIe';
{code}

Expected: they should be rejected with "Invalid hashed password value", just 
like {{'this_is_an_invalid_hash'}}.

h3. Possible fix
After the setting, a bcrypt hash contains the encoding of the 23-byte bcrypt 
output, which is always 31 characters. So every valid bcrypt hash has exactly 
the same length, 60 characters: 7 for {{$2a$NN$}}, 22 for the salt and 31 for 
the hash. The crypt(5) manual page documents this format as:
{noformat}
\$2[abxy]\$[0-9]{2}\$[./A-Za-z0-9]{53}
{noformat}
jBCrypt's {{hashpw()}} always produces a string of this format.

So in addition to calling {{checkpw()}}, {{RoleOptions.validate()}} could check 
that the given hash has the same length as {{BCrypt.hashpw("dummy", hash)}}, 
which is 60 characters. Or it could match the hash against the regular 
expression above.

Reproduced on Cassandra 5.0.9 and 6.0-alpha2.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to