Tags: aes-cbc crypto 

Rating:

# Jean-Sébastien Bash

We get a shell which only accepts encrypted commands, and the `/help`
function tells us the format is:

```
/cmd AES(key, CBC, iv).encrypt(my_command)
```

We also get a sample command, and if we try running it we will get
some fairly helpful output:

```
Running b'ls -l'
total 8
-rw-r--r-- 1 root root 21 Apr 25 21:18 flag.txt
-rwxr-xr-x 1 root root 2066 Apr 25 21:50 server.py
```

If we try running `/cmd <random string>`, we will just get a "What do
you mean?!" error. We can assume that we get the error due to
incorrect padding, and can try an attack that looks a bit like a
padding oracle (but doesn't quite go through the entire process). We
will take an arbitrary 32-byte string, and try all possible values for
the sixteenth byte until we hit a string with valid padding (since the
last byte of the decrypted data is xored with the last byte of the
first block).

Once we find it, the server will tell us what it decrypts to and try
to execute (and get a bunch of errors, since it is gibberish). We can
now change the start of the first block to get a command in the second
block. Since we cannot control what comes before the command, we will
simply add a semicolon before and after:

```
# the string with correct padding we found
get = b'\x15\x02\x9c;\x95\xe6\xcc\xe3\x10B\x97\x90\x9d7EYU\xad0A\xf8\xd6\x1f\xea\xaf\xd6\xf7\xa0>\x84D'

want = '; cat flag.txt;'

for i, w in enumerate(want):
base[i] = base[i] ^ ord(w) ^ get[i+16]

print('/cmd', binascii.hexlify(bytes(base)).decode('ascii'))
```

Submitting this to the server runs `<random data>; cat flag.txt;
<random>`, which throws several errors, but also prints the flag.