Git 是一个免费和开源的分布式版本控制系统,支持在多个系统(windows、linux、macbook)安装运行,广泛用于协作开发和管理软件项目。
CVE-2024-32002漏洞原理
利用文件系统特性:在 Windows 和 macOS 等默认采用大小写不敏感文件系统的平台上,攻击者创建与已有目录名称仅大小写不同的符号链接。
混淆 Git 写入路径:攻击者构造带有子模块的恶意 Git 仓库,其中主仓库有一个符号链接文件指向.git 目录,如名为 “a” 指向 “.git”,而子模块存储路径设置为与符号链接文件名仅大小写不同,如 “A/modules”。当用户使用 git clone --recursive 命令递归克隆该恶意仓库时,由于系统不区分大小写,Git 会将子模块写入到.git/modules 目录下而非正常的子模块工作树。
执行恶意脚本:子模块中包含恶意的钩子脚本(如 post-checkout),在克隆操作过程中,这些恶意脚本会被触发执行,而用户没有机会事先检查正在执行的代码。
影响版本:
git 2.45.0
git 2.44.0
git 2.43.* < 2.43.4
git 2.42.* < 2.42.2
git 2.41.0
git 2.40.* < 2.40.2
git < 2.39.4
复现
我是在win10虚拟机上安装了2.39.1版的git。然后GitHub要配置ssh-key。
不会可以上网搜在虚拟机上面配ssh公钥私钥来登录GitHub
管理员打开powershell,执行。
git config --global core.symlinks true
#启用符号链接支持
在支持符号链接的系统上:当 core.symlinks 设置为 true 时,Git 会像对待普通文件一样跟踪和管理符号链接。在提交和克隆仓库时,符号链接会被正确地处理和还原。例如,在 Linux 和 macOS 等系统中,默认支持符号链接,启用该选项可以确保符号链接在版本控制中正常工作。
在不支持符号链接的系统上:如果在不支持符号链接的系统(如某些 Windows 版本)上启用该选项,当克隆包含符号链接的仓库时,Git 可能会尝试创建符号链接,但可能会失败。此时,Git 可能会将符号链接当作普通文件处理,这可能导致文件内容与预期不符。
然后
git clone --recursive git@github.com:amalmurali47/git_rce.git
原理分析
符号链接的基本概念
符号链接(Symbolic Link),也被称为软链接,是一种特殊的文件,它包含一个指向另一个文件或目录的引用。简单来说,符号链接就像是一个快捷方式,当你访问符号链接时,系统会自动将你导向它所指向的目标文件或目录。
GitHub 本身支持符号链接,但这依赖于底层操作系统和 Git 的支持。在支持符号链接的操作系统(如 Linux、macOS)上,当你将包含符号链接的仓库推送到 GitHub 时,GitHub 能够正确识别并存储这些符号链接信息。
当其他用户克隆这个仓库时,如果他们使用的操作系统也支持符号链接,那么克隆下来的仓库中符号链接会保持原样,能够正常工作。
git clone
使用git clone命令时,实际执行的是几个子命令:
1、 mkdir -p <path> && cd <path> # 创建一个目录并进入
2、 git init # 初始化git仓库
3、 git remote add origin <url> # 添加远程仓库
4、 git fetch origin # 下载对象引用
5、 git checkout -b <branch> --track origin/<branch> #创建一个本地分支,并跟踪远程分支
hook
git里面提供了一个hook的功能,它允许用户在发生特定的git事件时,自动执行用户指定的脚本或操作,例如代码格式化、测试,运行、发送通知。
hooks脚本目录存在于.git目录下,里面存放很多shell脚本,这些脚本会在git执行到某个阶段时被执行,.git目录只会存放在本地,克隆网上的仓库的时候,也不会下载这个自录,它是由本地的git客户端自动生成的。
git中的子模块
一个git仓库嵌套了另一个git仓库,子模块的.git目录通常在外层仓库的.git/modules目录下
父仓库本来有个a符号链接,指向.git,又有一个A目录,由.gitmodules的内容知道A/modules下的x目录就是git@github.com:amalmurali47/hook.git这个子仓库克隆下来后的父目录
git clone --recursive 通常需要搭配 .gitmodules 文件
当你使用 git clone --recursive <远程仓库地址> 命令时,Git 会执行以下操作:
- 克隆主仓库:如同普通的 git clone 命令一样,将指定的远程仓库克隆到本地,创建一个包含 .git 目录的本地仓库副本,同时将主仓库的文件检出到工作目录。
- 递归克隆子模块:检查主仓库中的 .gitmodules 文件,该文件记录了子模块的配置信息(如子模块的名称、本地路径和远程仓库地址)。然后,Git 会根据这些配置信息,递归地克隆所有子模块到主仓库中指定的路径。对于每个子模块,Git 也会初始化其本地仓库,并从远程仓库拉取最新的提交。
- 处理嵌套子模块:如果子模块本身还包含其他子模块(即嵌套子模块),–recursive 选项会继续递归克隆这些嵌套子模块,确保整个仓库结构完整地克隆到本地。
整个过程是
git clone --recursive先克隆父仓库
检查到.gitmodules,检查到子仓库信息,开始克隆子仓库。
A目录和a符号链接冲突,A目录被指向.git的同名符号链接覆盖。
所以克隆的子仓库实际上在.git/modules/x/下,当克隆到.git/modules/x/y/hooks/post-checkout这个脚本时,前面说过git clone的最后一步是git checkout,这时就会触发post-checkout脚本执行。
漏洞本质上是:
git在进行clone的时候,由于Windows或者MacOS操作系统大小写不敏感的特点,主仓库中用于存放子模块的目录在下载时被另一个指向.git目录的同名符号链接覆盖,导致往子模块写入数据的时候,全部都写入了.git目录中,最后配合hook脚本完成隐蔽的攻击。
修复与防范措施
- 更新 Git 版本:将 Git 更新到 2.45.1、2.44.1、2.43.4、2.42.2、2.41.1、2.40.2、2.39.4 及以上版本。
- 禁用符号链接功能:在 Git 中禁用符号链接支持,可通过执行命令git config --global core.symlinks false。
- 谨慎克隆仓库:避免从不可信的来源克隆 Git 仓库,对来源不明的仓库要保持警惕。
参考链接
https://wsxk.github.io/cve202432002/