Dr. Xernon has finally approved an update to James Brahm’s spy terminal. (Someone finally told them that ECB isn’t secure.) Fortunately, CBC mode is safe! Right? Connect with
nc 2018shell1.picoctf.com 22666.
Hint: What killed SSL3?
Googling the hint, we come across the POODLE attack. Apparently, this problem uses a weak form of encryption (AES CBC) that we can exploit to get the flag. However, there wasn’t good literature on exactly how to implement this attack.
Eventually, I came across this article which detailed the attack in more depth. The following explanation is derived from this article.
First to understand this exploit, its important to understand how CBC (Cipher Block Chaining) works.
The value of the previous ciphertext is xored with our plaintext before AES. Thus, when decrypting, we get something that looks like this.
There are two parts to our attack. First, we must align the blocks such that there is one full block of padding. Next, we replace our padding block with one of our previous ciphertext blocks that we want to decode.
Red is padding block, blue is block we want to decode
Crucial to our exploit is
The only way this function verifies our message is if the original padding scheme remains, where 16 bytes are removed. If 16 bytes are removed, we know that the last byte of our decrypted text is going to be
10 = 0x1 because of how
We also know the value of the last byte of the ciphertext that is xored with the plaintext. It’s the last byte in the 2nd to last block! Thus, the output of our decrypted blue block should be
0x1 ^ blocks[-2][-1]. Remember that we’re not done! This value still needs to be xored one more time. To finish, we xor this value with the last value of the block behind our blue block to arrive at plaintext.
Overall, we extract plaintext by calculating
0x1 ^ blocks[-2][-1] ^ prevBlock[-1]. By shifting around the padding, we can extract more and more characters.
Note that we can only extract plaintext when
verify_mac returns true. Because IV is randomized, there is a 1/256 chance that this attack works everytime. By brute forcing, we can eventually extract the entire plaintext.
My implementation can be found here.