最近,Git 中一个可实现 RCE(远程代码执行)攻击的关键漏洞被披露,影响到多个版本的 Git 和 Microsoft Visual Studio 2017。利用该漏洞,攻击者可以使用子模块操纵 Git 存储库,利用 Git 中的一个漏洞,允许将文件写入子模块工作树之外的.git/目录。 该漏洞可在版本库克隆操作仍在运行时执行恶意钩子[1]。
CVE-2024-32002 漏洞影响 Microsoft Visual Studio 2017 15.9 版和早于 2.45.1、2.44.1、2.43.4、2.42.2、2.41.1、2.40.2 和 2.39.4 的 Git 版本。该漏洞可在不区分大小写的操作系统上启用符号链接支持的环境中被利用。
了解 Git
Git 是一个免费开源的分布式版本控制系统,旨在帮助软件开发人员快速高效地管理代码库。它以标准化、结构化的方式组织和跟踪对文件和目录的修改,从而加强开发团队成员之间的协作。
Git 广泛应用于软件开发。GitHub、GitLab 和 Bitbucket 等平台都是在 Git 的基础上构建的,其强大的功能加强了开发人员之间的协作:
- 记录代码文件的可追踪更改,即提交。
- 必要时将代码编辑回滚到以前的版本。
- 有效整合来自不同分支或贡献者的变更。
- 记录更改的历史及其日期。

Git 挂钩
使用 gitinit或git clone命令创建或克隆 Git 仓库时,会在工作树根目录下生成一个.git目录。.git目录的目录结构最初是这样的
Git 钩子是可执行脚本,位于.git/hooks目录或.git/modules/module_type/module_name/hooks目录中。钩子会在 Git 仓库发生特定事件时自动触发。
如果钩子目录中的文件后缀没有.sample,则该文件中的命令会在文件名中包含的特定 Git 操作(如提交前、提交 后和签出后)之前或之后执行。
Git 子模块
Git 子模块是 Git 仓库中引用外部仓库中特定提交的记录。当一个子模块被添加到版本库时,.gitmodules目录中就会创建一个新文件,其中包含子模块的 URL 与其本地目录之间的映射元数据。当一个版本库包含多个子模块时,.gitmodules文件将包含每个子模块的条目。[3]
符号链接(Symlinks)
符号链接也称为符号链接或软链接,是通过指定路径指向另一个文件或目录(称为 "目标")的文件。如果符号链接被删除,其目标不会受到影响。[4]
Git 中的符号链接(symlink)是指创建一个带有元数据的文件,作为另一个文件的引用或快捷方式。符号链接可用于为一个文件创建多个引用,而无需复制其内容。
GIT 安全漏洞分析
补丁分析
为了深入了解安全漏洞,安全专家通常会进行补丁分析。这是一种有助于识别易受攻击功能和潜在攻击载体的技术。 OPSWAT 研究员检查了补丁版本中为解决 CVE-2024-32002 漏洞所做的更改,他们发现有两个文件已更新以解决该 CVE。
更新的文件之一是submodule--helper.c文件,其中包含处理 Git 子模块克隆的代码。补丁版本中的新提交包括以下两个:
- 添加dir_contains_only_dotgit函数,确保子模块目录不包含任何.git文件或目录。
- 对clone_submodule()函数进行了修改,增加了一个检查子模块目录是否存在且为空的条件。如果目录不为空,克隆过程将被中止。
新提交中的第二个更新是在 t/t7406-submodule-update.sh 文件中,添加了一个测试脚本来验证安全漏洞是否已被解决。
从分析到利用
除了从补丁分析和 CVE-2024-32002 漏洞描述中收集到的见解外,OPSWAT 研究员还致力于研究 Git 中 symlink 和子模块的工作流程。他们分解了用户克隆版本库时发生的一系列事件:
- Git 会首先从主仓库下载文件和目录。
- 它利用符号链接文件中指定的定义,在本地文件系统中重新创建相应的符号链接。
- 如果符号链接指向现有文件,则符号链接将起作用;否则,符号链接将一直不起作用,直到目标文件被恢复。
- 如果使用--recursive选项克隆了版本库,Git 会克隆子模块(外部版本库),并将它们放在 .gitmodules 文件中指定的目录路径下。
- 如果子模块路径中包含一个符号链接(例如,util/module/test,其中util是指向另一个目录(如symlink_folder)的符号链接),Git 会将子模块内容存储在符号链接所引用的实际目录中(如symlink_folder/module/test),同时允许通过原始的符号链接路径进行访问。
了解 CVE-2024-32002 Git 安全漏洞
创建恶意资源库
OPSWAT 研究员进一步检查了根据对t/t7406-submodule-update.sh文件的更新创建恶意软件库的情况,并将这一过程细分为以下步骤:
- 创建包含签出后钩子的版本库
- 创建另一个包含子模块的版本库,该子模块位于A/modules/x路径下。新的子模块会引用之前创建的版本库。
- 创建一个名为a 的符号链接,指向 Git 索引中的.git文件夹。
了解安全漏洞
当用户使用--recursive选项克隆上一步创建的恶意资源库时,将触发结账后钩子中的恶意脚本,从而让攻击者入侵用户的设备。
之所以会发生远程代码执行,是因为主版本库会检测到一个名为a的符号链接,该链接在克隆时指向.git目录。启用递归模式后,子模块也会被拉入克隆版本库。该版本库包含一个 hooks 文件夹,其中包含检出后钩子脚本,其本地目录为A/modules/x 文件夹。
由于a指向.git目录,而文件系统不区分大小写,因此A被解释为等同于a。Git 会被误导将检出后钩子脚本写入.git/modules/query/fast/hooks/目录。如果在 .git/modules/{module_type}/{module_name}/hooks文件夹中发现了检出后钩子脚本,当使用--recursive选项克隆主仓库时,就会触发该脚本。因此,攻击者可通过执行远程代码成功入侵用户设备。
模拟利用 Git 漏洞
根据之前的发现,OPSWAT Fellows 创建了一个主存储库和钩子,以模拟创建恶意存储库:
- 起初,建议将 Git 配置为始终允许使用protocol.file,启用core.symlinks,并将默认分支名称设为main(以避免出现警告信息)。
- 恶意的结账后钩子脚本被添加到钩子目录中。为确保结账后脚本能在用户设备上执行,创建该钩子的 bash 脚本包含chmod +x fast/hooks/post-checkout 命令。
- 在主版本库中创建指向.git目录的符号链接。
带有检票后钩子的/hooks文件夹
补救措施
要消除威胁,用户可以卸载 Git 或应用最新的安全补丁。另外,像MetaDefender Endpoint 这样的解决方案可以及时通知用户,并通过直观的界面显示环境中的所有已知 CVE。MetaDefender Endpoint 可利用其300多万个数据点和3万多个相关CVE(含严重性信息)的功能,检测和缓解最新的CVE。 通过实施这两种对策,CVE 将被完全遏制,从而消除破坏性网络攻击的风险。
您准备好将MetaDefender Endpoint 放在网络安全战略的前沿了吗?