Skip to content

Instantly share code, notes, and snippets.

@righettod
Last active December 9, 2020 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save righettod/e50d2c4b5e6e28b002cafe2c0fa40f5e to your computer and use it in GitHub Desktop.
Save righettod/e50d2c4b5e6e28b002cafe2c0fa40f5e to your computer and use it in GitHub Desktop.
Function to validate that a ZIP file do not contains "ZIP SLIP" payload entries.
<?php
/**
* Function to validate that a ZIP file do not contains "ZIP SLIP" payload entries.
* @param string $zipFilePath Path to the ZIP to test.
* @return bool TRUE only if the archive do not contains ZIP SLIP payload entries.
* @link https://snyk.io/research/zip-slip-vulnerability
* @link https://stackoverflow.com/a/3599093/451455 (inspired from)
*/
function isZipValid($zipFilePath){
$isValid = false;
$invalidEntryCount = 0;
try {
$zip = zip_open($zipFilePath);
if ($zip)
{
while ($zipEntry = zip_read($zip))
{
$completeName = zip_entry_name($zipEntry);
//See https://www.php.net/manual/en/function.strpos.php
if(strpos($completeName, "..") !== false){
$invalidEntryCount++;
}else{
//Handle case of symlink, read the first 1KB of the entry and check them.
//This check is prone to bypass if the payload is over the first 1KB so
//feel free to apply this check on the entire content of the entry.
$content = zip_entry_read($zipEntry, 1024);
$finfo = new finfo(FILEINFO_MIME);
$mimeFull = $finfo->buffer($content);
$mime = trim(explode(";",$mimeFull)[0]);
if($mime === "text/plain" && strpos($content, "..") !== false){
$invalidEntryCount++;
}
}
}
$isValid = ($invalidEntryCount === 0);
}
} catch (Exception $e) {
$isValid = false;
//Log error
}
return $isValid;
}
//Call example
if(isZipValid("temp.zip")) { echo("IS VALID"); } else { echo("IS INVALID"); }
@righettod
Copy link
Author

righettod commented Dec 9, 2020

Execution example:

$ php zipslip_validation.php
ENTRY: ../../../../../../../../var/www/zUXB.php
IS INVALID

$ php zipslip_validation.php
ENTRY: 10k-most-common.txt
ENTRY: 45HhTLsOsAl1zqYjMJ4s/
ENTRY: 45HhTLsOsAl1zqYjMJ4s/scripts/
ENTRY: 45HhTLsOsAl1zqYjMJ4s/scripts/class/
ENTRY: 45HhTLsOsAl1zqYjMJ4s/scripts/class/Action/
ENTRY: 45HhTLsOsAl1zqYjMJ4s/scripts/class/Action/Admin/
ENTRY: 45HhTLsOsAl1zqYjMJ4s/scripts/class/Action/Admin/admin.php
ENTRY: 45HhTLsOsAl1zqYjMJ4s/scripts/test.inc
ENTRY: probable-v2-top12000.txt
ENTRY: rockyou.txt
IS VALID

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment