3

Background

In the article How to Hack KeePass, the author used keepass2john on a KeePass database to extract a hash of its master password.

For the database CrackThis.kdb the extracted hash was (line breaks added by me)

$keepass$*
1*
6000*
0*
dfb86938fedd22b8235c4de4b02e5bb3*
c292fa502cbb0e912f30c1e1b6829a2c04ebe30477cb269d462fbbbeeb9360a6*
b85fb0e07f3edbd4123db2c829b79355*
6d4857a728900d4da4fad66999233e5c647e5354330d31be3a47bbdd102a5ca7*
0*
CrackThis

Which Hash is Actually Stored?

To understand the risks of storing such a hash, we have to know more about the hash. How is it computed and what was the input? What are the different values separated by *?

From the KeePass website I learned that KeePass executes something like the following routine.

var password = readPasswordFromUser();
var hash1 = SHA256(password);

var salt = getSaltFromDatabase();
var iterations = getIterationsFromDatabase(); // default 6'000
var hash2 = AES_KDF(hash1, salt, iterations); // key derivation function

The database is then encrypted/decrypted using AES with the key hash2.

Back to our extracted hash from above. There are three possibilities.

  • The stored/extracted hash is hash2. Since hash2 is used as the decryption key, this would be a disaster. I think we can exclude this one.

  • The stored/extracted hash is hash1. Storing hash1 renders the key derivation function (KDF) useless. The KDF is there to slow down bruteforce attacks. With hash1 an attacker doesn't have to deal with the slow KDF, but only with SHA256.

  • I misunderstood something and the extracted hash is neither hash1 nor hash2.

Main Question

Why does the KeePass database contain an unencrypted hash of its master password at all? To decrypt the database we don't need a hash, we just decrypt using a given password. If the password was wrong then the encrypted data will be nonsense, no problem.

If the stored hash is only there to prevent dealing with nonsense data when the user entered a wrong password by accident, then I don't get why they didn't use a less risky way. For instance, wouldn't it be safer to compute a checksum (not necessarily cryptographic, for instance CRC) of the database and encrypt checksum+database. On decryption, the checksum can be verified against the database.

4

The answer is in the the source code of keepass2john.c that you linked, from lines 156 to 163. The only hash included is the hash of the plaintext of the database. I let you read what the other fields represent, the source code is rather self explanatory.

TL;DR Keepass databases do not include the hash of the master password.

  • Thank you for your answer. I was confused because I extracted the hash, deleted the database (!), cracked the hash and got the password. By looking at the source code, I found out that the database was inlined into keepass2john's output (not shown in my post). – Socowi Aug 21 '17 at 20:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.