用户上传的素材包只有 42KB,解压到一半磁盘告警,展开后是 4.5G 的重复内容。压缩比超过一万倍,单个文件声明的大小是 3.9G。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
unzip -l pkg.zip | tail -1 zipinfo -t pkg.zip
zip 的 deflate 对全零或高度重复的内容压缩比可以做到极高,解压时按声明的大小真实写盘。程序只校验了上传包体积,没限制解压后的总字节数和文件个数。这一点先确认清楚,后面就不用反复试。
碰到「解压炸弹」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。
具体做法是,解压前用 zipinfo 读各条目的 file_size 总和 超阈值直接拒绝;解压过程边写边计数 到上限立刻中断并删除目录;限制单文件大小和条目数量 拒绝绝对路径与 ../;用非 root 用户解压 目录放在独立配额的分区。
改完照着核一遍,构造的测试包在写入 200MB 时被脚本中断 /data 分区占用没有明显变化。
