Javaによるzipファイルの安全な解凍方法

以前、業務アプリ(Java)でzipファイルの操作が必要となったため、Javaにおけるzip圧縮解凍について調査しました。また、zip4jを使った圧縮・解凍についても説明しました。
ここでは、もう少し業務使用を考慮した、安全なzipファイル解凍について説明します。

安全なzipファイル解凍方法

  • ここで説明するサンプルは、Webアプリ上やバックエンドサーバ上で動作するアプリで使用すること前提とします。
  • zip圧縮を考えた場合、メモリ上のストリームまたはサーバ上のファイルやフォルダ等、サーバ上の信頼された領域のデータが対象になるので、それほどセキュリティを考慮する必要はありません。
  • zip解凍の場合、ユーザがアップロードしたようなzipファイルの場合は、いくつかの攻撃が考えられるため、解凍時にセキュリティ対策が必要です。(事前に検証済みなzipファイルやストリームであれば、考慮の対象外です。)
  • zip解凍時の想定される攻撃は次の通りです。
  • 一般的な正規化とは「一定のルールに沿って変形し、利用しやすくすること。」です。ここで言う正規化とは「相対パスを含まない絶対パス」です。絶対パスという表現だと、”/work/abc/../../etc/passwd”を許容する可能性があるため。パスを正規化する場合は、Fileクラスであれば#getCanonicalPath(), Pathクラスであれば#toAbsolutePath()と#normalize()を使用します。詳細はこちらを参考のこと。
  • zip4jライブラリを使用していますが、JDK標準ライブラリを使用する場合も同様です。

サンプルコード