I've been a long-time user of KeePass. I inspected its 2.x .NET source code today and quickly noticed the following issues which I find quite concerning:
The kdbx database is encrypted with AES in CBC/PKCS7 mode without proper authentication. HMAC is nowhere to be found in the code, other than when used for sha1-totp. There are SHA2 hashes that seem to guard the integrity of ciphertext, while these might catch a typical file corruption they will not prevent malicious tampering. Even if the hashes are used prior to encryption, that's still MtE - not EtM.
KeePass likely does not have an online threat model, so attacks like Padding-Oracle might not be applicable, but a lack of AEAD is IMHO highly concerning because it indicates that the author(s) are winging it when it comes to doing crypto right.
Byte array comparisons are done with this function from MemUtil.cs:
public static bool ArraysEqual(byte[] x, byte[] y)
{
// Return false if one of them is null (not comparable)!
if((x == null) || (y == null)) { Debug.Assert(false); return false; }
if(x.Length != y.Length) return false;
for(int i = 0; i < x.Length; ++i)
{
if(x[i] != y[i]) return false;
}
return true;
}
There are many other questionable patterns, code smells, and "I-invented-it" approaches that indicate a non-expert .NET programming skill. They can't even implement a Singleton correctly (see CryptoRandom.cs).
Has anyone ever done a security audit of KeePass 2.x or does everyone just believe that it's "good enough"?
P.S. None of this detracts from the fact that KeePass is a very useful, free utility with a lot of effort put into it. I thank all contributors for making/improving it over the years.
To the many readers of this thread who believe they don't care about the integrity of their password vault, just its confidentiality:
The problem is you can't necessarily have confidentiality without integrity.
Sound cryptosystems that provide integrity checking rule out chosen ciphertext attacks against the cipher: in order to submit a ciphertext to such a system, you have to get past a cryptographically secure integrity check.
Without that check, attackers can feed a victim systematically corrupted ciphertexts, which the victim will dutifully decrypt, and observe the behavior of the victim in handling them. This is the basis for a whole family of "error oracle" side channel attacks.
You generally don't want to trust the confidentiality of a cryptosystem that doesn't check ciphertext integrity and rule out manipulated ciphertexts.
As the poster points out: this might matter a lot less for a system that runs purely offline. Or it might not. I lean towards "not a super plausible attack vector". But who knows? Why be OK with bad crypto?