TOOLPIPO LAB ZIP · 13条件

ZIPを展開する前に、どこまで確認できる?

二重拡張子、不自然なパス、実行形式、高い圧縮率など13種類のZIPを自作し、展開せずに何が分かるか確認しました。

結論

ZIPを展開しなくても、ファイル名・パス・拡張子・圧縮前後のサイズから、確認の手がかりを得られます。13条件では、二重拡張子、実行形式候補、不自然なパス、入れ子ZIP、高圧縮率などを区別して表示できました。

一方、ファイル内容がマルウェアか、実際に開いて安全かまでは判断できません。確認項目が0件でも、安全性を保証する結果ではありません。

検証概要

使用Tool・方法
ZIP安全性チェッカーと同じ解析コードでZIPの名前・記録サイズを読取り
検証日・条件
・13種類のsynthetic fixture(自作の検証ファイル)
入力データ・処理
Tool入力の外部送信0。OSへの展開0。内側ZIPの再帰解析0。サイト共通の広告・アクセス解析通信は別です。
再現用ファイル
13条件とREADMEをダウンロード/測定結果JSON

今回作った13種類のZIP

通常例は短いtext、自作の1ページPDF、単色の8×8 PNGを含みます。他の条件では1つの特徴を選び、同じToolで読み直しました。実在人物・企業・実データ、実行可能コード、マクロ、マルウェアは使用していません。

setup.exe・invoice.pdf.exe・book.xlsmの実バイトは短い無害textです。ファイルの拡張子を分類する試験であり、EXE・Officeとしての内容を検査する試験ではありません。

生成はfflate 0.8.3。測定では公開ToolのanalyzeBytesを呼び、全entryのfilterがfalseになることを確認しました。読み取った件数・サイズ・倍率・finding(確認項目)を保存しています。

二重拡張子は「dotが2つある」だけではない

invoice.pdf.exeは、実行形式候補1件と二重拡張子候補1件でした。最後の.exeに加え、その直前の.pdfが文書形式を思わせる組合せを見ています。

backup.tar.gzは二重拡張子0件で、入れ子の圧縮ファイルという情報1件でした。.tar.gzは既知の複合拡張子として扱われます。単にdotの数を数える判定ではありません。

invoice.pdf.exeは二重拡張子と実行形式、backup.tar.gzは圧縮ファイルという比較
名前の分類の実測比較。実行内容や圧縮ファイルの中身を判定した図ではありません。

.exeや.xlsmという名前から、内容は断定できない

setup.exeは実行・script関連形式の候補1件になりました。.exeという名前だから要確認になるのであって、内容がマルウェアだと判定したわけではありません。今回の中身はtextです。

book.xlsmはマクロ対応Office形式の候補1件でした。.xlsmだからVBAが存在すると判定しているわけではありません。このToolはOffice内部のVBAを読みません。

../や絶対パスを展開前に確認できる

../toolpipo-test-outside.txtから、展開先の外側を参照する可能性があるパス1件が表示されました。同じentryの..は末尾dotの条件にも合い、環境依存名という情報1件も付きました。確認項目の合計2件は、2つのファイルという意味ではありません。

/tmp/toolpipo-test.txtとC:\temp\toolpipo-test.txtは絶対パス候補2件でした。ZIP内の名前が絶対パス形式であることを検出しただけです。OSに実際に展開した場合の保存先や上書きは検証していません。

ZIP内の../toolpipo-test-outside.txtの..は1つ上を指すパス要素
名前だけを見た概念図です。実ファイルを展開した結果ではありません。

OWASPは、アーカイブを展開する処理が内部パスを適切に検証しない場合に、意図しない場所へ書き込める問題を説明しています。結果は展開ソフト側の処理にも依存します。今回の内側ZIPを普通に展開して試す必要はありません。OWASP WSTG:Archive Directory Traversal

ファイル名だけでも分かる確認候補がある

Readme.txtとreadme.txtは、大文字・小文字による衝突の可能性1件でした。OSやfilesystemで扱いが異なるため、必ず上書きされるとは限りません。

見た目
reportfinal.txt
実際の文字列
report[U+200B]final.txt — reportとfinalの間に幅のない文字を1つ挿入

この名前は制御文字候補1件でした。U+200Bはzero-width space(幅のない空白)です。表示を分かりにくくする候補を挙げた結果であり、意図や内容の判定ではありません。

report.とfolder/name[末尾にspace]は環境依存名2件でした。21個のフォルダをつないだパスは、末尾のfile.txtも含めTool上で22階層あります。と表示されました。ここでの階層は空でないパス要素数で、フォルダだけの数ではありません。

入れ子ZIPの中までは確認していない

archives/inner.zipを含むZIPは、入れ子の圧縮ファイルという情報1件でした。存在と名前は分かりますが、inner.zipのentryや内容を再帰的に読み直してはいません。今回はinner.zip自体も短いreadme.txtから自作しています。

高い圧縮率は何を意味する?

文字Aを12,582,912 B(12 MiB)繰り返し、entryの圧縮後サイズは12,283 Bでした。entryの倍率は1,024.42倍で、高圧縮率候補1件となりました。

圧縮されたentry 12,283 bytesと展開後 12,582,912 bytesの実測比較
記録されたサイズの比較です。測定時に内容を展開したものではありません。

ZIP全体はヘッダーなどを含む12,405 Bです。Toolの要約に表示される展開倍率は、展開後合計÷ZIP全体のサイズで1,014.34倍。entryの倍率とは分母が違います。

現在のToolは、entryの展開後サイズが10×1024² B以上で、圧縮率1000倍以上なら候補を表示します。これはToolPipoの確認用の目安(heuristic)であり、規格上の危険ラインではありません。高圧縮率=ZIP bombとは断定しません。展開後サイズが大きい場合は、展開時に多くのメモリ・保存容量を必要とする可能性があります。

13条件の実測結果

「要確認」と「情報」を両方掲載しています。同じentryに複数の項目が付く場合があります。すべて生成したZIPを読み直した結果です。

確認できたことと、この測定では断定できないこと
条件Toolで確認できたこと断定できないこと
通常の小さなZIP
normal.zip
確認項目0件安全性やファイル内容の正しさ
実行形式の拡張子
executable-extension.zip
実行・script関連形式の候補 1件実行内容・マルウェアの有無
二重拡張子
double-extension.zip
実行・script関連形式の候補 1件/二重拡張子で実際の形式を見落とす可能性 1件PDFや実行ファイルとしての内容
通常の複合拡張子
compound-extension.zip
入れ子の圧縮ファイル 1件圧縮ファイルの中身
マクロ対応Office形式
macro-office.zip
マクロ対応Office形式 1件VBAやマクロの存在
入れ子ZIP
nested-archive.zip
入れ子の圧縮ファイル 1件inner.zip内のentryや内容
../を含むパス
path-traversal.zip
展開先の外側を参照する可能性があるパス 1件/環境依存のファイル名 1件OS上で実際に展開した挙動
絶対パス形式
absolute-path.zip
絶対パスの可能性 2件OSや展開ソフトごとの保存先
大文字・小文字だけの違い
case-collision.zip
環境によって名前が衝突する可能性 1件上書きや衝突の発生
見えにくいUnicode文字
invisible-character.zip
表示を分かりにくくする制御文字を含む可能性 1件内容や文字を入れた意図
末尾のdot・space
environment-name.zip
環境依存のファイル名 2件各OS・filesystemでの扱い
21フォルダの深いパス
deep-path.zip
非常に深いフォルダ階層 1件OSやソフトでのパス長制限
高い圧縮率
high-compression-ratio.zip
極端に高い圧縮率候補 1件ZIP bombかどうかや安全性
サイズ・件数・倍率の実測値を見る
ZIP全体を分母とした展開倍率
条件ZIP全体file / folder展開後合計展開倍率確認項目
通常の小さなZIP872 B3 / 2513 B0.59倍0件
実行形式の拡張子270 B2 / 054 B0.20倍1件
二重拡張子157 B1 / 027 B0.17倍2件
通常の複合拡張子239 B1 / 0114 B0.48倍1件
マクロ対応Office形式145 B1 / 027 B0.19倍1件
入れ子ZIP565 B2 / 2174 B0.31倍1件
../を含むパス183 B1 / 027 B0.15倍2件
絶対パス形式326 B2 / 054 B0.17倍2件
大文字・小文字だけの違い272 B2 / 054 B0.20倍1件
見えにくいUnicode文字163 B1 / 027 B0.17倍1件
末尾のdot・space270 B2 / 054 B0.20倍2件
21フォルダの深いパス311 B1 / 027 B0.09倍1件
高い圧縮率12,405 B1 / 012,582,912 B1,014.34倍1件

folderは末尾slashのある明示的なフォルダentryだけを数えます。パスにフォルダ名があるだけではfolder数は増えません。小さなZIPはヘッダーなどの比率が大きく、展開倍率が1倍未満になることもあります。

各ZIPのentry名と圧縮前後サイズを見る

通常の小さなZIP

  • documents/ — フォルダentry、圧縮後 2 B、展開後 0 B
  • documents/readme.txt — file、圧縮後 29 B、展開後 27 B
  • documents/report.pdf — file、圧縮後 224 B、展開後 414 B
  • images/ — フォルダentry、圧縮後 2 B、展開後 0 B
  • images/photo.png — file、圧縮後 67 B、展開後 72 B

実行形式の拡張子

  • setup.exe — file、圧縮後 29 B、展開後 27 B
  • readme.txt — file、圧縮後 29 B、展開後 27 B

二重拡張子

  • invoice.pdf.exe — file、圧縮後 29 B、展開後 27 B

通常の複合拡張子

  • backup.tar.gz — file、圧縮後 115 B、展開後 114 B

マクロ対応Office形式

  • book.xlsm — file、圧縮後 29 B、展開後 27 B

入れ子ZIP

  • documents/ — フォルダentry、圧縮後 2 B、展開後 0 B
  • documents/readme.txt — file、圧縮後 29 B、展開後 27 B
  • archives/ — フォルダentry、圧縮後 2 B、展開後 0 B
  • archives/inner.zip — file、圧縮後 92 B、展開後 147 B

../を含むパス

  • ../toolpipo-test-outside.txt — file、圧縮後 29 B、展開後 27 B

絶対パス形式

  • /tmp/toolpipo-test.txt — file、圧縮後 29 B、展開後 27 B
  • C:\temp\toolpipo-test.txt — file、圧縮後 29 B、展開後 27 B

大文字・小文字だけの違い

  • Readme.txt — file、圧縮後 29 B、展開後 27 B
  • readme.txt — file、圧縮後 29 B、展開後 27 B

見えにくいUnicode文字

  • report[U+200B]final.txt — file、圧縮後 29 B、展開後 27 B

末尾のdot・space

  • report. — file、圧縮後 29 B、展開後 27 B
  • folder/name — file、圧縮後 29 B、展開後 27 B

21フォルダの深いパス

  • d01/d02/d03/d04/d05/d06/d07/d08/d09/d10/d11/d12/d13/d14/d15/d16/d17/d18/d19/d20/d21/file.txt — file、圧縮後 29 B、展開後 27 B

高い圧縮率

  • repeated.txt — file、圧縮後 12,283 B、展開後 12,582,912 B

このToolで分からないこと

  • ファイル内容がマルウェアか、開く・実行する行為が安全か。
  • ファイルのCRCや中身の完全性、拡張子と実データ形式が一致するか。
  • マクロの有無、入れ子ZIPの中身、実際の展開先・上書き・名前の扱い。
  • 暗号化・非対応の圧縮方式・破損などで解析できないZIPの全内容。

展開後サイズはZIPに記録された値です。偽のmetadataや非対応形式もあり得るため、実際に展開した量の保証ではありません。Toolは250MBまで・10000 entriesまでのZIPを扱い、結果の表示にも上限があります。

自分のZIPを確認する

展開する前に、ファイル名・パス・サイズの確認候補を見られます。結果が0件でも、安全性の証明にはなりません。

自分のZIPを展開前に確認する

再現用ファイルとダウンロードの検証

検証用に意図的に不自然なentry名を含むZIPがあります。各inner ZIPを通常展開することを目的としたファイルではありません。ToolPipoのZIP checkerで確認してください。

outer ZIPにはREADME.txt・測定スナップショットresults.json・13個のZIPを相対名で収録しました。outerのentry名に../・絶対パスはなく、実行可能なバイナリも含みません。問題条件はinner ZIPの中だけです。

13条件の再現用ZIPを保存

ZIP全体のbytes
44,602 B
SHA-256
becd33eb67382c0c0a9ee571d1eafff160891a3e4f3f47fb3b31543fca298a9b

公開results.jsonにも最終ZIPのbytesとSHA-256を記録しています。ZIP自身の最終ハッシュをZIPの中に入れると循環参照になるため、同梱JSONはハッシュ確定前の測定スナップショットです。測定値は公開JSONと同じです。

検証条件・一次資料

生成用ソース:13条件のfixture生成・測定コード。固定日時のZIPを生成し、公開Toolと同じ解析コードで再測定しました。PKWARE資料はZIPの名前・サイズが記録される構造の確認に、OWASP資料はパスと展開処理の関係の確認に使用しました。

一次資料のZIP構造とToolPipo独自の1000倍という目安は別の事項です。今回、展開ソフト・OSごとの挙動や内容の安全性は検証していません。

関連する検証

自分のZIPを展開前に確認する