PicoCTF 2018 - 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). Source.

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

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

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 - (Cipher Block Chaining) - the key for encryption for each block of the plaintext is the the previous ciphertext.
the first plaintext (that dosent have a previous ciphertext) key is the IV
CBC encryption

For more information about AES and for CBC.
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

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 amazing article.

So I wrote this python code:

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á

Flag

picoCTF{fl1p_4ll_th3_bit3_a41d2782}

Downloads