Tags: crypto cbc-bit-flipping

Rating: 0

# *Secured Logon*

## Information
| Points |Category | Level|
|--|--|--|
| 500 | Web Exploitation |Hard |

## Challenge
> Uh oh, the login page is more secure... I think. http://2018shell.picoctf.com:12004 ([link](http://2018shell.picoctf.com:12004)). [Source](https://2018shell.picoctf.com/static/914c9135423cd92f5fdb3ff2dec437d8/server_noflag.py).
### Hint

> There are versions of AES that really aren't secure.
## Solution

Let's open the link we got, looks like a normal site with a login form.
and it's worked too!
After login we can see this text:

> Success: You logged in! Not sure you'll be able to see the flag though.

and a title that say "No flag for you" :-(

![no flag for you](https://i.imgflip.com/2tv5ci.jpg)

Below all this there is a text say:

And this message popup -

> I'm sorry the admin password is super secure. You're not getting in that way.

So let's check the cookie that saved for this site.

Right click -> inspect Element -> choose the tab Storage (in Mozilla Firefox)

and we can see that there are a few cookies but the one who cached my eyes was with the name "cookie"

and the value was:

>C5PhO981qfZXWk6gh1+yzqek/cbh3lFbhlAG74fgPUinlzV1ZL3NAVaxvZwl5abNpCRwzXTBrjV9oeTZfk3XuQ==

For checking if it's connected to the login I tried to sign out and the cookie disappeared.
So basically this:

became to this:
C5PhO981qfZXWk6gh1+yzqek/cbh3lFbhlAG74fgPUinlzV1ZL3NAVaxvZwl5abNpCRwzXTBrjV9oeTZfk3XuQ==

And probably we want the admin value be 1.
So now it's the time to check the source code we got.
In the source code we can see that the code connected to the login form, and the cookie.
So what we can learn about the encryption?
There is a function named "encrypt":
**Raw** - the data we want to encrypt
2. Create the iv
3. Get the ciphertext
4. return the ciphertext as 64base code

So here is some basic definitions that I will use later:

- **Plaintext** - the text we want to encrypt.
- **IV** - the block of text we use to randomize the encryption.
- **Key** - the key we use in a symmetric encryption.
- **Ciphertext** - the encrypted text.

So after looking again in the function we can see that the encryption is AES with CBC mode,
the padding is for 16 Bytes and after the encryption the result coded by 64base code.

So here is some explanations of the concepts above:
**AES** - subset encryption of block cipher, in general (it's away more complicated) there is a
plaintext and a key,the plaintext divided for blocks of some bytes and each block encrypted with the key.

**CBC** - (**C**ipher **B**lock **C**haining) - the key for encryption for each block of the **plain**text is the the previous **cipher**text.
the first plaintext (that dosent have a previous ciphertext) key is the IV

So now after some digging in the internet about AES CBC mode I found a nice attack
called "CBC Byte Flipping Attack" - the purpose of the attack is to change byte of the plaintext by changing byte of the ciphertext.

This is exactly what we want, we want to change the 0 value of admin to 1, so we don't need to "crack" the encryption
but only to change 1 byte of the ciphertext and after decryption the plaintext will be the plaintext we wanted.

and the plaintext we want is:
and by reviewing the cookie in the browser we can see that our ciphertext is:

Sj1vwoe8gNvq/I7UdyXTms8/T2+yPPiy4xuZQ33nktu/5eb+8Xl2pvLb9QKyIrnfaIhmGZmW3U5iq5M0LA7Fkg==

so let's check which block of plaintext we want to change - (remember we found in the source code that each block is 16 byte)

|Block|Value |
|:--:|:--:|
| 2 | 'admin': **0**, 'pa |
| 3 | ssword': ''} |

So we want to change the first block in order to
make a change in the second block (that his key is the ciphertext of the first block).

> **"A rule of thumb is that the byte you change in a ciphertext will ONLY affect a byte at the same offset of next plaintext."**

so now we want to check the offset of the byte we want to change -

|Index|Text |
|:--:|:--:|
| 0 | (whitespace)|
| 1| '|
| 2 | a|
| 3 | d|
| 4| m|
| 5| i|
| 6| n|
| 7 | '|
| 8| :|
| 9| (whitespace)|
| **10**| **0** |
| ...|... |

Therefore we want to change the first block at the 10 index byte.
in order to change it from 0 to 1, we take this byte and do XOR with "0"
and after that XOR with "1".

The first XOR with cause the bits of "0" to be zero and
after XOR with "1" the bits of "1" will be on in the byte and we will get the new ciphertext.

So I wrote this python code:
python
from base64 import b64encode, b64decode

#decrypt the 64base code

#In order to work with the 10th char, make it a list (because string in python is immutable)

#ord - cast from char to number
#chr - cast from char to ascii
#Set the 10th char to be the XOR of him with "0" and XOR that with "1"

#join again the list to a string

#encode the string again as a 64base code

> picoCTF{fl1p_4ll_th3_bit3_a41d2782}