1
$\begingroup$

Say I have plaintext database with key-value pairs of usernames and passwords. Then I iterate through the database, encrypt the passwords, and write the username and encrypted password pairs to file with a specific format: I would be storing the salt, IV, and an encrypted hash checksum (for authentication to file) in the headers. The rest of the file would be the username-encrypted password pairs. There are indicators that specify how many bytes the username and passwords are. What would be some of the security issues with this file format?

$\endgroup$
  • $\begingroup$ simplest point: You're re-using salts for the password hashing and so an attacker can observe which users have the same password. $\endgroup$ – SEJPM Apr 2 '16 at 12:25
  • $\begingroup$ cross-posted on sec.se $\endgroup$ – SEJPM Apr 2 '16 at 13:16
  • $\begingroup$ @SEJPM Thank you, that's a very good point. Are there more complex scenarios? $\endgroup$ – katsup Apr 2 '16 at 13:36
4
$\begingroup$

I'll start with the usual reminder: Please don't roll your own crypto, chances are you're getting it wrong.

For password databases, KDBX (KeePass' format) usually is a good example which you strongly should consider using. For an analysis of some format, also see "On The Security of Password Manager Database Formats" by Gasti and Rasmussen (PDF).


For understandability I'll quickly re-iterate your format more formally:

  • Header: $IV || \text{Salt} || E_{K,IV}(R||H(R)||0^{128})$
  • Data pairs: $\text{UsernameLength}||\text{Username}|| \text{PasswordLength} || E_{K,IV}(\text{password})$

where $E_{K,IV}$ denotes PKCS#7 padded AES-128-CBC encryption using the key $K$ and the IV $IV$ where $K$ is derived from $\text{MasterPassword}$ and $\text{Salt}$ as $K=H(\text{Salt}||r||\text{MasterPassword})$. The password is considered valid if the last header entry yields a consistent decryption. $R$ denotes a 256-bit random string and $r$ an 8-bit random string.


I'll start the answer with security issues of the format as stated and will conclude with potential security issues based on the information not given. The complete analysis is based on the recap I gave above, which is based on the comments given on InformationSecurity.SE, on the information from the question and the information given in the comments of this answer.

The first and potentially most devestating point: IV re-use. The scheme is re-using the IV for all encryptions which allows an attacker to detect the shared prefix between passwords. The mitigation is simple: Either use a well-established storage format, use a random IV for each encryption or encrypt the whole bulk data (including lengths and user names) in one go.

The second most interesting issue is that the lack of integrity protection. There is no authentication of the data, if an attacker changes any part of the ciphertext and the padding remains intact, the user won't notice that anything changed. This allows an attacker to run a denial-of-service attack on the user by cleverly introducing malicious changes into the plaintext, resulting in complains (caused by frustration of not being able to log-in) that your storage format is garbage, because the data won't be keepen and it could be leveraged to a scenario where the attacker can learn the password, by causing the user to reset his on a specific account and if the attacker broke the e-mail account he would know the new password without the user even suspecting an attacker sniffed the password. The mitigation is relatively simple: Use a well-established standard or use authenticated encryption (such as AES-GCM) paired with a proper alarming error message upon decryption failure like "this data has been maliciously corrupted".

The third security issue is the explicit length leaking. This scheme leaks the length of every single password, allowing an attacker to choose which to brute-force first and thereby easing up the attackers work significantly. The mitigation is again simple: Either use a well-established standard or do the encryption in one go over the entire data, so an attacker can't identify the exact lengths and where passwords start and end.

The last issue I could identify is that the username is leaked. This allows an attacker to potentially identify where the user is registered and run spear phishing attacks and / or brute-force attacks on the user. Additionally it may help an attacker to identify the user in leaked password dumps and use the file to recover possible password re-uses of this password (just try all sites you could identify with the otherwise leaked password and the given username). The mitigation is the same as for the previous point: Use a well-established standard or run the encryption over the entire data.

The scheme uses AES-CBC, which is completely unauthenticated which allows for many advanced attacks as detailed above, so the recommendation is to use authenticated encryption modes like AES-GCM, AES-OCB, AES-EAX or AES-CCM, which will take care of the authentication for you and use strong ciphers (e.g. AES).

The scheme uses very weak password based key-derivation, which requires up to 257 hashes and 4 AES encryptions to verify a password guess. This is extremely weak and allows for fast brute-force attacks on the master password, which is bad as many users will chose a weak password which requires few tries which will require a short amount of time, as 257 hashes and 4 AES encryptions are basically "nothing" to slow down a sophisticated attacker. The mitigation is clear as usual: Use a well-established format or use a strong PBDKF like Argon2, bcrypt or scrypt.

The header you're specifying lacks a mean to store parameters for password based key derivation. This implies that the scheme is vulnerable to simple progress of technology. To demonstrate the issue, simply look at TrueCrypt. It uses 1000 or 2000 iterations of a hash function for password based key derivation, which was fine a decade ago. The file format specification didn't allow for variable iterations and thus TrueCrypt is still using this low iteration count, resulting in minimal defense against password brute-force attacks. The mitigation is clear: Use a well-established scheme or store the parameters in your header.

$\endgroup$
  • $\begingroup$ Thank you very much for a very detailed response. To answer some of the ambiguities: the encryption algorithm that is used is AES-128 operating in CBC mode. I used the PKCS#7 padding scheme to pad the passwords before encryption. I used a hash digest of the salt + random char + master password for the key. For authentication, using the algorithm, key and IV, I have an encrypted 64 bytes, when decrypted will produce 32 bytes of a random string, 16 bytes of a hash checksum of that string, and 16 0's. If the hash digest of that random string equates to the checksum, we will authenticate the user. $\endgroup$ – katsup Apr 3 '16 at 7:29
  • $\begingroup$ I'm having a hard time understanding the second issue you have presented, but maybe the information I just gave changes that a bit. $\endgroup$ – katsup Apr 3 '16 at 7:33

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.