Zip Slip is a vulnerability that allows an attacker to upload a file to unintended location with a specially crafted zip file. Although Styk named the vulnerability as zipslip in 2018, it’s essentially classic path traversal via archive extraction.
How zipslip occurs
import zipfile
def unzipper(zip_path, extract_to):
with zipfile.ZipFile(zip_path, 'r') as z:
for member in z.namelist():
z.extract(member, extract_to)
if __name__ == "__main__":
unzipper("zipslip.zip", "output_folder")
When this kind of code extracts a zip file, if a file name contains ../
, that file will get out of the folder.
How to prevent zipslip
import os, zipfile
def safe_unzipper(zip_path, extract_to):
with zipfile.ZipFile(zip_path, 'r') as zf:
for member in zf.namelist():
path = os.path.normpath(os.path.join(extract_to, member))
if path.startswith(os.path.abspath(extract_to)):
zf.extract(member, extract_to)
if __name__ == "__main__":
safe_unzipper("zipslip.zip", "output_folder")
path = os.path.normpath(os.path.join(extract_to, member))
resolves any ../
inside member
and if path.startswith(os.path.abspath(extract_to)):
makes path stay within extract_to
.
How to create a file for zipslip
To exploit a zipslip vulnerability, you have to name a file inside the zipped folder with ../
inside. The problem is if you try to name it that way, the system prevents you from doing it.
To avoid this, first create a zip folder normally
zip zipslip.zip test.txt
Use zipnote
to extract file names from the zip folder:
zipnote zipslip.zip > names.txt
The content inside names.txt
looks like this:
@ test.txt/
@ (comment above this line)
@ (zip file comment below this line)
Add the new name like this:
@ test.txt/
@=../zipslip/test.txt
@ (comment above this line)
@ (zip file comment below this line)
Use zipnote
to update the name:
zipnote -w zipsip.zip < names.txt
Since modern tools normalize file paths during extraction, even if you open this zipped folder, test.txt will still be inside the folder. To test this, use a custom unzip tool or pick a old one that’s known to be vulnerable.