Tags: web

Rating:

# Ezflag - TetCTF 2022

# Challenge Description


We found an internal storage system exposed to the internet. By ambushing one of the employee, we got some files and the credentials of the system: "admin:admin". Unfortunately, our agent was poisoned and cannot continue hacking. Can you help us?

Service: http://18.220.157.154:9090/
or
Service: http://3.22.71.49:9080/

Author: @nyancat0131
Solves: 47(part1) / 20(part2) / 591


# Inspection

We are given the source code of the server files. In lighttpd.conf we can see that the server is configured to execute all file with .py extension with python3. If we can upload a file with .py then we can run anything on the server

python
\$ tail conf/lighttpd.conf
#server.breakagelog = "/var/log/lighttpd/breakage.log"
alias.url += ( "/cgi-bin" => "/var/www/cgi-bin" )
cgi.assign = ( ".py" => "/usr/bin/python3" )


But how do we upload our file?

We know that the server is handled by upload.py. In the handle_post function we can see that it takes the file, check the file name is valid, normalized it, then store the file in the upload folder.

python
def handle_post() -> None:
fs = cgi.FieldStorage()
item = fs['file']
if not item.file:
return
if not valid_file_name(item.filename):
return
normalized_name = item.filename.strip().replace('./', '')
path = ''.join(normalized_name.split('/')[:-1])

However, since it doesn’t check the file name again after sanitization, we can abuse that to create the file name we want. By supplying a file with .p./y extension, the normalization will remove the ./from the file name and give us the desire .py extension.
Simply upload file with import os;os.system('cat /flag') give us the flag.
part 1 flag: TetCTF{65e95f4eacc1fe7010616e051f1c610a}