Tags: crypto cbc-bit-flipping 

Rating:

# *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.
I tried to sign in with a random username and password - a:a
and it's worked?! maybe I chose the right username and password?
I tried to sign out and sign in as another username and password - b:b
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:

> Cookie: {'username': 'a', 'admin': 0, 'password': 'a'}

So maybe we just need to login as a admin?
I tried the username and password admin:admin.
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"
![name cookie](https://i.imgflip.com/2tv5uz.jpg)

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:

{'username': 'a', 'admin': 0, 'password': 'a'}
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
1. Get the raw and pad it (add bites)
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
![CBC encryption](https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/CBC_encryption.svg/601px-CBC_encryption.svg.png)

For more information about [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) and for [CBC](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_%28CBC%29).
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.
![Attack Explenation](https://mk0resourcesinfm536w.kinstacdn.com/wp-content/uploads/082113_1459_CBCByteFlip3.jpg)

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.

so our plaintext is: (after login with empty username and password)

{'username': '', 'admin': 0, 'password': ''}
and the plaintext we want is:
{'username': '', 'admin': 1, 'password': ''}
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 |
|:--:|:--:|
| 1 | {'username': '',|
| 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.
**For more information read [this](https://resources.infosecinstitute.com/cbc-byte-flipping-attack-101-approach/#gref) amazing article.**

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

cookie = 'Enter Your Cookie'
#decrypt the 64base code
Dcookie = b64decode(cookie)

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

#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"
listCookie[10] = chr(ord(Dcookie[10])^ord("0")^ord("1"))

#join again the list to a string
Dcookie = "".join(listCookie)

#encode the string again as a 64base code
print b64encode(Dcookie)
```
so this script print me the new ciphertext as the plain text was:

{'username': '', 'admin': 1, 'password': ''}
and now set this value as the value of cookie named "cookie" in the browser.
refresh the page, and...**vualá**
we got the flag!!

![vualá](https://i.imgflip.com/2tv5qk.jpg)

## Flag
> ``picoCTF{fl1p_4ll_th3_bit3_a41d2782}``

Original writeup (https://github.com/zomry1/picoCTF_2018_Writeup/tree/master/Web%20Exploitation/Secured%20Logon).