建網(wǎng)站買空間seo高端培訓(xùn)
分享一個(gè)有趣的工具
ZBLG:非遞歸zipbomb炸彈,比例為28000000:1
存儲(chǔ)有價(jià),數(shù)據(jù)無(wú)價(jià),謹(jǐn)慎使用,請(qǐng)勿用于非法用途。
譯文發(fā)表記錄聲明
版本:V1
「?jìng)€(gè)站:北岸冷若冰霜」A better zip bomb
「看雪:北岸冷若冰霜」ZBLG:非遞歸zip炸彈,比例為28000000:1
「CSDN:北岸冷若冰霜」ZBLG:非遞歸zipbomb炸彈,比例為28000000:1
2021年7月29日更:感謝原作認(rèn)可,V2版本譯文,正在譯制中。。。
歡迎關(guān)注V2版本譯文
原創(chuàng)聲明
本版本譯文為機(jī)翻后優(yōu)化,譯自:https://www.bamsoftware.com/hacks/zipbomb/
作者:David Fifield
Email:david@bamsoftware.com一切版權(quán)原作者所有。
2019-07-02 updated 2019-07-03, 2019-07-05, 2019-07-06
summary:
本文介紹如何構(gòu)建一個(gè)非遞歸zip炸彈,(維基Zip_bomb)
“非遞歸”意味著它不依賴于解壓縮程序在zip文件中嵌套的遞歸解壓縮zip文件:它在單輪解壓縮后完全展開(kāi)。輸出大小在輸入大小的基礎(chǔ)上呈二次方增加,在zip格式的限制下,達(dá)到壓縮比2800萬(wàn) (10 MB → 281 TB)。使用64位擴(kuò)展甚至可以實(shí)現(xiàn)更大的擴(kuò)展。該構(gòu)造僅使用最常見(jiàn)的壓縮算法DEFLATE,并且與大多數(shù)zip解析器兼容。
zbsm.zip | 42 kB | → | 5.5 GB |
---|---|---|---|
zblg.zip | 10 MB | → | 281 TB |
zbxl.zip | 46 MB | → | 4.5 PB (Zip64, less compatible) |
源代碼:
git clone https://www.bamsoftware.com/git/zipbomb.git
或者:
wget https://www.bamsoftware.com/hacks/zipbomb/zipbomb-20190702.zip
數(shù)據(jù)和數(shù)據(jù)來(lái)源
git clone https://www.bamsoftware.com/git/zipbomb-paper.git
non-recursive zip bomb
non-recursive | recursive | ||||
---|---|---|---|---|---|
zipped size | unzipped size | ratio | unzipped size | ratio | |
Cox quine | 440 | 440 | 1.0 | ∞ | ∞ |
Ellingsen quine | 28?809 | 42?569 | 1.5 | ∞ | ∞ |
42.zip | *42?374 | 558?432 | 13.2 | 4?507?981?343?026?016 | 106 billion |
this technique | 42?374 | 5?461?307?620 | 129 thousand | 5?461?307?620 | 129 thousand |
this technique | 9?893?525 | 281?395?456?244?934 | 28 million | 281?395?456?244?934 | 28 million |
this technique (Zip64) | 45?876?952 | 4?507?981?427?706?459 | 98 million | 4?507?981?427?706?459 | 98 million |
-
關(guān)于42.zip
-
有兩個(gè)版本的42.zip,一個(gè)較老版本的42 374字節(jié),以及更新版本的42 838字節(jié)。不同之處在于新版本在解壓縮之前需要密碼,新版本結(jié)業(yè)密碼為:42。我們僅與舊版本進(jìn)行比較。如果需要,提供以下副本: 42.zip。
16 x 4294967295 = 68.719.476.720 (68GB) 16 x 68719476720 = 1.099.511.627.520 (1TB) 16 x 1099511627520 = 17.592.186.040.320 (17TB) 16 x 17592186040320 = 281.474.976.645.120 (281TB) 16 x 281474976645120 = 4.503.599.626.321.920 (4,5PB)
使用zip格式的壓縮炸彈必須應(yīng)對(duì)這樣一個(gè)事實(shí),即zip解析器最常支持的壓縮算法DEFLATE 無(wú)法達(dá)到大于1032的壓縮比。因此,zip炸彈通常依賴于遞歸解壓縮,在其中嵌套zip文件zip文件以獲得每層的額外因子1032。但是這個(gè)技巧只適用于遞歸解壓縮的實(shí)現(xiàn),而大多數(shù)都沒(méi)有。
最著名的zip炸彈, 42.zip,擴(kuò)展到了一個(gè)強(qiáng)大的4.5 PB 如果它的所有六個(gè)層都是遞歸解壓縮的,那就是微不足道的 0.6 MB在頂層。
Zip Quines,就像Ellingsen 和Cox一樣,它們包含自己的副本,因此如果遞歸解壓縮無(wú)限擴(kuò)展,同樣可以非常安全地解壓縮一次。
本文展示了如何構(gòu)造一個(gè)壓縮比超過(guò)DEFAATE限制1032的非遞歸zip炸彈。它通過(guò)重疊zip容器內(nèi)的文件來(lái)工作,以便在多個(gè)文件中引用高度壓縮數(shù)據(jù)的“內(nèi)核”,而不制作它的多個(gè)副本。zip炸彈的輸出尺寸在輸入尺寸上呈二次方增長(zhǎng); 即,隨著炸彈變大,壓縮比變得更好。構(gòu)造取決于zip和DEFLATE的特征 - 它不能直接移植到其他文件格式或壓縮算法。它與大多數(shù)zip解析器兼容,例外的是“流”解析器,它在一次傳遞中解析而無(wú)需先查詢zip文件的中心目錄。我們?cè)噲D平衡兩個(gè)相互沖突的目標(biāo):
- 最大化壓縮比。我們將壓縮率定義為zip文件中包含的所有文件大小的總和除以zip文件本身的大小。它不計(jì)算文件名或其他文件系統(tǒng)元數(shù)據(jù),只計(jì)算內(nèi)容。
- 兼容。Zip是一種棘手的格式,解析器不同,特別是在邊緣情況和可選功能周圍。避免利用僅適用于某些解析器的技巧。我們將評(píng)論某些方法來(lái)提高zip炸彈的效率,這會(huì)降低兼容性。
zip文件的結(jié)構(gòu)
zip文件由引用 文件的中央目錄組成。
正常格式
中央目錄位于zip文件的末尾。它是中央目錄標(biāo)頭的列表。每個(gè)中央目錄頭包含單個(gè)文件的元數(shù)據(jù),如文件名和CRC-32校驗(yàn)和,以及指向本地文件頭的向后指針。中央目錄標(biāo)題長(zhǎng)度為46個(gè)字節(jié),加上文件名的長(zhǎng)度。
文件由本地文件頭和 后面的壓縮文件數(shù)據(jù)組成。本地文件頭長(zhǎng)30個(gè)字節(jié),加上文件名的長(zhǎng)度。它包含來(lái)自中央目錄標(biāo)頭的元數(shù)據(jù)的冗余副本,以及隨后的文件數(shù)據(jù)的壓縮和未壓縮大小。Zip是容器格式,而不是壓縮算法。每個(gè)文件的數(shù)據(jù)都使用元數(shù)據(jù)中指定的算法進(jìn)行壓縮 - 通常是DEFLATE。
zip格式中的許多冗余和含糊不清允許各種惡作劇。zip炸彈只是刮擦表面。進(jìn)一步閱讀的鏈接:
- 一萬(wàn)個(gè)安全隱患:ZIP文件格式,由Gynvael Coldwind講話
- 模糊的zip解析允許隱藏來(lái)自linter和審閱者的附加文件,這是我在addons.mozilla.org中發(fā)現(xiàn)的漏洞
這種zip格式的描述省略了許多理解zip炸彈所不需要的細(xì)節(jié)。有關(guān)完整信息,請(qǐng)參閱 APPNOTE.TXT的4.3節(jié) 或Florian Buchholz 的PKZip文件結(jié)構(gòu),或參閱源代碼。
第一個(gè)見(jiàn)解:重疊文件
通過(guò)壓縮一長(zhǎng)串重復(fù)字節(jié),我們可以生成 高度壓縮數(shù)據(jù)的內(nèi)核。就其本身而言,內(nèi)核的壓縮率不能超過(guò)1032的DEFLATE限制,因此我們想要一種在許多文件中重用內(nèi)核的方法,而無(wú)需在每個(gè)文件中單獨(dú)復(fù)制它。我們可以通過(guò)重疊文件來(lái)實(shí)現(xiàn):使許多中央目錄標(biāo)頭指向單個(gè)文件,其數(shù)據(jù)是內(nèi)核。
讓我們看一個(gè)例子,看看這種結(jié)構(gòu)如何影響壓縮比。假設(shè)內(nèi)核是1000字節(jié) 并解壓縮到 1 MB。然后第一個(gè)MB 輸出“成本” 1078個(gè)字節(jié) 輸入:
- 31個(gè)字節(jié) 用于本地文件頭(包括1字節(jié)文件名)
- 47個(gè)字節(jié) 用于中央目錄頭(包括1字節(jié)文件名)
- 1000字節(jié) 對(duì)于內(nèi)核本身
但每一個(gè) 1 MB 僅在第一次成本之后的產(chǎn)出 47個(gè)字節(jié) - 我們不需要另一個(gè)本地文件頭或內(nèi)核的另一個(gè)副本,只需要一個(gè)額外的中央目錄頭。因此,雖然內(nèi)核的第一個(gè)引用具有1 000 000 /1078≈928的壓縮比,但每個(gè)附加引用將該比率拉近接近1 000 000 /47≈21277,更大的內(nèi)核提高了上限。
這個(gè)想法的問(wèn)題是缺乏兼容性。由于許多中央目錄標(biāo)頭指向單個(gè)本地文件頭,因此元數(shù)據(jù)(特別是文件名)無(wú)法與每個(gè)文件匹配。一些解析器對(duì)此猶豫不決。 Info-ZIP UnZip (標(biāo)準(zhǔn)的Unix unzip
程序)提取文件,但有警告:
unzip overlap.zip
inflating: A
B: mismatching "local" filename (A),continuing with "central" filename versioninflating: B
...
并且Python zipfile模塊 拋出異常:
$ python3 -m zipfile -e overlap.zip .
Traceback (most recent call last):
...
__main__.BadZipFile: File name in directory 'B' and header b'A' differ.
接下來(lái),我們將看到如何修改文件名一致性的構(gòu)造,同時(shí)仍保留重疊文件的大部分優(yōu)點(diǎn)。
第二個(gè)見(jiàn)解:引用本地文件頭
我們需要為每個(gè)文件分離本地文件頭,同時(shí)仍然重用單個(gè)內(nèi)核。簡(jiǎn)單地連接所有本地文件頭都不起作用,因?yàn)閦ip解析器將找到一個(gè)本地文件頭,它希望找到DEFLATE流的開(kāi)頭。但這個(gè)想法會(huì)有所改變。我們將使用DEFLATE(非壓縮塊)的一個(gè)功能來(lái)“引用”本地文件頭,使它們看起來(lái)像是在內(nèi)核中終止的同一個(gè)DEFLATE流的一部分。每個(gè)本地文件頭(第一個(gè)除外)將以兩種方式解釋:作為代碼(zip文件結(jié)構(gòu)的一部分)和數(shù)據(jù)(文件內(nèi)容的一部分)。
DEFLATE流是一系列 塊,其中每個(gè)塊可以是壓縮的或非壓縮的。壓縮塊是我們通常想到的; 例如,內(nèi)核是一個(gè)大的壓縮塊。但也有非壓縮塊,它以一個(gè)5字節(jié)的頭開(kāi)始, 長(zhǎng)度字段意味著“ 逐字輸出下一個(gè)n字節(jié)”。解壓縮非壓縮塊意味著僅剝離5字節(jié)頭。壓縮和非壓縮塊可以在DEFLATE流中自由混合。輸出是按順序解壓縮所有塊的結(jié)果的串聯(lián)。
“非壓縮”概念僅在DEFLATE層具有意義; 文件數(shù)據(jù)仍然在zip層計(jì)為“壓縮”,無(wú)論使用哪種塊.
最簡(jiǎn)單的方法是從內(nèi)到外理解這種引用重疊結(jié)構(gòu),從最后一個(gè)文件開(kāi)始,然后向后工作。首先插入內(nèi)核,它將形成每個(gè)文件的文件數(shù)據(jù)結(jié)尾。
預(yù)先 添加本地文件頭LFH N并添加指向它的中央目錄頭CDH N. 將LFH N和CDH N中的“壓縮大小”元數(shù)據(jù)字段設(shè)置為內(nèi)核的壓縮大小。現(xiàn)在預(yù)先添加一個(gè)5字節(jié)的非壓縮塊頭(圖中用綠色顯示),其長(zhǎng)度字段等于LFH N的大小。前置第二個(gè)本地文件頭LFH N -1 并添加一個(gè)中央目錄頭CDH N -1這指向它。將兩個(gè)新標(biāo)頭中的“壓縮大小”元數(shù)據(jù)字段設(shè)置為內(nèi)核的壓縮大小 加上非壓縮塊標(biāo)頭的大小(5個(gè)字節(jié)) 加上 LFH N的大小。
此時(shí),zip文件包含兩個(gè)名為“Y”和“Z”的文件。讓我們來(lái)看看解析它時(shí)zip解析器會(huì)看到什么。假設(shè)內(nèi)核的壓縮大小為1000字節(jié),LFH N的大小為31字節(jié)。我們從CDH N -1開(kāi)始, 然后按照指向LFH N -1的指針。第一個(gè)文件的文件名是“Y”,其文件數(shù)據(jù)的壓縮大小是1036個(gè)字節(jié)。將下一個(gè)1036字節(jié)解釋為DEFLATE流,我們首先遇到非壓縮塊的5字節(jié)頭,該塊表示要復(fù)制接下來(lái)的31個(gè)字節(jié)。我們寫下接下來(lái)的31個(gè)字節(jié),即LFH N.,我們解壓縮并附加到文件“Y”。繼續(xù)在DEFLATE流中,我們找到一個(gè)壓縮塊(內(nèi)核),我們將其解壓縮到文件“Y”?,F(xiàn)在我們已經(jīng)到達(dá)壓縮數(shù)據(jù)的末尾并且使用文件“Y”完成。繼續(xù)執(zhí)行下一個(gè)文件,我們按照從CDH N 到LFH N的指針,找到一個(gè)名為“Z”的文件,其壓縮大小為1000字節(jié)。將這1000個(gè)字節(jié)解釋為DEFLATE流,我們立即遇到壓縮塊(內(nèi)核再次)并將其解壓縮到文件“Z”。
現(xiàn)在我們已經(jīng)到了最終文件的末尾并完成了。輸出文件“Z”包含解壓縮的內(nèi)核; 輸出文件“Y”是相同的,但另外以LFH N的31個(gè)字節(jié)為前綴。
我們通過(guò)重復(fù)引用過(guò)程完成構(gòu)造,直到zip文件包含所需數(shù)量的文件。每個(gè)新文件都添加一個(gè)中心目錄頭,一個(gè)本地文件頭和一個(gè)非壓縮塊來(lái)引用緊接著的本地文件頭。壓縮文件數(shù)據(jù)通常是一系列DEFLATE非壓縮塊(引用的本地文件頭),后跟壓縮內(nèi)核。內(nèi)核中的每個(gè)字節(jié)對(duì)輸出大小貢獻(xiàn)大約1032? N,因?yàn)槊總€(gè)字節(jié)都是N的一部分文件。輸出文件的大小不同:zip文件中較早出現(xiàn)的文件大于稍后出現(xiàn)的文件,因?yàn)樗鼈儼鄮б?hào)的本地文件頭。輸出文件的內(nèi)容不是特別有意義,但沒(méi)有人說(shuō)它們必須有意義。
這種引用重疊結(jié)構(gòu)具有比前一部分的完全重疊結(jié)構(gòu)更好的兼容性,但兼容性是以壓縮比為代價(jià)的。在那里,每個(gè)添加的文件只花費(fèi)一個(gè)中央目錄標(biāo)題; 這里,它需要一個(gè)中心目錄頭,一個(gè)本地文件頭,以及引用頭的另外5個(gè)字節(jié)。
優(yōu)化
現(xiàn)在我們已經(jīng)有了基本zip炸彈結(jié)構(gòu),我們將努力使其盡可能高效。我們想回答兩個(gè)問(wèn)題:
- 對(duì)于給定的zip文件大小,最大壓縮比是多少?
- 考慮到zip格式的限制,最大壓縮比是多少?
內(nèi)核壓縮
盡可能密集地壓縮內(nèi)核是值得的,因?yàn)槊總€(gè)解壓縮的字節(jié)都被放大N倍。為此,我們使用一個(gè)名為bulk_deflate的自定義DEFLATE壓縮器,專門用于壓縮重復(fù)字節(jié)串。
當(dāng)給定無(wú)限重復(fù)字節(jié)流時(shí),所有體面的DEFLATE壓縮器將接近1032的壓縮比,但我們更關(guān)心特定的有限大小而不是漸近。bulk_deflate將更多數(shù)據(jù)壓縮到與通用壓縮器相同的空間:比zlib和Info-ZIP大約多26kB,比Zopfli大約多15kB,Zopfli是一種用于密度交換速度的壓縮器。
bulk_deflate高壓縮比的價(jià)格缺乏一般性。bulk_deflate只能壓縮單個(gè)重復(fù)字節(jié)的字符串,并且只有那些特定長(zhǎng)度,即517 + 258的? ?為整數(shù)? ≥0此外密集壓縮,bulk_deflate是快速的,這樣做基本恒定的工作而不管輸入的大小,一邊從實(shí)際寫出壓縮字符串的工作。
文件名
出于我們的目的,文件名大多是自重。雖然文件名由于是引用的本地文件頭的一部分而確實(shí)對(duì)輸出大小做出了貢獻(xiàn),但文件名中的一個(gè)字節(jié)的貢獻(xiàn)幾乎與內(nèi)核中的一個(gè)字節(jié)無(wú)關(guān)。我們希望文件名盡可能短,同時(shí)保持文件名不同,并且需要考慮兼容性。
在文件名上花費(fèi)的每個(gè)字節(jié)都是在內(nèi)核上花費(fèi)的2個(gè)字節(jié)。(2因?yàn)槊總€(gè)文件名在中央目錄頭和本地文件頭中出現(xiàn)兩次。)文件名字節(jié)平均只產(chǎn)生(N + 1)/ 4字節(jié)的輸出,而內(nèi)核中的一個(gè)字節(jié)計(jì)為1032? ?。
示例: 1 2 3
第一個(gè)兼容性考慮因素是字符編碼。zip格式規(guī)范規(guī)定文件名將被解釋為CP 437,或者如果設(shè)置了某個(gè)標(biāo)志位則為UTF-8(APPNOTE.TXT附錄D)。但這是跨zip解析器不兼容的一個(gè)主要問(wèn)題,它可能會(huì)將文件名解釋為某些固定或特定于語(yǔ)言環(huán)境的編碼。因此,為了兼容性,我們必須將自己限制在CP 437和UTF-8中具有相同編碼的字符; 即US-ASCII的95個(gè)可打印字符。
我們受文件系統(tǒng)命名限制的進(jìn)一步限制。某些文件系統(tǒng)不區(qū)分大小寫,因此“a”和“A”不計(jì)為不同的名稱。像FAT32這樣的常見(jiàn)文件系統(tǒng) 禁止某些字符, 如’*‘和’?'。
作為安全但不一定是最佳折衷方案,我們的zip炸彈將使用由36個(gè)字符的字母表組成的字符組成的文件名,不依賴于大小寫區(qū)別或使用特殊字符:
0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
文件名以明顯的方式生成,通過(guò)可能的字符循環(huán)每個(gè)位置并在溢出時(shí)添加位置:
“0”,“1”,“2”,…,“Z”,
“00”,“01”,“02”,…,“0Z”,
…,
“Z0”,“Z1”,“Z2”, …,“ZZ”,
“000”,“001”,“002”,…
有36個(gè)長(zhǎng)度為1的文件名,36 個(gè)長(zhǎng)度為2的文件名,依此類推。四個(gè)字節(jié)足以表示 1 727 604 不同的文件名。
鑒于zip文件中的N個(gè)文件名通常不是全長(zhǎng)相同,我們應(yīng)該按哪種方式排序,最短到最長(zhǎng)或最長(zhǎng)到最短?一點(diǎn)點(diǎn)反思表明最好把最長(zhǎng)的名字放在最后,因?yàn)檫@些名字引用最多。訂購(gòu)文件名最長(zhǎng)最后添加900 MB輸出到zblg.zip,與組織它們最長(zhǎng)的相比。不過(guò),這是一個(gè)次要的優(yōu)化900 MB 只包括 0.0003%總輸出大小。
內(nèi)核大小
引用重疊結(jié)構(gòu)允許我們放置壓縮的數(shù)據(jù)內(nèi)核,然后便宜地復(fù)制它多次。對(duì)于給定的zip文件大小 X,我們應(yīng)該投入多少空間來(lái)存儲(chǔ)內(nèi)核,以及制作副本的數(shù)量是多少?
為了找到最佳平衡,我們只需要優(yōu)化單個(gè)變量N,即zip文件中的文件數(shù)。N的每個(gè)值都需要一定量的開(kāi)銷用于中央目錄頭,本地文件頭,引用塊頭和文件名。所有剩余空間都可以由內(nèi)核占用。因?yàn)镹必須是整數(shù),并且在內(nèi)核大小降至零之前只能容納這么多文件,所以只需測(cè)試N的每個(gè)可能值 并選擇產(chǎn)生最多輸出的值。
將優(yōu)化程序應(yīng)用于X = 42 374,大小為42.zip,在N = 250 處找到最大值。這250個(gè)文件需要21 195 離開(kāi)的字節(jié)數(shù) 21 179內(nèi)核的字節(jié)數(shù)。該大小的內(nèi)核解壓縮到21 841 249 字節(jié)數(shù)(比率為 1031.3)。解壓縮內(nèi)核的250個(gè)副本加上來(lái)自引用的本地文件頭的一點(diǎn)點(diǎn)額外內(nèi)容,產(chǎn)生的總解壓縮輸出為5 461 307 620字節(jié),壓縮率為129萬(wàn)。
zbsm.zip 42 kB → 5.5 GB
zipbomb --mode = quoted_overlap --num-files = 250 --compressed-size = 21179> zbsm.zip
優(yōu)化在分配給內(nèi)核的空間和分配給文件頭的空間之間產(chǎn)生了幾乎均勻的分割。這不是巧合。讓我們看一下引用重疊結(jié)構(gòu)的簡(jiǎn)化模型。在簡(jiǎn)化模型中,我們忽略了文件名,以及由于引用本地文件頭而導(dǎo)致輸出文件大小略有增加。對(duì)簡(jiǎn)化模型的分析將表明,內(nèi)核和文件頭之間的最佳分割大致是均勻的,并且當(dāng)分配最佳時(shí),輸出大小以二次方式增長(zhǎng)。
定義一些常量和變量:
X | zip文件大小(固定) | |
---|---|---|
? | zip文件中的文件數(shù)(要優(yōu)化的變量) | |
CDH | = 46 | 中央目錄頭的大小(沒(méi)有文件名) |
LFH | = 30 | 本地文件頭的大小(沒(méi)有文件名) |
Q | = 5 | DEFLATE非壓縮塊頭的大小 |
C | ≈1032 | 內(nèi)核的壓縮比 |
設(shè)H(N)為N個(gè)文件所需的頭部開(kāi)銷量。請(qǐng)參考下圖以了解此公式的來(lái)源。
H ( N ) = N ? ( C D H + L F H ) + ( N ? 1 ) ? Q H(N) = N ·(CDH + LFH)+(N -1)·Q H(N)=N?(CDH+LFH)+(N?1)?Q
內(nèi)核剩余的空間是 X - H(N)??偨鈮嚎s大小 S X(N)是內(nèi)核的N個(gè)副本的大小,以比率C解壓縮。(在此簡(jiǎn)化模型中,我們忽略了來(lái)自引用的本地文件頭的次要附加擴(kuò)展。)
S X ( N ) = ( X ? H ( N )) C N . = ( X ? ( N ? ( C D H + L F H ) + ( N ? 1 ) ? Q )) C N . = ? ( C D H + L F H + Q ) C N 2 + ( X + Q ) C N . S X(N) =(X - H(N))C? N. =(X - (N ·(CDH + LFH)+(N -1)·Q))C? N. = - (CDH + LFH + Q)C? N 2 +(X + Q)C? N. SX(N)=(X?H(N))C?N.=(X?(N?(CDH+LFH)+(N?1)?Q))C?N.=?(CDH+LFH+Q)C?N2+(X+Q)C?N.
小號(hào)X(?)是一個(gè)多項(xiàng)式?,因此它的最大必須一個(gè)地方衍生物 小號(hào) ’ X(?)是零。取導(dǎo)數(shù)并找到零給我們 N OPT,最佳文件數(shù)。
小 號(hào) ′ X ( N ~ O P T ) = ? 2 ( C D H + L F H + Q ) C N O P T + ( X + Q ) C 0 = ? 2 ( C D H + L F H + Q ) C N O P T + ( X + Q ) C N O P T = ( X + Q ) / ( C D H + L F H + Q ) / 2 小號(hào) ' X(? OPT) = -2(CDH + LFH + Q)C? N OPT +(X + Q)C 0 = -2(CDH + LFH + Q)C? N OPT +(X + Q)C N OPT =(X + Q)/(CDH + LFH + Q)/ 2 小號(hào)′X(N~OPT)=?2(CDH+LFH+Q)C?NOPT+(X+Q)C0=?2(CDH+LFH+Q)C?NOPT+(X+Q)CNOPT=(X+Q)/(CDH+LFH+Q)/2
H(N OPT)為文件頭分配了最佳的空間量。它獨(dú)立于CDH,LFH和C,接近X?/ 2。
H ( N O P T ) = N O P T ? ( C D H + L F H ) + ( N O P T ? 1 ) ? Q = ( X ? Q ) / 2 H(N OPT) = N OPT ·(CDH + LFH)+(N OPT - 1)·Q =(X - Q)/ 2 H(NOPT)=NOPT?(CDH+LFH)+(NOPT?1)?Q=(X?Q)/2
S X(N OPT)是分配最佳時(shí)的總解壓縮大小。由此我們看到輸出大小在輸入大小上呈二次方增長(zhǎng)。
S X ( N O P T ) = ( X + Q ) 2 C / ( C D H + L F H + Q ) / 4 S X(N OPT) =(X + Q)^2 ?C /(CDH + LFH + Q)/ 4 SX(NOPT)=(X+Q)2?C/(CDH+LFH+Q)/4
它有點(diǎn)復(fù)雜,因?yàn)榫_的限制取決于實(shí)現(xiàn)。Python zipfile 忽略 文件數(shù)。Go archive / zip 允許 更大的文件計(jì)數(shù),只要它們?cè)诘?6位中相等即可。但是為了廣泛的兼容性,我們必須堅(jiān)持所述的限制。
隨著我們將zip文件擴(kuò)大,最終我們遇到了zip格式的限制。zip文件最多可包含2 個(gè) 16-1個(gè)文件,每個(gè)文件的未壓縮大小最多為2^32 - 1個(gè)字節(jié)。更糟糕的是, 一些實(shí)現(xiàn) 采用最大可能值作為64位擴(kuò)展的存在的指示符,因此我們的限制實(shí)際上是2^16 - 2和2^32 - 2. 碰巧我們遇到的第一個(gè)限制是關(guān)于未壓縮的文件大小。在zip文件大小為8 319 377字節(jié)時(shí),天真優(yōu)化將使我們的文件數(shù)為47 837,最大文件為2^32 + 311字節(jié)。
接受我們不能無(wú)限制地增加N和內(nèi)核的大小,我們希望找到可達(dá)到的最大壓縮比,同時(shí)保持在zip格式的限制內(nèi)。繼續(xù)進(jìn)行的方法是使內(nèi)核盡可能大,并擁有最大數(shù)量的文件。即使我們不能再維持內(nèi)核和文件頭之間的大致均勻分割,每個(gè)添加的文件確實(shí)會(huì)增加壓縮比 - 只是沒(méi)有像我們能夠繼續(xù)增長(zhǎng)內(nèi)核那樣快。實(shí)際上,當(dāng)我們添加文件時(shí),我們需要減小內(nèi)核的大小,以便為每個(gè)添加的文件獲得稍大的文件大小騰出空間。
該計(jì)劃產(chǎn)生一個(gè)zip文件,其中包含2^16 - 2個(gè)文件和一個(gè)解壓縮到2^32 - 2 178 825字節(jié)的內(nèi)核。文件在zip文件的開(kāi)頭變長(zhǎng) - 第一個(gè)和最大的文件解壓縮到2^32 - 56個(gè)字節(jié)。這與我們可以使用bulk_deflate-encoding的粗略輸出大小一樣接近,最后54個(gè)字節(jié)的成本將超過(guò)它們的價(jià)值。(zip文件整體壓縮率是2800萬(wàn),最后54個(gè)字節(jié)最多可以獲得54?1032?(2^16 - 2)…“3650萬(wàn)字節(jié),所以只有54個(gè)字節(jié)可以用1個(gè)字節(jié)編碼才有用 - 我不能用不到2個(gè)字節(jié)進(jìn)行編碼。)所以除非你能將54個(gè)字節(jié)編碼成1個(gè)字節(jié),否則只會(huì)降低壓縮率。)輸出大小這個(gè)zip炸彈,281 395 456 244 934字節(jié),是理論最大值(2^32 - 1)?(2^16 - 1)的99.97%。 壓縮比的任何重大改進(jìn)只能來(lái)自減小輸入大小,而不是增加輸出大小。
zblg.zip 10 MB → 281 TB
10 MB → 281 TB
zipbomb --mode = quoted_overlap --num-files = 65534 --max-uncompressed-size = 4292788525> zblg.zip
高效的CRC-32計(jì)算
中央目錄頭和本地文件頭中的元數(shù)據(jù)是 未壓縮文件數(shù)據(jù)的 CRC-32校驗(yàn)和。這帶來(lái)了一個(gè)問(wèn)題,因?yàn)橹苯佑?jì)算每個(gè)文件的CRC-32需要與總解壓縮大小成比例地工作,這在設(shè)計(jì)上是很大的。(畢竟這是一個(gè)zip炸彈。)我們寧愿做最壞情況下與zip成比例的工作尺寸。有兩個(gè)因素對(duì)我們有利:所有文件共享一個(gè)共同的后綴(內(nèi)核),而未壓縮的內(nèi)核是一串重復(fù)的字節(jié)。我們將CRC-32表示為矩陣產(chǎn)品 - 這將使我們不僅可以快速計(jì)算內(nèi)核的校驗(yàn)和,還可以跨文件重用計(jì)算。本節(jié)中描述的技術(shù)是crc32_combine
zlib中函數(shù)的輕微擴(kuò)展,Mark Adler 在此解釋 。
您可以將CRC-32建模為狀態(tài)機(jī),為每個(gè)輸入位更新32位狀態(tài)寄存器。0位和1位的基本更新操作是:
uint32 crc32_update_0(uint32 state) {// Shift out the least significant bit.bit b = state & 1;state = state >> 1;// If the shifted-out bit was 1, XOR with the CRC-32 constant.if (b == 1)state = state ^ 0xedb88320;return state;
}uint32 crc32_update_1(uint32 state) {// Do as for a 0 bit, then XOR with the CRC-32 constant.return crc32_update_0(state) ^ 0xedb88320;
}
如果你認(rèn)為狀態(tài)寄存器是一個(gè)32元素的二進(jìn)制向量,并使用XOR進(jìn)行加法和AND進(jìn)行乘法運(yùn)算,那么 crc32_update_0
就是 線性變換 ; 即,它可以表示為乘以32×32二進(jìn)制 變換矩陣。要了解原因,請(qǐng)注意將矩陣乘以向量只是將每列乘以向量的相應(yīng)元素后對(duì)矩陣的列求和。移位操作state >> 1
只是取狀態(tài)向量的每個(gè)位 i并將其乘以除了位i -1(從右到左對(duì)位進(jìn)行編號(hào))之外的任何位置的向量。有條件的最終XOR state ^ 0xedb88320
只在位時(shí)發(fā)生 b
是1可以代表第一次乘以 b
0xedb88320然后將其異或進(jìn)入狀態(tài)。
此外,crc32_update_1
只是 crc32_update_0
加(XOR)常數(shù)。這使得crc32_update_1
一個(gè) 仿射變換:矩陣乘法再平移(即,矢量相加)。如果我們將變換矩陣的尺寸放大到33×33并且將額外的元素附加到始終為1的狀態(tài)向量,我們可以在單個(gè)步驟中表示矩陣乘法和平移。(此表示稱為 齊次坐標(biāo)。)
矩陣M 0如下
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
矩陣M1如下
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
33×33變換矩陣M 0和M 1分別計(jì)算由0位和1位影響的CRC-32狀態(tài)變化。列向量存儲(chǔ)在底部的最高有效位:從下到上讀取第一列,您會(huì)看到CRC-32多項(xiàng)式常量edb88320 16 = 1 1 1
0 1 1
0 11
0 1 1 1
0 0 0 1
0 0 0 0 0 1 1
0 0 1
0 0 0 00 2。兩個(gè)矩陣僅在最終列中不同,最終列表示齊次坐標(biāo)中的平移向量。在M 0中,平移為零,并且在M 1中,它是edb88320 16,CRC-32多項(xiàng)式常數(shù)。正好在對(duì)角線上方的1表示換檔操作state >> 1
。
這兩種操作crc32_update_0
和crc32_update_1
可以由33×33的變換矩陣來(lái)表示。示出了矩陣M 0和M 1。矩陣表示的好處是矩陣組成。假設(shè)我們想要表示通過(guò)處理ASCII字符’a’而產(chǎn)生的狀態(tài)變化,其二進(jìn)制表示為01100001 2。我們可以在單個(gè)變換矩陣中表示這8位的累積CRC-32狀態(tài)變化:
M a = M 0 M 1 M 1 M 0 M 0 M 0 M 0 M 1 M a = M 0 M 1 M 1 M 0 M 0 M 0 M 0 M 1 Ma=M0M1M1M0M0M0M0M1
并且我們可以通過(guò)將M a的多個(gè)副本乘以一起矩陣求冪來(lái)表示一串重復(fù)’a’的狀態(tài)變化。我們可以使用square-and-multiply算法快速進(jìn)行矩陣求冪,這允許我們 僅在大約log 2 n步驟中計(jì)算M n。例如,表示9’a的字符串的狀態(tài)變化的矩陣是 ?
$$
(Ma)9 = M M M M M M M M Ma a a a a a a a a
=(M M M M)2 M.a a a a a
=((M M)2)2 M.a a a
=(((Ma)2)2)2 M.a
$$
square-and-multiply算法對(duì)于計(jì)算M kernel是非壓縮內(nèi)核的矩陣很有用,因?yàn)閮?nèi)核是一串重復(fù)的字節(jié)。要從矩陣生成CRC-32校驗(yàn)和值,請(qǐng)將矩陣乘以零向量。(齊次坐標(biāo)中的零向量,即:32 0后跟1。這里我們省略校正和預(yù)處理和后處理的次要復(fù)雜性。)為了計(jì)算每個(gè)文件的校驗(yàn)和,我們向后工作。首先初始化M := M 內(nèi)核。內(nèi)核的校驗(yàn)和也是最終文件的校驗(yàn)和,文件 N,因此將M乘以零向量并將得到的校驗(yàn)和存儲(chǔ)在CDH N和LFH中?。的文件的文件數(shù)據(jù) ? - 1相同的文件的文件數(shù)據(jù) ?,但隨著LFH添加的前綴 ?。這樣計(jì)算中號(hào)LFH ?,用于LFH狀態(tài)改變矩陣 ?,和更新中號(hào) := 中號(hào) 中號(hào)LFH ??,F(xiàn)在 M表示處理LFH N后跟內(nèi)核的累積狀態(tài)變化。 通過(guò)再次將 M乘以零向量來(lái)計(jì)算文件 N -1的校驗(yàn)和。繼續(xù)該過(guò)程,將狀態(tài)變化矩陣?yán)鄯e到 M中,直到所有文件都已處理完畢。
擴(kuò)展名:Zip64
早些時(shí)候,由于zip格式的限制,我們?cè)跀U(kuò)展方面遇到了障礙 - 無(wú)論zip文件多么巧妙地打包,都不可能產(chǎn)生超過(guò)281 TB的輸出。使用Zip64可以超越這些限制,Zip64是zip格式的擴(kuò)展,可將某些標(biāo)題字段的大小增加到64位。對(duì)Zip64的支持絕不是通用的,但它是更常用的擴(kuò)展之一。至于壓縮率,Zip64的作用是將中央目錄頭的大小從46字節(jié)增加到58字節(jié),并將本地目錄頭的大小從30字節(jié)增加到50字節(jié)。參考 公式 為了在簡(jiǎn)化模型中實(shí)現(xiàn)最佳擴(kuò)展,我們看到Zip64格式的zip炸彈仍然以二次方式增長(zhǎng),但由于分母較大而變得更慢 - 這 在Zip64線的垂直位置略低的下圖可見(jiàn) 。為了彌補(bǔ)兼容性的損失和增長(zhǎng)緩慢,我們刪除了所有實(shí)際的文件大小限制。
假設(shè)我們想要一個(gè)擴(kuò)展到的zip炸彈 4.5 PB,與.zip遞歸擴(kuò)展的大小相同。zip文件有多大?使用二進(jìn)制搜索,我們發(fā)現(xiàn)解壓縮大小超過(guò)解壓縮大小42.zip的最小zip文件的壓縮大小為 46 MB。
zbxl.zip 46 MB → 4.5 PB (Zip64,兼容性較差)
zipbomb --mode = quoted_overlap --num-files = 190023 --compressed-size = 22982788 --zip64> zbxl.zip
4.5 PB大致是Event Horizon Telescope捕獲的數(shù)據(jù)大小,用于制作黑洞,堆棧和硬盤堆棧的 第一張圖像。
使用Zip64,考慮最大壓縮率不再是實(shí)際有趣的,因?yàn)槲覀兛梢岳^續(xù)增加zip文件大小和壓縮率,直到壓縮的zip文件都非常大。然而,一個(gè)有趣的門檻是2 64 個(gè)字節(jié) (18 EB 要么 16 EiB) - 大多數(shù)文件系統(tǒng)都不適合這么多數(shù)據(jù)。二進(jìn)制搜索找到產(chǎn)生至少那么多輸出的最小zip炸彈:它包含1200萬(wàn) 文件并具有壓縮內(nèi)核 1.5 GB。zip文件的總大小是 2.9 GB 它解壓縮到 2 64 + 11 727 895 877字節(jié),壓縮比超過(guò) 62億。我沒(méi)有讓這個(gè)可下載,但你可以使用源代碼自己生成它。它包含的文件非常大,可以發(fā)現(xiàn) Info-ZIP UnZip 6.0中的錯(cuò)誤。
zipbomb --mode = quoted_overlap --num-files = 12056313 --compressed-size = 1482284040 --zip64> zbxxl.zip
擴(kuò)展名:bzip2
? bzip2以一個(gè)行程編碼步驟開(kāi)始,該步驟將重復(fù)字節(jié)串的長(zhǎng)度減少51倍。然后將數(shù)據(jù)分成 900 kB塊和每個(gè)塊單獨(dú)壓縮。根據(jù)經(jīng)驗(yàn),運(yùn)行長(zhǎng)度編碼后的一個(gè)塊可以壓縮到32個(gè)字節(jié)。900 000×51/32 = 1 434 375。
DEFLATE是zip格式中最常用的壓縮算法,但它只是眾多選項(xiàng)中的一種??赡艿诙N最常見(jiàn)的算法是bzip2,雖然不像DEFLATE那樣兼容,但它可能是第二種最常用的壓縮算法。根據(jù)經(jīng)驗(yàn),bzip2的最大壓縮比約為1.4百萬(wàn),這允許更密集的內(nèi)核包裝。忽略兼容性的損失,bzip2能否實(shí)現(xiàn)更高效的zip炸彈?
是 - 但僅適用于小文件。問(wèn)題是bzip2沒(méi)有像我們用來(lái)引用本地文件頭的 非壓縮的DEFLATE 塊那樣。因此不可能重疊文件并重用內(nèi)核 - 每個(gè)文件必須有自己的副本,因此整體壓縮率并不比任何單個(gè)文件的比率好。在圖中我們看到,無(wú)重疊bzip2僅對(duì)大約一兆字節(jié)以下的文件優(yōu)于引用的DEFLATE。
仍然有希望使用bzip2 - 下一節(jié)中討論的本地文件頭引用的替代方法。此外,如果您碰巧知道某個(gè)zip解析器支持bzip2 并容忍不匹配的文件名,那么您可以使用完全重疊構(gòu)造,而不需要引用。
zip尺寸適用于各種zip炸彈結(jié)構(gòu)。請(qǐng)注意日志日志比例。每個(gè)結(jié)構(gòu)都顯示有和沒(méi)有Zip64。無(wú)重疊構(gòu)造具有線性生長(zhǎng)速率,其在線的1:1斜率中可見(jiàn)。bzip2線的垂直偏移表明bzip2的壓縮比大約是DEFLATE的壓縮比的千倍。引用的DEFLATE結(jié)構(gòu)具有二次增長(zhǎng)率,如線的2:1斜率所證明的。Zip64變體的效率略低,但允許輸出超過(guò)281 TB。在達(dá)到最大文件大小時(shí),字段引用的bzip2從二次到線性轉(zhuǎn)換的行(2^32 - 2個(gè)字節(jié)),或外場(chǎng)引用允許的最大文件數(shù)。
擴(kuò)展:額外字段引用
到目前為止,我們使用DEFLATE的一個(gè)功能來(lái)引用本地文件頭,我們剛剛看到同樣的技巧不適用于bzip2。有一種替代的引用方式,稍微有點(diǎn)限制,只使用zip格式的功能,而不依賴于壓縮算法。
在本地文件頭結(jié)構(gòu)的末尾有一個(gè)可變長(zhǎng)度的 *額外字段,*其目的是存儲(chǔ)不適合標(biāo)題的普通字段的信息(APPNOTE.TXT第4.3.7節(jié)))。額外信息可以包括例如高分辨率時(shí)間戳或Unix uid / gid; Zip64信息存儲(chǔ)在額外字段中。額外字段表示為長(zhǎng)度值結(jié)構(gòu); 如果我們?cè)诓惶砑又档那闆r下增加長(zhǎng)度字段,那么額外的字段將增長(zhǎng)到包含在zip文件中的任何內(nèi)容 - 即下一個(gè)本地文件頭。使用此技術(shù),每個(gè)本地文件頭可以通過(guò)將它們包含在其自己的額外字段中來(lái)“引用”以下本地文件頭。與DEFLATE非壓縮塊引用相比,額外字段引用的好處有三個(gè):
- 額外字段引用只需要4個(gè)字節(jié)的開(kāi)銷,而不是5個(gè)字節(jié),從而為內(nèi)核留出更多空間。
- 額外字段引用不會(huì)增加文件的大小,這會(huì)在zip格式的限制下運(yùn)行時(shí)為更大的內(nèi)核留下更多的空間。
- 額外字段引用提供了一種將引用與bzip2結(jié)合的方法。
盡管有這些好處,但外場(chǎng)報(bào)價(jià)不如DEFLATE報(bào)價(jià)靈活。它不像DEFLATE引用那樣鏈:每個(gè)本地文件頭不僅必須包含緊接的下一個(gè)頭,而且還必須包含所有后面的頭。隨著接近zip文件的開(kāi)頭,額外字段的長(zhǎng)度會(huì)增加。因?yàn)轭~外字段的最大長(zhǎng)度為 2^16 - 1個(gè)字節(jié),假設(shè)文件名按照描述分配,則最多只能引用1808個(gè)本地文件頭(或帶有Zip64的1170)。(在DEFLATE的情況下,您可以對(duì)第一個(gè)(最短的)本地文件頭使用額外字段引用,然后切換到剩余的DEFLATE引用。)另一個(gè)問(wèn)題是,為了符合內(nèi)部數(shù)據(jù)結(jié)構(gòu)在額外字段中,必須選擇16位類型標(biāo)記(APPNOTE.TXT第4.5.2節(jié))。在引用的數(shù)據(jù)之前。我們想要選擇一個(gè)類型標(biāo)記,它將導(dǎo)致解析器忽略引用的數(shù)據(jù),而不是試圖將其解釋為有意義的元數(shù)據(jù)。Zip解析器應(yīng)該忽略未知類型標(biāo)記,因此我們可以隨機(jī)選擇類型標(biāo)記,但是存在將來(lái)可能分配標(biāo)記的風(fēng)險(xiǎn),從而破壞了構(gòu)造的兼容性。
上圖說(shuō)明了使用帶有和不帶Zip64的bzip2的額外字段引用的可能性。兩條線都有一個(gè)膝蓋,在該拐點(diǎn)處,生長(zhǎng)從二次轉(zhuǎn)變?yōu)榫€性。在非Zip64情況下,膝蓋出現(xiàn)在最大未壓縮文件大小的位置(2……32 - 2個(gè)字節(jié)) 到達(dá)了; 在此之后,人們只能增加文件數(shù)量,而不能增加文件的大小。當(dāng)文件數(shù)達(dá)到1809時(shí),當(dāng)我們?cè)陬~外字段中用盡房間引用額外標(biāo)題時(shí),該行完全結(jié)束。在Zip64的情況下,膝蓋發(fā)生在1171個(gè)文件,之后文件的大小可以增加,但不是它們的數(shù)量。外場(chǎng)引用也有助于DEFLATE,但差別很小,以至于在視覺(jué)上難以察覺(jué),因此從圖中省略了。它將 zbsm.zip 的壓縮比提高了 1.2%; zblg.zip 0.019%;和zbxl.zip 0.0025%。
討論
在相關(guān)工作中, Pl?tz等人。 使用重疊文件創(chuàng)建近自我復(fù)制的zip文件。Gynvael Coldwind 之前曾建議(幻燈片47)重疊文件。
為了兼容性,我們?cè)O(shè)計(jì)了引用重疊zip炸彈結(jié)構(gòu),考慮了許多實(shí)現(xiàn)差異,其中一些顯示在下表中。由此產(chǎn)生的結(jié)構(gòu)與通常從后到前工作的zip解析器兼容,首先咨詢中心目錄并將其用作文件索引。其中包括Nail中包含的示例zip解析器,這是從正式語(yǔ)法自動(dòng)生成的。但是,這種結(jié)構(gòu)與“流”解析器不兼容,這些解析器是在沒(méi)有首先讀取中心目錄的情況下從頭到尾解析zip文件的解析器。就其性質(zhì)而言,流式解析器不允許任何類型的文件重疊。最有可能的結(jié)果是他們只會(huì)提取第一個(gè)文件。它們甚至可能引發(fā)錯(cuò)誤,就像sunzip一樣,它解析了最后的中心目錄并檢查它與已經(jīng)看到的本地文件頭的一致性。
如果您需要提取的文件以除本地文件頭的字節(jié)之外的某個(gè)前綴開(kāi)頭,則可以在引用下一個(gè)頭的非壓縮塊之前插入DEFLATE塊。并非zip文件中的每個(gè)文件都必須參與炸彈構(gòu)造:如果需要,您還可以包含普通文件以符合某種特殊格式。(源代碼有一個(gè)--template
選項(xiàng)來(lái)促進(jìn)這個(gè)用例。)許多文件格式使用zip作為容器; 示例是Java JAR,Android APK和LibreOffice文檔。
PDF 在許多方面類似于zip。它在文件末尾有一個(gè)交叉引用表,指向文件中較早的對(duì)象,它支持通過(guò)FlateDecode過(guò)濾器對(duì)對(duì)象進(jìn)行DEFLATE壓縮。我沒(méi)有嘗試過(guò),但也許可以使用引用重疊的想法制作PDF壓縮炸彈。甚至可能沒(méi)有必要努力工作:binaryhax0r在 博客文章中 建議人們可以簡(jiǎn)單地在單個(gè)對(duì)象上指定多層FlateDecode,這使得壓縮炸彈變得容易。
檢測(cè)我們?cè)诒疚闹虚_(kāi)發(fā)的特定類型的zip炸彈很容易:只需查找重疊文件。Mark Adler已經(jīng) 為Info-ZIP UnZip 編寫了一個(gè)補(bǔ)丁。但是,一般來(lái)說(shuō),拒絕重疊文件并不能防止所有類別的zip炸彈。除非您準(zhǔn)確了解將用于解析它的解析器的內(nèi)部,否則很難預(yù)先確定zip文件是否是炸彈。 通常,查看標(biāo)題并匯總所有文件的“未壓縮大小”字段不起作用,因?yàn)闃?biāo)題中存儲(chǔ)的值可能與實(shí)際的未壓縮大小不一致。(請(qǐng)參閱兼容性表中的“允許太短的文件大小”行。)對(duì)zip炸彈的強(qiáng)大保護(hù)涉及在操作時(shí)對(duì)zip解析器設(shè)置時(shí)間,內(nèi)存和磁盤空間限制。處理zip解析,作為對(duì)不受信任數(shù)據(jù)的任何復(fù)雜操作,請(qǐng)謹(jǐn)慎操作。
Info-ZIP UnZip 6.0 | Python 3.7 zipfile | 去1.12 檔案/郵編 | yauzl 2.10.0 (Node.js) | 指甲 示例/zip | Android 9.0.0 r1 libziparchive | sunzip 0.4 (流媒體) | |
---|---|---|---|---|---|---|---|
DEFLATE | ? | ? | ? | ? | ? | ? | ? |
ZIP64 | ? | ? | ? | ? | ? | ? | ? |
bzip2的 | ? | ? | ? | ? | ? | ? | ? |
允許不匹配的文件名 | 警告 | ? | ? | ? | ? | ? | ? |
允許錯(cuò)誤的CRC-32 | 警告 | ? | 如果為零 | ? | ? | ? | ? |
允許太短的文件大小 | ? | ? | ? | ? | ? | ? | ? |
允許文件大小為2 32 - 1 | ? | ? | ? | ? | ? | ? | ? |
允許文件數(shù)為2 16 - 1 | ? | ? | ? | ? | ? | ? | ? |
unzips overlap.zip | 警告 | ? | ? | ? | ? | ? | ? |
解壓縮zbsm.zip和zblg.zip | ? | ? | ? | ? | ? | ? | ? |
解壓縮zbxl.zip | ? | ? | ? | ? | ? | ? | ? |
所選zip解析器與各種zip功能,邊框和zip炸彈結(jié)構(gòu)的兼容性。背景顏色表示從限制較少到限制較多的比例。為了獲得最佳兼容性,請(qǐng)使用不帶Zip64的DEFLATE壓縮,匹配中央目錄頭和本地文件頭中的名稱,計(jì)算正確的CRC,并避免32位和16位字段的最大值。
致謝
我感謝 Mark Adler, Russ Cox, Brandon Enright, Marek Majkowski, Josh Wolfe以及USENIX WOOT 2019評(píng)論員對(duì)本文草稿的評(píng)論。CaolánMcNamara評(píng)估了LibreOffice中zip炸彈的安全影響。
本文的一個(gè)版本將出現(xiàn)在 USENIX WOOT 2019 研討會(huì)上。該論文的源代碼可用。 準(zhǔn)備提交的工件是zipbomb-woot19.zip
你有沒(méi)有找到一個(gè)扼殺這些zip炸彈的系統(tǒng)?他們是否幫助您展示漏洞或贏得錯(cuò)誤賞金? 讓我知道,我會(huì)在這里提一下。
-
LibreOffice 6.1.5.2
重命名為zblg.odt或zblg.docx的zblg.zip將導(dǎo)致LibreOffice在嘗試確定文件格式時(shí)創(chuàng)建和刪除大量~4 GB的臨時(shí)文件。它最終完成,它會(huì)刪除臨時(shí)文件,因此它只是一個(gè)不填滿磁盤的臨時(shí)DoS。CaolánMcNamara回復(fù)了我的錯(cuò)誤報(bào)告。
-
Mozilla addons-server 2019.06.06
我嘗試了針對(duì)本地安裝的addons-server的zip炸彈,這是addons.mozilla.org背后的軟件的一部分。該系統(tǒng)處理它擺好,強(qiáng)加時(shí)間限制 的110秒提取。zip炸彈的擴(kuò)展速度與磁盤允許達(dá)到時(shí)間限制一樣快,但在此之后,進(jìn)程被終止并且解壓縮的文件最終會(huì)自動(dòng)清除。
-
UnZip 6.0
Mark Adler 為UnZip 編寫 了一個(gè)補(bǔ)丁來(lái)檢測(cè)這類zip炸彈。2019年7月5日:我注意到CVE-2019-13232 已分配給UnZip。就個(gè)人而言,我認(rèn)為UnZip(或任何zip解析器)處理此處討論的zip炸彈的能力必然代表一個(gè)安全漏洞,甚至是一個(gè)bug。這是一種自然的實(shí)現(xiàn)方式,并且不會(huì)以任何方式違反規(guī)范。本文中討論的類型只是一種類型的zip炸彈,并且有許多方法可以解決zip解析可能出錯(cuò)的非炸彈。 如上所述,如果要抵御資源耗盡攻擊,你應(yīng)該不嘗試枚舉,檢測(cè)和阻止每個(gè)已知的攻擊; 相反,你應(yīng)該對(duì)時(shí)間和其他資源施加外部限制,這樣無(wú)論面對(duì)什么樣的攻擊,解析器都不會(huì)行為過(guò)多。嘗試檢測(cè)和拒絕某些結(jié)構(gòu)作為首次通過(guò)優(yōu)化沒(méi)有任何問(wèn)題,但你不能就此止步。如果您最終沒(méi)有隔離并限制對(duì)不受信任數(shù)據(jù)的操作,則您的系統(tǒng)可能仍然容易受到攻擊。考慮用HTML中的跨站點(diǎn)腳本進(jìn)行類比:正確的防御不是嘗試過(guò)濾掉可能被解釋為代碼的字節(jié),而是要正確地逃避一切。
-
防病毒引擎
Twitter用戶@TVqQAAMAAAAEAAA 報(bào)告稱 “我的測(cè)試機(jī)器上的McAfee AV爆炸了”。我沒(méi)有獨(dú)立確認(rèn),也沒(méi)有版本號(hào)等細(xì)節(jié)。Tavis Ormandy 指出 ,VirusTotal for zblg.zip 中有很多“Timeout”結(jié)果 (截圖)2019年7月6日)。AhnLab-V3,ClamAV,DrWeb,Endgame,F-Secure,GData,K7AntiVirus,K7GW,MaxSecure,McAfee,McAfee-GW-Edition,Panda,Qihoo-360,Sophos ML,VBA32。 zbsm.zip的結(jié)果 (截圖2019年7月6日) 是相似的,但有一組不同的超時(shí)發(fā)動(dòng)機(jī):Baido,噶,ClamAV的,CMC,DrWeb,殘局,ESET,NOD32,F-Secure公司,的GData,金山,邁克菲-GW-版,納米防病毒時(shí),Acronis 。有趣的是,zbxl.zip的結(jié)果沒(méi)有超時(shí) ; (截圖2019年7月6日) 也許這意味著一些殺毒軟件不支持Zip64?一些引擎將文件檢測(cè)為某種壓縮炸彈。有趣的是,當(dāng)進(jìn)行小的修改時(shí),它們是否仍然這樣做,例如更改文件名或?yàn)槊總€(gè)文件添加ASCII前綴。