如何制作Zip炸弹?

148

这个问题关于zip炸弹自然而然地引导我去了维基百科页面。该文章提到了一个45.1 kb的zip文件的例子,解压后大小为1.3 exabytes。

首先用到的是哪些原理/技术呢?我并不想真的去做这件事,更感兴趣的是对所涉及概念的简化的“工作原理”解释。

文章提到了9层zip文件,因此这不是简单地将一堆零压缩在一起的情况。为什么是9层,每层为什么要有10个文件?


5
@Michael你的抱怨是无效的。虽然OP询问了它是如何工作的,但是文章中没有任何内容说明它是为了禁用防病毒软件而设计的。相反,文章的重点似乎是一种DOS风格的攻击,只是顺带提到了禁用防病毒软件。 - San Jacinto
2
重点是,OP指的是一个特定的文件,它由嵌套的存档组成,而不是一个巨大的压缩文件。 - Michael Borgwardt
1
我认为迈克尔是正确的,他解释了如何创建“PS”中描述的文件,而其他人没有。然而,“PS”是作为编辑添加的,因此那些答案在给出时可能并不明显错误。他们只是认为“这样的文件”意味着“任何解压到1.3 exabytes的文件”,而事实证明它的意图是“一个像我链接文章中描述的文件结构”。 - Steve Jessop
1
@onebyone 我完全同意。我只是认为在这种情况下不应该使用负评。 - San Jacinto
4
我猜这取决于你认为downvote的含义是“这不是回答问题的最佳答案”还是“你是个傻瓜,不值得活着”,或者介于两者之间。就我个人而言,我认为downvote意味着我应该重新阅读我的答案,看看是否有明显的错误需要修正。但是,如果我认为我的答案有所贡献,我现在非常乐意接受反对意见而不改变我的答案。而且我已经对整个投票过程变得相当不关心,因为很明显我永远无法赶上Jon Skeet;-) - Steve Jessop
显示剩余8条评论
15个回答

101

引用自维基百科页面:

一个Zip炸弹的例子是45.1.zip文件,它是45.1千字节的压缩数据,包含9层嵌套的ZIP文件,每组中有10个底层存档,每个底层存档都包含一个1.30千兆字节的文件,总共达到1.30艾字节的未压缩数据。

所以,您只需要一个装满零的单一1.3GB文件,将其压缩成一个ZIP文件,复制10份,打包到一个ZIP文件中,然后重复此过程9次。

这样,您将获得一个文件,当完全解压缩时,会产生一些荒谬的数据,而不需要从那么多的数据开始。

另外,嵌套的存档使得像病毒扫描器这样的程序更难聪明地拒绝解压缩“太大”的存档,因为在最后一层之前,总数据量并不大,只有到达该层级别时才能看到底层文件有多大,每个单独的文件不是“太大”,只有巨大的数量是有问题的。


4
一旦您压缩了底部的零文件并将其打包,生成的压缩文件下一层的可压缩性会大大降低。 - pufferfish
20
但是在每个层级上,你会有十个完全相同的文件 - 这再次可以很好地压缩。虽然ZIP不利用跨文件冗余,但包含十个单独压缩的相同文件的归档本身可能有很多重复内容,以供下一层级利用。 - Michael Borgwardt
12
重点不在于如何从尽可能小的文件中生成最大量的数据,而在于打败病毒扫描器对过大压缩包的防护。 - Michael Borgwardt
2
这不是维基百科上文章的重点,它似乎在推动一种DOS攻击方式。 - San Jacinto
2
但是文件不会递归地被提取...受害者应该继续提取子zip文件才能使其工作...有什么解决方法吗? - Manoj
显示剩余11条评论

60

创建一个1.3艾克斯字节大小的零文件。

右键单击>发送到压缩(zipped)文件夹。


26
你忘记加上讽刺的表情符号了。 - tvanfosson
1
由于文件大小的限制,大多数文件系统和压缩算法都无法实现这一点。然而,将文件嵌套在压缩存档中(如果压缩算法有总大小限制,则在存档中放置更多的嵌套存档)可以绕过这些限制。 - Blixt
145
应该生成一个1.3艾字节的1文件。它们比0更细小 :) - Quinn Wilson
38
@quinn - 这就是为什么压缩(最初较粗的)零更加有效。 - wefwfwefwe
2
这将会给你一个大于1GB的压缩文件,除非我弄错了。 - Chris S
显示剩余9条评论

47

使用以下命令可以在Linux下轻松完成此操作:

dd if=/dev/zero bs=1024 count=10000 | zip zipbomb.zip -

将count替换为您要压缩的KB数。上面的示例创建了一个10MiB的zip炸弹(实际上并不是很大,但它展示了整个过程)。

您不需要硬盘空间来存储所有未压缩的数据。


9
但是你需要计算能力来压缩未压缩的数据,这仍然与未压缩的数据大小成O(n)关系。 - tonfa
2
是的,所有其他答案都是这样。 - Thomi
7
Michael Borgwardt的答案在未压缩数据大小为O(log N)。 - Steve Jessop
1
大约,无论如何。每次重复“剥离存档头,将压缩文件条目复制10次,替换存档头,压缩”过程都会将zip嵌套级别增加1,所需时间与前一步骤的压缩数据大小成比例,未压缩数据大小乘以10,并且如果它增加了压缩数据的大小,肯定不是线性因素。 - Steve Jessop
4
只是作为一个测试,我使用 zip -9 压缩了 1.3GB 的零数据。结果是一个 1.3MB 的文件。我将其复制了 10 次(懒得去玩 zip 头文件,所以这个结果不能作为 Zip 炸弹,但能说明原理),得到了一个大小为 13MB 的文件,用 zip -9 压缩后变成了 34381 字节。因为 deflate 只支持某个最大尺寸的 token,所以复制步骤实际上会使文件更小。接下来的步骤分别得到 18453、19012、19312、19743、20120、20531、20870。 - Steve Jessop
显示剩余2条评论

10
以下是针对 Windows 操作系统的说明:
Security Focus 的概念验证(NSFW!)中,这是一个带有 16 个文件夹的 ZIP 文件,每个文件夹中又包含了 16 个文件夹,并且以此类推。具体如下所示(42 是 zip 文件名称):

\42\lib 0\book 0\chapter 0\doc 0\0.dll
...
\42\lib F\book F\chapter F\doc F\0.dll

我可能错误了,但它会产生 4^16 (4,294,967,296) 个目录。因为每个目录都需要 N 字节的分配空间,所以最终会变得非常大。最后的 dll 文件大小为 0 字节。
解压缩第一个目录 \42\lib 0\book 0\chapter 0\doc 0\0.dll 将导致分配出 4GB 的空间。

28
我曾以为是裸女在进行安全研究。 - James McMahon
3
这个zip文件不适合在工作场所打开。如果你打开它,会引起巨大的警报声和一只笼子会从天花板上掉下来罩住你的桌子。 - Chris S
4
如果每个病毒文件的击中都导致与人力资源部门的面试,那么要么你不需要病毒扫描器,要么你不需要人力资源部门。其中一个没有为业务做出贡献 ;- ) - Steve Jessop
2
可能也不安全,因为网络病毒扫描器可能会想要检查并提取它。 - Michael Stum
5
病毒扫描器应该将其标记为可疑文件(这可能会导致它被安全地阻止,或者可能会导致您因尝试安装病毒而被不安全地报告)。如果炸弹真的爆炸了,那么您的IT部门就学到了有价值的东西 - 他们需要一个更好的病毒扫描器。 - Steve Jessop
显示剩余2条评论

9

认真的回答:

压缩依赖于发现重复模式,因此zip文件将包含代表类似以下数据的内容

0x100000000000000000000000000000000000  
(Repeat this '0' ten trillion times)

非常短小的zip文件,但是当你扩展它时,它变得非常巨大。

1
这甚至可以更进一步压缩:0x1(0x35)(也就是说,第二个0重复了35次,因此它会扩展到你的注释中)。 - Michael

6
文章中提到了9层压缩文件,所以这不是简单地压缩一堆“0”的情况。为什么需要9层,每层为什么有10个文件?
首先,维基百科当前的文章中提到了5层,每层16个文件。不确定数据差异来自哪里,但这并不是很重要。真正的问题是,为什么首先要使用嵌套。
DEFLATE是zip文件唯一常见的支持压缩方法*,其最大压缩比为1032。这可以渐近地对任何重复的1-3字节序列进行实现。无论对zip文件做什么,只要它只使用DEFLATE,未解压缩的大小将至多是原始zip文件大小的1032倍。
因此,必须使用嵌套zip文件才能实现非常离谱的压缩比。如果您有两层压缩,则最大比率变为1032^2 = 1065024。对于3层,它是1099104768,以此类推。对于在42.zip中使用的5层,理论最大压缩比是1170572956434432。正如您所看到的,实际的42.zip远远没有达到那个水平。其中一部分是zip格式的开销,另一部分是他们根本不关心。
如果我猜的话,我会说42.zip是通过创建一个大的空文件,并反复压缩和复制它来形成的。他们没有试图推动格式的极限或最大化压缩或任何事情-他们只是武断地选择了每层16个副本。重点是要轻松创建一个大的有效载荷。
注:其他压缩格式,例如bzip2,提供非常非常高的最大压缩比。但是,大多数zip解析程序不接受它们。
P.S.可以创建一个zip文件,它将解压缩为自身的副本(称为quine)。您还可以制作一个将解压缩为多个自身副本的zip文件。因此,如果您无限递归地解压缩文件,则最大可能大小为无限大。唯一的限制是在每次迭代中,它最多可以增加1032。
P.P.S. 1032这个数字假定zip中的文件数据是不交叉的。 zip文件格式的一个奇怪之处是它有一个列出存档中文件和偏移量的中央目录。如果创建多个文件条目指向相同的数据,则即使没有嵌套,也可以实现更高的压缩比,但是这样的zip文件很可能会被解析器拒绝。

5

要在实际环境中创建一个(即不在你巨大的硬盘上创建1.3 exabyte文件),你可能需要学习二进制级别的文件格式,并编写一些将其转换为所需文件外观的东西,后期进行压缩。


4
创建zipbomb(或gzbomb)的好方法是了解你要针对的二进制格式。否则,即使你使用流文件(例如使用/dev/zero),你仍然会受到压缩流所需的计算能力的限制。
一个很好的gzip炸弹的例子:http://selenic.com/googolplex.gz57(在多次压缩后嵌入了一条消息,导致文件巨大)。
玩得开心,找到那个消息 :)

3
硅谷第三季第七集带我来到这里。生成zip炸弹的步骤如下:
  1. 创建一个大小为1GB的零文件(如果您认为它们很瘦,可以用1代替零)。
  2. 将此文件压缩为zip文件,例如1.zip
  3. 创建 n(比方说10)个此文件的副本,并将这10个文件添加到压缩档案中(例如2.zip)。
  4. 重复第3步 k 次。
  5. 您就会得到一个zip炸弹。
Python的实现请参考这个

3
不必使用嵌套文件,可以利用zip格式覆盖数据。

https://www.bamsoftware.com/hacks/zipbomb/

本文介绍了如何构建一个非递归的压缩炸弹,通过在 zip 容器内部重叠文件来实现高压缩比。 "非递归" 意味着它不依赖于解压缩程序递归地解压缩嵌套在 zip 文件中的 zip 文件:它在一轮解压缩后完全展开。输出大小随输入大小的平方增长,达到超过 2800 万的压缩比(10 MB → 281 TB)在 zip 格式的极限处。使用 64 位扩展可以实现更大的扩展。该构造仅使用最常见的压缩算法 DEFLATE,并且与大多数 zip 解析器兼容。
“使用zip格式的压缩炸弹必须应对一个事实,即DEFLATE是zip解析器最常支持的压缩算法,无法达到大于1032的压缩比。因此,zip炸弹通常依赖于递归解压缩,在zip文件中嵌套zip文件以每个层次获得额外的1032倍压缩比。但这个技巧只适用于递归解压缩的实现,而大多数实现不会这样做。最著名的zip炸弹42.zip,如果递归解压缩其六个层次,则扩展到惊人的4.5 PB,但在顶层仅为微不足道的0.6 MB。像Ellingsen和Cox的Zip quines一样,它们包含自己的副本,因此如果递归解压缩则会无限扩展,也同样完全安全。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接