我正在使用这个函数调用,因为当我读取一个受信任的文件时,它会导致 zipbomb 错误。

ZipSecureFile.setMinInflateRatio(double ratio)

   FileInputStream file = new FileInputStream("/file/path/report.xlsx");
   ZipSecureFile.setMinInflateRatio(-1.0d);
   XSSFWorkbook wb = new XSSFWorkbook(file);

我想了解它是如何工作的?

我能找到的唯一来源是 https://poi.apache.org/apidocs/org/apache/poi/openxml4j/util/ZipSecureFile.html

但是,由于我对这个概念不熟悉,因此无法获得清晰的画面。

之间有什么区别
ZipSecureFile.setMinInflateRatio(-1.0d);

对比
ZipSecureFile.setMinInflateRatio(0.009);

对比
ZipSecureFile.setMinInflateRatio(0);

最佳答案

zip 炸弹检测的工作方式如下:

在解压缩时,它会检查 compressedBytes/uncompressedBytes 比率,如果该比率低于特定值 ( MinInflateRatio ),则检测到炸弹。

因此,如果比值 compressedBytes/uncompressedBytes0.01d,那么这意味着压缩文件比未压缩文件小 100 倍,没有信息丢失。换句话说,压缩文件仅以文件大小的 1% 存储相同的信息,这是未压缩文件所需要的。使用现实生活数据,这真的不太可能。

为了说明这是多么不可能,我们可以(以一种流行的科学方式)看看压缩是如何工作的:

让我们把字符串
"This is a test for compressing having long count of characters which always occurs the same sequence."
这需要 101 个字节。假设这个字符串在文件中出现了 100,000 次。然后解压缩它需要 10,100,000 字节。压缩算法会为该字符串提供一个 ID,并且只会存储该字符串一次,将其映射到该 ID,并且会存储 100,000 倍于该字符串在文件中出现的 ID。这将需要 101 个字节 + 1 个字节 (ID) + 100,000 个字节 (ID) = 100,102 个字节。例如,这将具有 compressedBytes/uncompressedBytes 的比率 0.009911089d

因此,如果我们将 MinInflateRatio 设置为低于 0.01d ,那么我们接受这种不太可能的数据压缩率。

我们还可以看到,如果 compressedBytes/uncompressedBytes 为 0,那么比率 0 只能是 compressedBytes。但这意味着没有要解压缩的字节。所以 MinInflateRatio0.0d 永远无法达到或低于。因此,使用 MinInflateRatio0.0d 将接受所有可能的比率。

当然,MinInflateRatio-1.0d 也永远无法达到或低于。因此,使用它也将接受所有可能的比率。

10-06 15:08