如何使用 PHP 检测 zip 炸弹?

Posted

技术标签:

【中文标题】如何使用 PHP 检测 zip 炸弹?【英文标题】:How to detect a zip bomb using PHP? 【发布时间】:2012-11-07 22:31:58 【问题描述】:

我正在制作一个 php 脚本,它使用 ZipArchive 对象检索用户给定的 zip 文件、解压缩并使用其中的文件做一些事情。如何避免像42.zip 这样的拉链炸弹?

【问题讨论】:

在您接受之前对上传的文件使用病毒扫描程序。 不能解压顶层吗? 如果我的回答有帮助,请告诉我,OP。 @MatthewBlancarte:好吧,有问题的 zip 没有。 @hakre:前提是病毒扫描程序本身不易受到 ZIP 炸弹的攻击。这只是增加了复杂程度,并没有真正解决问题。 【参考方案1】:

查看 zip_entry_filesize:http://php.net/manual/en/function.zip-entry-filesize.php

它应该为您提供 .zip 文件中未压缩存档的实际大小。以下是手册页评论中提供的示例函数:

function get_zip_originalsize($filename) 
    $size = 0;
    $resource = zip_open($filename);
    while ($dir_resource = zip_read($resource)) 
        $size += zip_entry_filesize($dir_resource);
    
    zip_close($resource);

    return $size;


$size = get_zip_originalsize('file.zip');
echo "original size: $size bytes\n";

【讨论】:

我用 2.4M 的零填充了一个 bomb 文件,我将它压缩成一个 bomb.zip 文件(2.4K),我将它复制了四次,然后我将五个 zip 文件压缩到file.zip (14K)。该函数给了我一个 12985 字节的原始大小,这是五个 zip 文件的大小,而不是整个大小。 其实我的 PHP 脚本不需要递归解压文件,所以其实用户提交一个 zip 炸弹就可以了,它会删除嵌套的 zip 档案,但我感兴趣的是解决方案拥有整个尺寸。 我自己一直在研究这个,虽然上面的函数确实返回了我多次压缩的文件的大小。对于42.zip,大小返回为0。我相信这是由于密码保护。 这也只检查顶层。对于 zip 中的 zip,它需要是递归的。 这个答案对于 PHP8 来说已经过时了。

以上是关于如何使用 PHP 检测 zip 炸弹?的主要内容,如果未能解决你的问题,请参考以下文章

使用apache poi - 检测到Zip Bomb

拉链炸弹的副作用?

如何让我的对象检测它是不是被点击?

zip解压及zip炸弹的防御

使精灵变形直到纹理不再连续 - 如何保持接触检测?

如何使用 PHP 下载 .zip 文件