关于本文
本文是通过利用生成式 AI 的自动化生成流程创建的。我们查阅了 .NET 的 ZipArchive/ZipArchiveEntry 官方 API,将其整理为预检(preflight check),用于在实际解压 ZIP 之前检查是否包含跳出目标目录的路径或过大的解压体积。验证状态:📘 已确认微软官方规范,代码尚未实际运行验证
仅不解压而直接列出文件虽然很方便,但如果要推进到自动化处理,还需要再多做一步。
在解压前判定“是否可以将此 ZIP 解压到指定文件夹”这样可以更容易地阻止意外的路径和巨大的解压。
首先打开检查对象
$zipPath = 'C:Tempsample.zip' $extractRoot = 'C:Tempextract' $archive = [IO.Compression.ZipFile]::OpenRead($zipPath)
此处尚未解压。
1. 确认路径不会超出解压目标目录
如果 ZIP 条目名称中包含 .. 等内容,如果直接进行路径拼接,可能会指向意图解压目录之外的地方。
针对每个条目,计算“如果实际解压会变成哪个绝对路径”。
$rootFull = [IO.Path]::GetFullPath($extractRoot)
$rootPrefix = $rootFull.TrimEnd(
[IO.Path]::DirectorySeparatorChar,
[IO.Path]::AltDirectorySeparatorChar
) + [IO.Path]::DirectorySeparatorChar
foreach ($entry in $archive.Entries) {
$dest = [IO.Path]::GetFullPath(
[IO.Path]::Combine($rootFull, $entry.FullName)
)
if (-not $dest.StartsWith(
$rootPrefix,
[StringComparison]::OrdinalIgnoreCase
)) {
"BLOCK: $($entry.FullName)"
}
}
目的不仅是看字符串中是否有 ..,而是要确认规范化后的绝对路径是否位于解压根目录下。
2. 查看解压后的大小总和
压缩文件本身可能很小,但解压后可能会变得非常大。
$totalUncompressed = (
$archive.Entries |
Measure-Object -Property Length -Sum
).Sum
"Total uncompressed: $totalUncompressed bytes"
例如,如果在业务上规定限制在 100MB 以内,那么一旦超出该上限,就可以自动停止解压。
3. 对文件数量也设置上限
$count = $archive.Entries.Count
if ($count -gt 1000) {
"BLOCK: too many entries ($count)"
}
除了总大小之外,还可以检查其中是否包含数量极端庞大的文件。
4. 仅允许预期的扩展名
如果是 CSV 接收处理,还可以制定仅允许 CSV 和 README 的规则。
$allowed = '.csv', '.txt'
foreach ($entry in $archive.Entries) {
if ([string]::IsNullOrEmpty($entry.Name)) {
continue # ディレクトリエントリ
}
$ext = [IO.Path]::GetExtension($entry.Name).ToLowerInvariant()
if ($ext -notin $allowed) {
"REVIEW: unexpected extension $ext : $($entry.FullName)"
}
}
预检流程
flowchart TD
A[ZIPをOpenRead] --> B[パス正規化]
B --> C{展開先配下か}
C -- No --> X[BLOCK]
C -- Yes --> D[合計サイズ]
D --> E[ファイル数]
E --> F[拡張子/命名規則]
F --> G[人または後続処理が展開判断]
如何在工作中应用
自动接收合作伙伴的 ZIP
批处理前的输入验证
备份解压
CI/CD 制品检查
用户上传 ZIP 的预先检查
这样,我们就可以做到不再“因为是 ZIP 就直接解压”,而是先将解压条件规则化。
注意事项
仅凭这个示例并不能完全判定恶意 ZIP。
在实际运营中,还需要根据用途确认:
加密 ZIP 的处理
符号链接等特殊条目
单个文件大小上限
压缩率
文件名长度
恶意软件检查
解压目标的权限
等。
务必执行 Dispose
$archive.Dispose()
在实际代码中使用 try/finally,即使中途发生检查错误也能将其关闭,这样才安全。
总结
ZIP 可以在解压前检查危险路径
不仅依赖字符串的
..检查,还通过绝对路径规范化来进行判定可以对解压后的总大小和文件数量设置上限
确定允许的扩展名可使接收处理趋于安全
在预检通过后才做出解压判断
