6 KiB
Padding Oracle
CBC - Cipher Block Chaining
In CBC, the encryption uses the previous encrypted block as IV to XOR with the following block as you can see in the following image taken from Wikipedia:
To decrypt CBC the opposite operations are done:
Notice how it's needed to use an encryption key and an IV.
Message Padding
As the encryption is performed in fixed size blocks, padding is usually needed in the last block to complete its length.
Usually PKCS7 is used, which generates a padding repeating the number of bytes needed to complete the block. For example, if the last block is missing 3 bytes, the padding will be \x03\x03\x03
.
Let's look at more examples with a 2 blocks of length 8bytes:
Block #0 | Block #1 | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 |
P | A | S | S | W | O | R | D | 1 | 2 | 3 | 4 | 5 | 6 | 0x02 | 0x02 |
P | A | S | S | W | O | R | D | 1 | 2 | 3 | 4 | 5 | 0x03 | 0x03 | 0x03 |
P | A | S | S | W | O | R | D | 1 | 2 | 3 | 0x05 | 0x05 | 0x05 | 0x05 | 0x05 |
P | A | S | S | W | O | R | D | 0x08 | 0x08 | 0x08 | 0x08 | 0x08 | 0x08 | 0x08 | 0x08 |
Note how in the last example the last block was full so another one was generated only with padding.
Padding Oracle
When an application decrypts encrypted data, it will first decrypt the data; then it will remove the padding. During the cleanup of the padding, if an invalid padding triggers a detectable behaviour, you have a padding oracle vulnerability. The detectable behaviour can be an error, a lack of results, or a slower response.
If you detect this behaviour, you can decrypt the encrypted data and even encrypt any cleartext.
How to exploit
You could use https://github.com/AonCyberLabs/PadBuster to exploit this kind of vulnerability or just do
sudo apt-get install padbuster
In order to test if the cookie of a site is vulnerable you could try:
perl ./padBuster.pl http://10.10.181.45/index.php "Nl0OpaQYeGPMJeWSih2iiQ==" 8 -encoding 0 -cookies "auth=Nl0OpaQYeGPMJeWSih2iiQ=="
Encoding 0 means that base64 is used but others are available, check the help menu
.
You could also abuse this vulnerability to encrypt new data. For example, imagine that the content of the cookie is "user=MyUsername", then you may change it to "user=administrator" and escalate privileges inside the application. You could also do it using paduster
specifying the -plaintext parameter:
perl ./padBuster.pl http://10.10.181.45/index.php "Nl0OpaQYeGPMJeWSih2iiQ==" 8 -encoding 0 -cookies "auth=Nl0OpaQYeGPMJeWSih2iiQ==" -plaintext "user=administrator"
If the site is vulnerable padbuster
will automatically try to find when the padding error occurs, but you can also indicating the error message it using the -error parameter.
perl ./padBuster.pl http://10.10.181.45/index.php "Nl0OpaQYeGPMJeWSih2iiQ==" 8 -encoding 0 -cookies "hcon=Nl0OpaQYeGPMJeWSih2iiQ==" -error "Invalid padding"
The theory
In summary, you can start decrypting the encrypted data by guessing the correct values that can be used to create all the different paddings. Then, the padding oracle attack will start decrypting bytes from the end to the start by guessing which will be the correct value that creates a padding of 1, 2, 3, etc.
Imagine you have some encrypted text that occupies 2 blocks formed by the bytes from E0 to E15.
In order to decrypt the last block **E8** to **E15**
, the whole block passes through the "block cipher decryption" generating the intermediary bytes I0 to I15.
Finally, each intermediary byte is XORed with the previos encrypted bytes E0 to E7
. So:
C15 = D(E15) ^ E7 = I15 ^ E7
C14 = I14 ^ E6
C13 = I13 ^ E5
C12 = I12 ^ E4
- ...
Now, It's possible to modify E7
until C15
is 0x01
, which will also be a correct padding. So, in this case: \x01 = I15 ^ E'7
So, finding E'7, it's possible to calculate I15: I15 = 0x01 ^ E'7
Which allow us to calculate C15: C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7
Knowing C15, now it's possible to calculate C14, but this time brute-forcing the padding \x02\x02
.
This BF is as complex as the previous one as it's possible to calculate the the E''15
whose value is 0x02: E''7 = \x02 ^ I15
so it's just needed to find the E'14
that generates a C14
equals to 0x02
.
Then, do the same steps to decrypt C14: C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6
Follow this chain until you decrypt the whole encrypted text.
Detection of the vulnerability
Register and account and log in with this account .
If you log in many times and always get the same cookie, there is probably something wrong in the application. The cookie sent back should be unique each time you log in. If the cookie is always the same, it will probably always be valid and there won't be anyway to invalidate it.
Now, if you try to modify the cookie, you can see that you get an error from the application.
But if you BF the padding using padbuster for example
you manage to get another cookie valid for a different user. This scenario is highly probably vulnerable to padbuster.