Are encrypted Cookies vulnerable to Padding Oracle Attacks

Is it necessary to sign or will a modified encrypted string fail to decrypt?

In the cryptography world a modified message is called a tampered message. Encryption by itself does not provide protection against tampering, but block ciphers are not used alone. Block ciphers are used in different modes, f.e. ECB, CBC, CTR, GCM, etc. Different modes have different properties, some of them provide protection against tampering (a.k.a. Authenticated Encryption, f.e. GCM) and others not.

If you're using an Authenticated Encryption mode a tampered message will fail to decrypt. But, if you're using others modes like CBC or CTR (These are the most widespread in my experience) a tampered message will happily decrypt unless there is a padding error

If it doesn't result in valid json which can be parsed into a session it will be empty in the same way that it would with an invalid signature.

This will depend on how your application handles an invalid json, and here is where a padding oracle may appear.

My understanding is that padding oracle attacks work by getting feedback from the server. Would an encrypted empty json string be enough?

A padding oracle attack occurs when the attacker sends a tampered message and is able to distinguish if the padding is correct or is not. And this is why I said previously that how your application handles an invalid JSON may derive into a padding oracle

Imagine that an attacker sends a tampered message with a wrong padding, your application will try to decrypt the message but a wrong padding exception will throw. After that the attacker tampers the message again but this time he's able to forge a correct padding, your application will decrypt correctly the message but the content will be and invalid JSON, the application will attempt to parse the invalid JSON and throw an error as it can't be parsed

If the attacker is able to distinguish both scenarios cause the HTTP status returned is different, or a stacktrace shows the different error messages, or just by timing the response time. Then the attacker has a padding oracle and can recover the plaintext from the cookie

To prevent this you should always provide same error message when the message can't be decrypted and when the message decrypts but the content is invalid. Furthermore you should ensure that both scenarios require the same time to respond.

IMO the best approach would be to use an authenticated encryption mode that gives you encryption and signing together and let the encryption framework/library handle it

BTW, I mentioned an encryption mode that should never be used. It's ECB, if you're using this mode (Some libraries default to it) please change it as it's a weak mode


The short answer is that you cannot rely on encryption to ensure the integrity of a message. See here for example.

To demonstrate why that general statement is also true for the specific example of this question, let's see how an attacker can modify an encrypted message. For the sake of simplicity I'm going to assume you're using AES-CBC encryption. Let's consider the following string:

{"Name":"Ryan Archer","Crime":"First Degree Murder","Judge 1":"Afred E Newman Jr","Verdict":"Not Guilty"}

When one AES-CBC encrypts the above string it will be encrypted in the following 16-byte blocks:

Block 0:   "Name":"Ryan Arc
Block 1:   her","Crime":"Fi
Block 2:   rst Degree Murde
Block 3:   r","Judge 1":"Al
Block 4:   fred E Newman Jr
Block 5:   ","Verdict":"Not
Block 6:   Guilty" 

And each block of the encrypted string will correspond with the the same block of the original cleartext string.

Now here's an interesting characteristic of CBC. Even if you don't know the encryption key you can modify the encrypted text in a way that when it is decrypted the clear text will be modified in a specific way.

Let's take the example above. If someone was to AES-CBC encrypt this string with some key and I don't know this key, if I XOR the last 3 bytes of block 4 of the encrypted text with the string "Not" then the impact on the decrypted text would be as follows:

  • Block 4 would be corrupted in an unknown random way.
  • The last 3 bytes of block 5 would be XORed with the string "Not"

So after decryption the string would read as follows:

Block 0:   "Name":"Ryan Arc
Block 1:   her","Crime":"Fi
Block 2:   rst Degree Murde
Block 3:   r","Judge 1":"Al
Block 4:   %$#$%@#%$@#%#%#$ (random garbage bytes)
Block 5:   ","Verdict":"
Block 6:   Guilty" 

And would be read as the following valid json string.:

"Name":"Ryan Archer","Crime":"First Degree Murder","Judge 1":"Al%$#$%@#%$@#%#%#$","Verdict":" Guilty"

The judge's name is randomly corrupted, but the attacker has successfully modified a critical portion of the message - Ryan Archer is now guilty of murder!

Of course not all strings are structured in such a way and it is possible that the random bytes in block 4 will corrupt the string so that it is no longer a valid json string. But an attacker can try this attack multiple times with various modifications of the encrypted string and sooner or later will get a valid json string.