
2025/12/20 6:34
A Better Zip Bomb
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
## Summary 本稿は、単一の DEFLATE カーネル内で多数のファイルを重ね合わせることで 28 百万倍(例:10 MB → 281 TB)以上の圧縮率を実現する非再帰的「zip ボム」を提示しています。構築方法は次の二種類です。 * **Full overlap** – 圧縮率を最大化しますが、非常に寛容な ZIP パーサーでのみ動作します。 * **Quoted‑overlap** – 非圧縮ブロック内でローカルファイルヘッダーを引用し、若干低い比率でも広範囲の互換性を提供します。 著者は最適なカーネルサイズ(≈ zip サイズの ½;例:42 kB のボムは約 250 ファイルを含み、約 129 000 倍の圧縮)に関する式を示し、Zip64 拡張がヘッダーサイズを増加させる(46→58 バイト、30→50 バイト)ことから、最大 46 MB のボムでも約 4.5 PB に達できる(`zbxl.zip`)と論じています。ソースコードは https://www.bamsoftware.com/git/zipbomb.git で入手可能であり、図表は https://www.bamsoftware.com/git/zipbomb-paper.git にあります。 **互換性評価** – 本稿では、Info‑ZIP UnZip、Python zipfile、Go archive/zip、Node yauzl、Nailexamples/zip、Android libziparchive、sunzip など多くの ZIP ライブラリをテストし、DEFLATE、Zip64、bzip2、CRC‑32 処理、短いファイルサイズ、および最大ファイル数への対応状況を評価しています。実際のボムファイル(`zbsm.zip`、`zblg.zip`、`zbxl.zip`)を引用し、LibreOffice(4 GB の一時ファイル)、Mozilla のアドオンサーバー(110 秒抽出制限)、Windows Defender、Explorer、7‑zip、複数の AV エンジン、ブラウザ(Chrome/Safari 自動解凍)、圧縮ファイルシステム(ZFS)への影響を示しています。 **検知と対策** – Mark Adler の CVE‑2019‑13232 パッチは UnZip で重複ファイルを検出します。著者はパターンマッチングだけに頼らず、ZIP パーサーを厳格な時間・メモリ・ディスク制限付きのサンドボックスで実行することを推奨しています。AV 署名とブラウザの Safe Browsing の更新も、新しい変種が登場した際に期待されます。 **影響** – ユーザーはボムを開く際に高い CPU 使用率や大きな一時ファイルを経験する可能性があります。企業はライブラリをパッチし、セキュリティツールを更新し、サンドボックス化を徹底して悪用リスクを軽減すべきです。
本文
デイビッド・フィファイル
david@bamsoftware.com
2019‑07‑02
更新日:2019‑07‑03, 05, 06, 08, 18, 20, 22, 24; 2019‑08‑05, 19, 22; 2019‑10‑14, 18, 30, 11‑28;
2020‑07‑28; 2021‑01‑21, 02; 2021‑05‑03, 07‑29; 2023‑05‑18
概要
この記事では、zip コンテナ内でファイルを重複させることで非常に高い圧縮率を実現する 非再帰的 zip ボム の構築方法について説明します。
- 「非再帰的」とは、ネストされた zip を再帰的に展開するデコンプレッサーの仕組みに依存せず、1 回の解凍で完全に展開されることを意味します。
- 出力サイズは入力サイズと二次関数的に増加し、zip 形式の限界では圧縮率が 2800 万倍(10 MB → 281 TB)まで達します。
- Zip64 拡張機能を使えばさらに大きな展開も可能です。
- DEFLATE のみを使用しているため、ほとんどの zip パーサーとの互換性が保証されます。
ソースコード
git clone https://www.bamsoftware.com/git/zipbomb.git # 例示バイナリ: zipbomb-20210121.zip # 図表データとソース: git clone https://www.bamsoftware.com/git/zipbomb-paper.git
プレゼンテーションビデオ – @m1rko によるロシア語字幕、北岸冷若冰霜による中国語字幕。
42 ZIP バリアント
| バージョン | サイズ (bytes) |
|---|---|
| 古いバージョン | 42 374 |
| 新しいバージョン | 42 838 (パスワード保護済み) |
本記事では古いバージョンのみを対象に比較しています。
ダウンロード:42.zip。
圧縮率表
| タイプ | Zip サイズ | Unzip サイズ | Ratio | Unzip サイズ | 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 |
| 当社手法 | 42 374 | 5 461 307 620 | 129 k | 5 461 307 620 | 129 k |
| 当社手法 | 9 893 525 | 281 395 456 244 934 | 28 million | 281 395 456 244 934 | 28 million |
| Zip64 バリアント | 45 876 952 | 4 507 981 427 706 459 | 98 million | 4 507 981 427 706 459 | 98 million |
キー概念
- 重複ファイル – 単一の圧縮「カーネル」を多くのファイルエントリで再利用し、各ファイルごとのオーバヘッドを削減します。
- ローカルファイルヘッダーの引用 – ヘッダー文字列自体を非圧縮 DEFLATE ブロックとして埋め込み、各ファイルに独自ヘッダーを持たせつつカーネルを共有可能にします。
- 二次成長 – 追加されるファイルごとに 47 バイトの中央ディレクトリヘッダー(+5 バイトの引用ブロック)だけがコピーされるため、出力サイズはファイル数 (N) の二乗に比例します。
最適化モデル
定義
- (X):zip ファイルサイズ
- (N):ファイル数
- CDH=46 バイト、LFH=30 バイト、Q=5 バイト(引用ブロック)
- (C \approx 1032) (最大 DEFLATE 比率)
ヘッダーオーバーヘッド:
( H(N)=N(CDH+LFH)+(N-1)Q )
カーネルサイズ:( X-H(N) )
解凍後サイズ:
( S_X(N)=C,N,(X-H(N)) )
最大化すると
[ N_{\text{opt}}=\frac{X+Q}{2(CDH+LFH+Q)} ]
この点でヘッダーオーバーヘッドは約 (X/2) になり、解凍後サイズは (X) に対して二次的に増加します。
実際の例
| Zip サイズ | Unzip サイズ | Ratio |
|---|---|---|
| 42 kB (zbsm.zip) | 5.46 GB | 129 k |
| 10 MB (zblg.zip) | 281 TB | 28 million |
| 46 MB (Zip64, zbxl.zip) | 4.5 PB | – |
ツールで生成する例:
zipbomb --mode=quoted_overlap \ --num-files=250 \ --compressed-size=21179 > zbsm.zip zipbomb --mode=quoted_overlap \ --num-files=65534 \ --max-uncompressed-size=4292788525 > zblg.zip zipbomb --mode=quoted_overlap \ --num-files=190023 \ --compressed-size=22982788 \ --zip64 > zbxl.zip
CRC‑32 の計算
CRC‑32 は 33×33 の二進行列として表現でき、同じバイトを繰り返し適用する際に高速指数演算が可能です。
カーネルのチェックサムはゼロベクトルとマトリクス (M_{\text{kernel}}) を掛け合わせて得られます。
各ファイルの前でローカルヘッダー行列を先頭に追加し、累積的に更新します。
拡張機能
| 機能 | 効果 |
|---|---|
| Zip64 | ヘッダーサイズが 46→58 バイト、30→50 バイトへ拡大。実質的なサイズ制限を除去し、圧縮率はゆっくり増加するものの解凍後サイズは 281 TB を超える可能性があります。 |
| bzip2 | 最大比率 ≈ 1.4 百万。非圧縮ブロックがないため重複は不可で、非常に小さいファイルしか有効ではありません。 |
互換性表(代表的パーサー)
| 機能 | Info‑ZIP UnZip | Python zipfile | Go archive/zip | Yauzl (Node.js) | libzip |
|---|---|---|---|---|---|
| DEFLATE | ✓ | ✓ | ✓ | ✓ | ✓ |
| Zip64 | ✓ | ✓ | ✓ | ✖ | ✖ |
| bzip2 | ✓ | ✓ | ✖ | ✖ | ✖ |
| ファイル名不一致(警告) | ✔ | ✖ | ✓ | ✓ | ✖ |
| CRC‑32 不正(警告) | ✖ | ゼロ時に警告 | ✓ | ✖ | ✓ |
| ファイルサイズ不足 | ✓ | ✖ | ✖ | ✖ | ✖ |
| 最大 2^32−1 バイト | ✓ | ✓ | ✓ | ✖ | ✓ |
| 最大 2^16−1 ファイル数 | ✓ | ✓ | ✓ | ✖ | ✓ |
Quoted‑overlap ボムは中央ディレクトリを先に読むパーサーではすべて正しく解凍できます。ストリーミングパーサー(例:sunzip)は最初のファイルだけを抽出するかエラーになる場合があります。
実務上の注意
- 検知 – ファイル名の重複はローカルヘッダーと中央ディレクトリの名前を比較して検出できます。
- サンドボックス化 – 信頼できないアーカイブを解凍する際は、必ず時間・メモリ・ディスク使用量を制限してください。
- ブラウザ挙動 – Chrome や Safari はダウンロード後自動で unzip します。「ダウンロード後に安全なファイルを開く」設定を無効化することを検討してください。
- ファイルシステムへの影響 – 圧縮済みや重複排除されたファイルシステムでは実際の膨張量は小さくなる場合がありますが、依然として大きな拡張になります。
クレジット
Mark Adler、Blake Burkhart、Gynvael Coldwind、Russ Cox、Brandon Enright、Joran Dirk Greef、Marek Majkowski、Josh Wolfe、USENIX WOOT 2019 レビューアー、Caolán McNamara(LibreOffice)、@m1rko(ロシア語翻訳)、北岸冷若冰霜(中国語翻訳)に感謝します。
ソースコードと実験データは元論文リポジトリで入手可能です。