Apache POIは、JavaでExcelファイルを読み書きするためのライブラリです。
この記事では、Apache POIでExcelファイルを読み込んだ際に、発生するZipボム検出エラーについて、原因と対処方法を説明します。
Zipボム検出エラーとは
Zipボム検出エラーは、Apache POIが圧縮ファイル内にセキュリティリスクを検出したときに発生します。 具体的には、圧縮ファイルのサイズが解凍後のデータサイズに比べて非常に小さい場合にこのエラーが発生します。
これは、解凍時に大量のメモリやリソースを消費することで、システムを攻撃するZipボムと呼ばれる圧縮ファイルが存在するためです。
エラーメッセージ
Apache POIが、高圧縮なファイルを読み込みZipボムの可能性があると検知すると、下記のようなエラーメッセージが出力され処理が中断します。
Zip bomb detected! The file would exceed the max. ratio of compressed file size to the size of the expanded data. This may indicate that the file is used to inflate memory usage and thus could pose a security risk. You can adjust this limit via ZipSecureFile.setMinInflateRatio() if you need to work with files which exceed this limit.
Zipボムと判断される理由
Zipボムは、非常に高い圧縮率で圧縮されたファイルで、解凍時に巨大なデータ量を生成し、メモリやリソースを消費することでシステムを攻撃するものですが、Apache POIはこのようなファイルを読み込むリスクを回避するために、デフォルトで圧縮されたファイルサイズと展開されたデータサイズの比率に制限を設けています。
具体的には、デフォルトで圧縮率が0.01 (1%)
つまり、元ファイルから1/100以下に圧縮されている場合にZipボムと判定されます。
圧縮率が高くなるエクセルファイルとは
悪意がないファイルであっても、 圧縮率が高いファイルであれば、Apache POIはリスク回避のためにエラーとして検知してしまいます。
一般的に、エクセルファイルの圧縮率を直接制御することは難しいですが、 ファイル内のデータ構造や内容に冗長なもの、もともとサイズが大きい画像ファイルなどが含まれていると圧縮率は高くなる傾向です。
また、プログラムによって生成したエクセルファイルの場合、CSVのように単純なテキストデータが並ぶ場合が多いので、 その場合も圧縮率が高くなる可能性はあります。
Zipボム検出の対処方法
最小インフレーション比率の変更
エラーメッセージにある通り、
デフォルトの検出閾値を調整するには、ZipSecureFile.setMinInflateRatio()
メソッドが使えます。
import org.apache.poi.openxml4j.util.ZipSecureFile;
public class YourClass {
public static void main(String[] args) {
// Set the minimum inflation ratio to a lower value (default is 0.01)
// Be cautious when lowering this value, as it may expose your application to security risks
ZipSecureFile.setMinInflateRatio(0.005);
// Your code for handling Excel files with Apache POI
...
}
}
この例では、圧縮率の制限をデフォルトの0.01から0.005に変更しています。 設定値はstatic領域に保持されているので、プログラム開始時に一度設定してしまうか、 検知してしまうファイルを読み込む前に、一時的に変更して読み取り、そのあと元設定に戻すような実装が好ましいです。
セキュリティリスクの検討
この制限を緩和することでセキュリティリスクは高まることに注意してください。
信頼できるファイルのみを扱う場合や、扱うファイルが非常に高い圧縮率を持つことが予想される場合にのみ、 制限緩和を検討してください。
まとめ
-
エクセルファイルは、XMLファイルなどをまとめたZipファイル。
Zipボムは、高圧縮なファイルを展開させてコンピュータリソースを枯渇させようとする悪意あるファイルのこと。 -
Apache POIは、一定の高圧縮ファイルを検知すると、リスク回避の為エラーとして検出する。
Zipボムかどうかは圧縮率による単純な判定のため、悪意がないファイルであっても一定の圧縮率であれば検知されてしまう。 -
ファイルの圧縮率は内容物の構造によるので、元サイズが大きいものや、冗長データが並ぶものだと圧縮率が高くなりがち。
また、プログラミングで生成したエクセルファイルは、構造がシンプルになる傾向があるので、誤検知される可能性はある。 -
Zipボムリスクとして検知する閾値は、デフォルトで0.01 (1%)に設定されている。
圧縮後のファイルサイズが1/100以下になっている場合にエラー検知される。 -
ZipSecureFile.setMinInflateRatio()
で、検知する閾値は変更できる。
信頼できるファイルであれば、閾値調整して扱う事ができる。