MENU

Zip Slip脆弱性とは?アーカイブ展開処理のパストラバーサル・任意ファイル上書きの仕組みと対策ガイド

Zipファイルやtarボールを展開する処理は、システム管理ツール・Webアプリケーション・ビルドシステムで日常的に使われます。ところが、展開処理の実装に不備があると、攻撃者が細工したアーカイブを渡すだけで、展開先ディレクトリの外側にある任意の場所へファイルを書き込まれてしまいます。これが「Zip Slip脆弱性」です。

この脆弱性は2018年にSnyk Research Teamのレポートで広く知られるようになり、Java・Python・Go・Node.js・Rubyなど主要言語の複数ライブラリに影響が確認されました。今日でも自作の展開コードや古いライブラリを使っているシステムでは現役のリスクです。

この記事では、Zip Slipの仕組み・影響範囲・防御の具体的な手順を、開発者・情シス・システム管理者それぞれが実践できるレベルで解説します。

Zip Slip脆弱性とは?アーカイブ展開処理のパストラバーサル・任意ファイル上書きの仕組みと対策ガイド - 解説

目次

Zip Slip脆弱性とは?

Zip Slip(ジップ・スリップ)は、アーカイブファイル(ZIP・TAR・JAR・WARなど)を展開するときに発生するパストラバーサルの一種です。

通常、ZIPファイルにはエントリーごとに「展開先のファイル名」が記録されています。ここに ../../../etc/cron.d/backdoor のような親ディレクトリを遡る(ドットドット)パスを含めても、多くの展開ライブラリは素通りさせてしまいます。展開処理がパスを正規化せずにファイルを書き込むと、展開先ディレクトリの外にあるファイルが作成・上書きされてしまいます。

Webアプリケーションの「ファイルアップロード機能」でZIPを受け取りサーバー側で展開する実装は、特に影響を受けやすいパターンです。

Zip Slipが引き起こす主なリスク
・任意ファイルの上書き: /etc/passwd や /etc/cron.d/ などのシステムファイルに悪意あるファイルを書き込まれる
・Webシェルの設置: Webルート配下にPHPファイル等を設置され、リモートコード実行の踏み台にされる
・設定ファイルの改ざん: アプリケーション設定を書き換えて動作を変えられる
・権限昇格への発展: cron設定やsudoers等を書き換えることで、より高い権限の奪取につながる

攻撃の仕組みを理解する

攻撃者が作成する悪意あるZIPファイルには、次のようなエントリーが含まれています。

# 通常のZIPエントリー例 normal_file.txt # 悪意あるZIPエントリー例(パストラバーサル) ../../../etc/cron.d/evil ../../../../var/www/html/webshell.php

展開先を /tmp/extract/ に設定していても、ライブラリがパスをそのまま使って展開すると、実際の書き込み先は次のようになります。

# 意図した展開先 /tmp/extract/normal_file.txt # 実際の書き込み先(脆弱な実装の場合) /etc/cron.d/evil # cronジョブを追加できてしまう /var/www/html/webshell.php # WebシェルをWebルートに設置できてしまう

攻撃者からすると、特別なツールは不要です。標準ツールや簡単なスクリプトで細工したZIPを作成し、アップロード機能やAPIエンドポイントへ送信するだけです。

シンボリックリンクを使った亜種(TAR形式)
TAR形式では、シンボリックリンクのエントリーを悪用する亜種もあります。シンボリックリンク先を /etc/ などにしたエントリーを含めることで、後続のファイル書き込みを任意の場所へ誘導できます。ZIP形式よりも複雑ですが、原理は同じです。

影響を受けたライブラリと言語

Zip Slipは特定の製品の欠陥というよりも、パターン的な実装ミスです。2018年のSnyk調査では、以下をはじめとする多数のエコシステムで脆弱な実装が確認されました(現在は多くが修正済み)。

言語 影響を受けた代表的なライブラリ・ツール(修正前の状態) 現状
Java Apache Commons Compress、Plexus Archiver など複数 修正済み(バージョン確認要)
JavaScript(Node.js) adm-zip、extract-zip など 修正済み(バージョン確認要)
Python 自作の zipfile.extractall() 利用コード(標準ライブラリ自体の問題というより実装パターンの問題) 安全な使い方への移行で対応
Go archive/zip の一部の使い方 安全な使い方への移行で対応
Ruby rubyzip など 修正済み(バージョン確認要)

重要なのは、「ライブラリを更新すれば自動で安全になる」ケースばかりではないという点です。自作の展開コードや、ライブラリの安全でない使い方が残っているシステムでは、今も脆弱な状態のままです。

具体的な防御手順

1. 展開先パスの正規化とディレクトリチェック

最も確実な対策は、エントリーのパスを正規化したうえで、展開先ディレクトリ内に収まっているかを確認することです。以下は想定例として示す実装パターンです。

# Python での安全な展開パターン(想定例) import zipfile import os def safe_extract(zip_path, extract_dir): extract_dir = os.path.realpath(extract_dir) with zipfile.ZipFile(zip_path, 'r') as zf: for member in zf.namelist(): # エントリーパスを正規化し、展開先に収まるか確認 target = os.path.realpath(os.path.join(extract_dir, member)) if not target.startswith(extract_dir + os.sep): raise ValueError(f"不正なパスが検出されました: {member}") zf.extract(member, extract_dir)

ポイントは os.path.realpath() でシンボリックリンクを解決したうえで、プレフィックスチェックを行うことです。startswith() だけでは /tmp/extractextra/ のような類似パスに誤マッチするため、extract_dir + os.sep でセパレーターを末尾に付けます。

Java(Apache Commons Compress)での想定例も考え方は同じです。エントリー名を File.getCanonicalPath() で正規化し、展開先ディレクトリのパスを先頭に含むかを確認してから書き込みます。

2. サンドボックス環境での展開

Webアプリケーションでユーザーからのアーカイブを展開する場合は、展開処理をWebルートや重要なディレクトリから切り離した専用ディレクトリで実行し、展開後に内容を検証してから移動する設計が安全です。

・専用の一時ディレクトリを用意する(例: /var/tmp/sandbox/): 万一トラバーサルが起きてもWebルートには届かない
・展開後にファイルタイプ・拡張子を検証する: .php や .sh などの実行可能ファイルが混入していれば拒否する
・展開後の一時ディレクトリを速やかに削除する: 残留ファイルが悪用されるリスクを下げる

3. 依存ライブラリのバージョン管理と定期スキャン

使用しているアーカイブ処理ライブラリが最新版かどうかを確認します。SCA(ソフトウェアコンポジション解析)ツールを導入しておくと、依存ライブラリの既知脆弱性を継続的に検出できます。

・Java(Maven/Gradle): Dependabot や OWASP Dependency-Check を活用
・Node.js: npm audit / yarn audit で定期確認
・Python: pip-audit や safety コマンドで確認
・Go: govulncheck で依存パッケージの脆弱性を確認

中小企業・情シスでも今日からできること

開発者不在の情シス部門でも実施できる対策があります。

・社内システムの棚卸し: ZIPファイルや圧縮アーカイブを受け取って処理するシステムを洗い出す(ファイルアップロード機能を持つWebアプリ、ビルドシステム、自動展開スクリプトなど)
・開発部門へのヒアリング: アーカイブ展開に使用しているライブラリ名とバージョンを確認し、最新状態かをチェックする
・Webアプリのアップロード機能の確認: ZIPアップロードを受け付けるエンドポイントがある場合、展開処理の実装を開発者に確認してもらう
・権限の最小化: アーカイブを展開するプロセスの実行権限を必要最小限に絞る(Webサーバープロセスをrootで動かさないなど)
・WAFでのアーカイブ検査設定: ZIPファイルのアップロードを受け付ける箇所には、WAFのファイルスキャン機能を有効化する

Webアプリケーション全体のセキュリティ設計については、OWASP Top 10の基本知識と組み合わせて考えることを推奨します。ファイル処理全般のセキュリティ(パストラバーサルの基礎)についてはディレクトリトラバーサルの仕組みと対策もあわせてご参照ください。

よくある誤解と注意点

「ZIPの中身を一覧確認してから展開するから大丈夫」
一般的には、一覧表示(list)と実際の展開(extract)では使うコードパスが異なります。一覧に危険なパスが見えなくても、展開時に異なる動作をする実装上の差異がある場合もあります。最終的には展開処理そのものにパスチェックを入れることが必要です。

「ファイル名に .. を含むエントリーは文字列マッチングで拒否している」
URLエンコーディングや別の文字コードでドットドットを表現するバイパス手法が存在します。文字列マッチングだけの防御は迂回されやすく、パスの正規化後にチェックする方式が確実です。

「古い静的サイトには関係ない」
サーバー上で動くビルドスクリプト・デプロイスクリプト・CI/CDツールもZIPを扱うことがあります。Webアプリだけでなく、インフラ構築のコードでも同様の実装ミスが起きます。CI/CD環境でサードパーティのArtifact(成果物)を展開するパイプラインがある場合は特に注意が必要です。

「ZIPだけの問題だ」
TAR・JAR・WAR・CWARなど、エントリーパスを持つすべてのアーカイブ形式で同様の問題が起きます。またZIP形式内のZIPを再帰展開するケース(Zip Bomb対策と重なる点)でも注意が必要です。

Zip Slip脆弱性とは?アーカイブ展開処理のパストラバーサル・任意ファイル上書きの仕組みと対策ガイド - まとめ

本記事のまとめ

項目 内容
脆弱性の本質 アーカイブエントリーのパスを正規化せずに展開することで、展開先ディレクトリ外へのファイル書き込みが発生する
影響 任意ファイルの上書き・Webシェル設置・設定ファイル改ざんによるRCEへの発展
影響範囲 Java・Node.js・Python・Go・Rubyなど言語横断(ライブラリや実装による)
対策の核心 展開前にパスを正規化し(realpath)、展開先ディレクトリの範囲内かを確認する
運用上の対策 展開プロセスの権限最小化・依存ライブラリの定期スキャン・サンドボックス展開の設計
情シスができること アーカイブ展開処理を持つシステムの棚卸し・開発部門へのライブラリバージョン確認依頼

Zip Slipは「知っていれば防げる」シンプルな脆弱性です。しかしコードレビューで見落とされやすく、展開処理は「動いている」ので後回しにされがちです。自社のシステムにアーカイブ展開処理が存在するなら、一度コードとライブラリのバージョンを確認する機会を作ることをお勧めします。セキュリティはコードの品質から始まります。

PR

体系的に学ぶ 安全なWebアプリケーションの作り方 第2版(徳丸浩/SBクリエイティブ)

Zip Slipを含むWebアプリの脆弱性を体系的に理解したい方に。ファイル処理・パストラバーサル・インジェクション系の攻撃と対策を実装レベルで解説した定番書です。

関連記事をもっと読む

同じテーマの記事をまとめています。あわせて読みたい記事はこちらからご覧いただけます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次