I have a scheme that, long story short, uses AES in CBC mode to encrypt third-party credentials for user accounts with a password-derived key. It's been mentioned that the use of CBC mode is a vulnerability because it is susceptible to "padding oracle attacks"; the cipher, after being initialized by the legitimate user with the proper key/IV, can be used by an attacker to execute a chosen-ciphertext attack to recover the plaintext without ever discovering the key.

The question is, do I actually have to worry about this type of attack given the way my system uses the cipher, specifically the fact that the cipher instance is only in existence for some seconds before its internal state is erased and it goes out of scope?

Perhaps more background is necessary. The basic scheme is that the user enters their username and password. The password is "stretched" by hashing it with SHA-512, and then that digest is split in half; one side is BCrypted for password verification by the server, the other half is the AES key used to decrypt the user credentials retrieved from the server.

So, the AES cipher isn't being used to maintain an open secure channel with a remote party; it's created, initialized, does its job on one message, and is then cleaned, disposed and garbage collected. This takes less than a second. To my way of thinking, this would make a POA infeasible, because the attacker would need an open, initialized instance of the cipher to bounce his chosen ciphertexts off of, which would take far longer than the second or two that the cipher instance is doing its job. Further, the cipher instance isn't being exposed to anyone outside the computer; if an attacker's in the computer, he has the user's password plain and simple, but an attacker can't even make a network request of the client computer that would involve the cipher in any way.

There are much easier attacks on this scheme as implemented, perhaps the simplest being that the AES key is derived rather simply from a user-chosen password (and we know how much entropy those have).

So, should I worry about the vulnerability of CBC mode to padding oracle attacks in my specific circumstance, or am I reasonably safe from that particular vector and should concentrate on other areas of weakness?

  • $\begingroup$ What do you mean by "decrypt the user credentials retrieved from the server"? Didn't the user send you his password? $\endgroup$ Jan 22 '13 at 23:53
  • $\begingroup$ The user has a password to the application. That application must authenticate with a third party, in my case a cloud provider, using a separate set of credentials. These credentials must be secured in reversible fashion; they can't be BCrypted like the main application password, because the client app needs them in plain text to send to the cloud provider. $\endgroup$
    – KeithS
    Jan 23 '13 at 0:53

If I understand your scenario correctly, padding oracle attacks are probably not a massive concern, but not for the reasons you seem to believe. Padding oracle attacks have nothing to do with maintained open channels, lack of garbage collection, or time the cipher is kept in memory.

A padding oracle attack requires two things: a ciphertext whose contents you wish to read, and a "padding oracle": more or less, a way to tell if a ciphertext that you've forged passed through the decryption algorithm successfully. If you never decrypting information directly received from users, then you are probably not significantly vulnerable. If users can supply ciphertexts to be decrypted, you are probably vulnerable. If an attacker can write to your database through something like SQL injection, you retrieve and decrypt ciphertexts from the database, and your service can be instructed to decrypt something stored in the database, you have bigger fish to fry, but you are probably also vulnerable to padding oracle attacks.

Long story short: if it is at all plausible that an attacker can feed you ciphertexts to decrypt, you should authenticate ciphertexts. Consider also if the contents of your ciphertexts should remain secure even in the face of other exploits. Since it's very hard to reason about what a motivated attacker might be able to do if given access to your system, you should absolutely default to using an AEAD mode unless you have a overwhelmingly compelling reason not to.

With that out of the way, you should highly reconsider how you handle passwords and encryption keys. SHA-512 by itself is not "key stretching", and the left half of SHA-512 plus bcrypt for digests, plus the right half for keys is tantamount to sprinkling cryptography around like magic pixie dust, expecting it to magick away security concerns.

For password digests, you should use BCrypt. SHA-512 plus BCrypt is probably not worse, per se, but it's unnecessary, and gains you nothing.

Your key derivation, however, is extraordinarily weak. SHA-512 is fast, and an attacker can trivially brute force his way through common passwords and use trial decryption to expose ciphertexts of users with weak passwords. You should use an actual key-stretching function such as PBKDF2. For each user, generate a cryptographically random 128-bit value. Compute the PBKDF2 of the user's password using this value as the salt, SHA-256 as the PRF parameter, an output length corresponding to the key length of your encryption algorithm (16 bytes for AES-128, 32 bytes for AES-256), and a number of iterations calibrated to take around 0.1s on your server hardware. Store the number of iterations and the salt. The output of this function should be used as your encryption key.

And, of course, don't overlook generating unique IVs for each encryption with a given key.

  • $\begingroup$ The symmetric decryption happens in a thick client application accessing a database server. Theoretically, this all happens inside a trusted network in the first place, but I'm trying to add some defense in depth because we've seen a few holes, and plaintext credentials in the DB are just a Very Bad Thing. The original scheme as designed assumed that connections from client to server couldn't use TLS, which currently holds. Therefore, the idea was that an attacker who'd penetrated the outer defense could never sniff credentials as they were passed back and forth inside our trusted network. $\endgroup$
    – KeithS
    Jan 23 '13 at 1:15
  • $\begingroup$ As designed, the scheme uses a service layer to do the BCrypting and initial password validation, before returning the encrypted credentials for decryption by the client. So, the initial round of SHA-512 was partially to obfuscate the password on its way to the server. Pre-imaging this hash naively with just the data seen on the wire would be difficult and would not necessarily produce the correct other half of the actual hash (but trying common passwords might). The encrypted data coming back is, well, encrypted, and the key is never sent over the wire, so that data's safe as well. $\endgroup$
    – KeithS
    Jan 23 '13 at 1:25
  • 1
    $\begingroup$ The point of encrypting is to prevent an attacker with access to the data from reading it. If you use an insecure method to generate keys such as the one described, an attacker who can intercept the data only need generate the SHA-512 hash of common passwords and do trial decryptions to reveal a large number of your plaintexts. You can defend the choice as much as you'd like, but it doesn't change the fact that your approach to key generation dramatically reduces the security of this traffic. If you're going to implement encryption anyway, why not do it right? $\endgroup$ Jan 23 '13 at 1:30
  • $\begingroup$ As built, however, there is no service layer performing any validation, so data is easy to get, and an attack could then be performed offline. The vector is still brute-forcing the password, not trying to reverse-engineer the plaintext. I still see no vector for a padding oracle attack that wouldn't require enough control over a legitimate user's system to simply install a keylogger. $\endgroup$
    – KeithS
    Jan 23 '13 at 1:30
  • 1
    $\begingroup$ In this case, it sounds like you probably are susceptible to padding oracle attacks. If you're sending packets encrypted in CBC mode back and forth between client and server, an attacker can simply forge his own packets and send them to either end. If an attacker can detect a difference between how the forged packet is processed (e.g., an error is returned, or it takes microseconds less time to handle a malformed ciphertext), he can exploit the padding oracle attack. $\endgroup$ Jan 23 '13 at 1:38

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.