Tags: padding optimization bruteforce aes aes-ecb 

Rating:

# CSAW '17
## baby_crypt (crypto 350)

https://ctf.csaw.io/challenges#baby_crypt

> The cookie is `input + flag` AES ECB encrypted with the sha256 of the flag as the key.

>`nc crypto.chal.csaw.io 1578`

### Recon

They only gave us a link to the server, so this is a blackbox challenge. There's no binary or script to analyze, so let's start with the encryption method: AES-ECB. One known issue with ECB is that blocks are encrypted independently of each other; that means that two blocks that have the same contents are going to be encoded the same way. Because our input is prepended to the flag, we have an attack vector. We can control how much of the unknown flag is inside a block that we control.

### Exploitation

To exploit this vulnerability, we can send the server 15 bytes, example:
```
A A A A A A A A A A A A A A A
41414141 41414141 41414141 414141
```
When we send this, the exchange looks like:
```
Enter your username (no whitespace): AAAAAAAAAAAAAAA
Your Cookie is: 79d6ef8b25ab8e64c452f9f5eb90e418ac30cc07bdb589446fa1fe24fad8f4060569323ed7299f231ccf7192a4cde656
```
We can see that the output is 48 bytes long, or 3 blocks. If we remove the block containing our input, that tells us that the flag is at most 32 bytes long (technically 33, but we'll ignore that, it is actually 32). Remember that for later.

We now only care about the first block (16 bytes) of the cookie, since that is what we control. Remember, this block is the encrypted form of our input plus the first character of the flag:
```
79d6ef8b 25ab8e64 c452f9f5 eb90e418
```
Once we have this, we can brute force the first character of the flag. We can append any printable character to the input, send it to the server, and check to see if it matches our block. By doing this, we find that the first character of the flag is `f`. We can now modify our payload to overflow 2 characters, knowing that the 15th character will be f and use this to brute-force the next character:
```
A A A A A A A A A A A A A A
41414141 41414141 41414141 4141
```
Once we have our encrypted value, we append what is known of the flag, and we begin brute-forcing the next character. Repeat the cycle until there is no longer a match or we've run out of characters.

For the sake of simplicity, I've only shown 1 block here, but like I've mentioned above, we know the flag is actually at most 32 characters. That requires 2 blocks of padding instead of 1, and therefore we check against the second block, since that is now the block that contains the unknown character.

### Fix
This specific vulnerability in ECB could be mitigated by instead encrypting `flag + input`. This ensures that the user does not have control over the position of `flag` during encryption. However, I would highly recommend using other ciphers over ECB. As I previously stated, the much larger issue is that equal blocks of plaintext will be equal in ciphertext, even when encrypted together. There is virtually no entropy; an attacker would be able to notice patterns in the ciphertext just as well as if it were plaintext. If the communication often contains repeated messages, it would be fairly easy to predict them. The correct fix would be to use a different AES cipher if you are encrypting more than 1 block of data at any time.

### Solution

The final exploit is contained in [`exploit.py`](https://gitlab.com/AGausmann/ctfs/blob/master/2017/csaw/baby_crypt/exploit.py).

`flag{Crypt0_is_s0_h@rd_t0_d0...}`

Original writeup (https://gitlab.com/AGausmann/ctfs/blob/master/2017/csaw/baby_crypt).