1

I am trying to create a padding oracle attack to decrypt a cipher that is encrypted with cbc and PKCS#7 padding.

My first step is just to try and decrypt the second block.

I have read a lot about it, and have started to code the first step of the attack, where I edit last byte in the first block and send it to the oracle. But there is a point of the attack/decryption method I'm a bit confused about regarding the xor of the bytes.

The part I don't understand completely is the math on how manipulating the last byte in the first block result in the last byte in the decrypted byte to turns out to be 0x01, 0x02 etc.

I haven't figured out how the math for that works, for what I have researched it should just be to xor OriginalByte xor TestByte xor 1.

Should that be equal to 0x01?

Here I have a string "TestBlockForStackBBBBBBBBBBBa31", it is 31 bytes. That means that it has to get padded with 1 to make it equal to 32 bytes so it fits inside 16 byte blocks. The string byte is as following (without encryption):

54657374426C6F636B466F72537461636B4242424242424242424242613331

Then we decrypt the string with the key and IV below using cbc and PKCS#7.

byte[] Key = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9}; 
       //we don't need key the key under the attach, only under encryption.
byte[] IV  = new byte[]{2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2 };

We then get this result:

Ciphertext:  ;fŒ˜ÆOgÄ:VûÎ{Ž+6iXK¿îMŠžÌš

Cipher bytes: 3B668C98C64F67C43A56FBCE7B8E150E9D2B1F3669584BBFEE4D8A0E189ECC9A

Under the padding oracle attack I edit the last byte in the first block

(3B668C98C64F67C43A56FBCE7B8E15 0E <--).

I know that when I edit the last byte in the first block to 0D the decryption result will have a 0x01 at the end. The first block is then going to look like this:

3B668C98C64F67C43A56FBCE7B8E150D

And what I then send to the oracle in this case DecryptStringFromBytes (code can be found in RijndaelManaged.CreateDecryptor Method) is the following first the edited chiper 3B668C98C64F67C43A56FBCE7B8E150D9D2B1F3669584BBFEE4D8A0E189ECC9A, then the key that is only 0 (Key = new byte[16]), then the same iv as above.

It then returns that the padding is valid. I did go into the function BCryptDecrypt (used inside the decryption call) and set a breakpoint to confirm this, and it is indeed 0x01.

The output bytes from the call BCryptDecrypt is then like this:

 [0]  0x95    byte        [1] 0x28    byte        [2] 0xE5    byte        [3] 0x18    byte
 [4]  0x90    byte        [5] 0x8E    byte        [6] 0x31    byte        [7] 0xFF    byte
 [8]  0xF0    byte        [9] 0x28    byte       [10] 0x86    byte       [11] 0x7B    byte
[12]  0x9D    byte       [13] 0x63    byte       [14] 0x2F    byte       [15] 0x01    byte

The decrypted file result that returns from the decrypter to the user looks like this:

Text :  ?????xi?G?w?T}!y?(???1??(?{?c/ Bytes : 
3F3F3F3F3F78693F473F773F547D21793F283F183F3F313F3F283F7B3F632F (Thay
have removed the 0x01 and the bytes is a bit different, maybe something
with how I formatted it or it does something more before returning the
bytes?)

So my questions are:

  • How does the info I did send turn out to be 0x01 at the end?
  • What do I need to xor to the result to get the plaintext/byte?
yostart123
  • 11
  • 1

1 Answers1

1

You don't start by manipulating the last byte of the first block. Rather you manipulate the last byte of the last block. You start at the end and work backwards. The side-channel leak in the padding oracle attack is that the server distinguishes between a bad cipher and bad padding. This is the leak that lets you figure out the message.

If you try every possibility for the last byte, the server will tell you if the padding is bad. If you get no "bad padding" error you know the value you tried is likely 1 xor'd with what will decrypt the last byte of the actual message. So then you try changing the last two values to get "2" and "2". You already know to xor 2 with the last value at the end that gave no bad padding error. So it's a matter of figuring out the second to last byte and trying every byte until you get no padding error and so on.

The best way to understand this that I know of is to do the cryptopals challenge (google it). It's also very helpful to look at a diagram of how CBC works because you can visualize what's happening.

robotcookies
  • 111
  • 3