漏洞概况
CVE-2024-32002漏洞
当用户使用管理员权限执行git clone —recursive 克隆一个恶意仓库时,git中存在的漏洞会触发远程代码执行
攻击者可以创建恶意的仓库,诱导使用git的用户clone,从而在客户端执行任意的系统命令
什么是Git?
Git是一个版本管理控制工具,常用来管理代码仓库,它可以记录每一次提交的内容,能够随时恢复到之前的版本。
什么是GitHub?
Github是一个使用Git作为版本管理控制的代码托管平台,个人或组织可以将自己的软件项目存放到GitHub上,可在其中存储、共享并与他人一起编写代码。
受影响的版本:
2.45.0
2.44.0
2.43.0 - 2.43.4
2.42.0 - 2.42.2
2.41.0
2.40.0 - 2.40.2
< 2.39.4
只影响windows和mac系统(文件系统大小写不敏感)
利用条件:
git开启符号链接支持
使用管理员权限执行
git clone --recursive
命令clone恶意仓库
漏洞复现
靶场环境搭建与复现步骤:
安装Git
注册GitHub账号
生成ssh密钥
在GitHub中配置ssh公钥
开启Git中的符号链接支持
克隆恶意仓库,触发漏洞
详细步骤讲解:
1.安装带有漏洞版本的Git客户端,我这里用的版本是2.39.1
(安装步骤省略,无脑点击下一步即可)
2.注册Github账号,相信大家都会玩Github,这里就不做过多赘述了,如果实在是不知道咋注册,可以去搜索相应的文章,这里给大家推荐一篇文章:github新手用法详解(建议收藏!!!)-CSDN博客
- 生成ssh密钥
ssh-keygen -t ed25519 -C "(这里写你自己对应的邮箱)"
使用more 命令来查看ssh公钥文件
- 在GitHub中配置ssh公钥
打开如下网址,进入如下界面
https://github.com/settings/ssh/new
我们把ssh的公钥信息粘贴到key的里面,然后再Add SSH Key
保存成功
- 开启Git中的符号链接支持
用管理员权限打开CMD,运行如下命令
git config --global core.symlinks true
完成以上几步,我们的漏洞环境就配置好了
在虚拟机中,往C盘的位置创建一个临时目录
- 克隆恶意仓库,触发漏洞
接着用管理员权限打开cmd,运行下列命令
git clone --recursive [email protected]:amalmurali47/git_rce.git
计算器成功弹了出来,漏洞复现成功
漏洞分析
想要了解此漏洞的原理,首先我们需要知道git中几个重要的知识点
git中的hook功能:
git里面提供了一个hook的功能,它允许用户在发生特定的git事件时,自动执行用户指定的脚本或操作,例如代码格式化、测试运行、发送通知。(白话来讲,用户可以编写一些脚本,当git发生了一些特定事件后,git就会自动的调用这些脚本,这些脚本就会被运行)
hook脚本存放在.git目录下面,.git目录只会存放在本地,克隆网上的仓库的时候,也不会下载这个目录,它是由本地的git客户端自动生成的
常见的git事件有以下几种:(稍做了解即可)
pre-commit:在提交之前运行。可以用来检查代码格式、运行单元测试等。
commit-msg:在提交信息编辑器关闭之后运行。可以用来验证提交消息的格式。
post-commit:在提交完成之后运行。可以用来发送通知或执行其他后续任务。
post-checkout:在 git checkout 命令执行之后运行。可以用来设置特定文件的状态。(其中的这个post-checkout 就是我们在克隆仓库的时候会发生的)
post-merge:在合并操作完成之后运行。可以用来重新编译项目或执行其他合并后的任务。
问题:如果我们电脑上的某个git项目中的.git目录下面存放了一些恶意的hook脚本会产生什么样的后果?
答案:当我们进行一些git操作的时候,比如克隆仓库,提交代码这些恶意的脚本都有可能被触发,因此自己编写的hook脚本,一定要保证它是安全并且正确的
hook脚本的话,刚才我们说了,它是用户自己编写的,存放在.git目录下,并且这个.git目录只会保存在本地,并不会上传到GitHub上面,那么当我们去克隆网上的仓库的时候,其他人的.git目录也不会下载保存到我们的电脑上,因此在正常情况下,即使我们克隆了恶意的代码仓库,就算其中包含的恶意的脚本,也不会下载保存到本地电脑上,所以我们可以放心大胆的从GitHub上克隆仓库,但是今天的这个漏洞,就是通过一些特殊的方式,将恶意的脚本,写入到了.git目录下面
要想弄明白这是怎么做到了,这就又涉及到另一个知识点了
git中的子模块
一个git仓库嵌套了另一个git仓库,子模块的.git目录通常在外层仓库的.git/modules目录下
(它的意思就是说一个git仓库里面包含了另外一个git仓库,里面的这个git仓库就是外面的git仓库的子模块,当我们执行git clone --recursive 克隆一个仓库的时候,它就会把外面的这个仓库的代码下载下来,然后再把里面的仓库的代码也克隆下来,同时子模块也有自己的.git目录,它的这个git目录通常是在外层仓库的.git/modules目录下,子模块中也可以有自己的hook脚本,在git操作执行到特定的流程的时候,也会被执行)
我们回过头来看我们刚才克隆的那个恶意仓库
在这个仓库里存在着modules目录,我们点击进去看一下
这个目录下面存放的就是一些子模块
我们再打开这个子模块看一下
我们可以看到,这个子模块中存放了一个y目录,y目录下面又有一个hooks目录,我们点击进去看一下
我们可以看到,hooks目录中存放了一个名为post-checkout的脚本我们点击进去看一下
而这个脚本的内容,就是我们刚才执行的那个恶意脚本,它被触发后,就会在我们windows中打开一个计算器程序
我们回过头再看这个恶意仓库,除了这个A目录外,还有一个a目录
而这个a目录,实际上它是一个软链接,它指向的是.git目录,作用类似于windows中的快捷方式,也就是说我们往a目录里面写文件,实际上是往.git目录下面,那么在liunx系统中,对于A目录和a目录,实际上是两个不同的目录,但在windows中,文件系统不会区分大小写,因此A目录等同于a目录
现在我们来看一下Git克隆这个仓库的时候,执行了什么样的一个流程,我们就能弄明白这个漏洞的原理是什么样的了
首先我们执行git clone的时候,git会把这个仓库的内容克隆到我们本地,然后它再把子模块的内容克隆到我们本地
注意:白色选中部分的那两行信息是一个报错信息,意思是告诉我们,我们当前的操作系统,它是大小写不敏感的
那么这个项目中存在了两个名称相同的目录,也就是A目录和a目录,但最后只有a目录保存到了操作系统上
这里我们可以打开目录看一下,只有a目录,没有A目录
克隆完外层的仓库后,git就会克隆子模块的目录,在克隆这个子模块的时候,由于内容全部存放在A目录上面,但是在我们的系统上A目录和a目录实际上是同一个目录,而a目录它又指向了.git目录,因此这个子模块中的内容它会存放在.git目录下面,我们可以打开这个目录看一下
这个文件的内容就是我们刚刚在GitHub上看到的那个恶意脚本,它会在我们windows电脑中打开一个计算器程序
以上就是这个漏洞的利用原理
我们再来回顾一下:
首先这个恶意仓库里面有一个名为A的目录,然后这个A目录中又有一个modules目录,在这个modules里面有一个子模块,这个子模块的名称是x,然后x下面有个y目录,y目录下面又有一个hooks目录,在这个hooks目录下面又存放了一个脚本,它叫做post-checkout
然后这个恶意仓库里面还有一个a目录,这个a目录实际上是一个软链接(符号链接),它指向了.git目录
那么在git在克隆这个恶意仓库的时候,首先它会把a目录保存到磁盘上,但a目录实际上是.git目录,然后它会去克隆子模块,这个子模块由于在Windows上a和A实际上是同一个目录,因此这个子模块所有的内容它就会写入到a目录下面,那么最终这个子模块中的内容,它的路径是这样的
.git/modules/x/y/hooks/post-checkout
这样一来我们就能理解这个漏洞的原理了
小总结:
恶意的git项目里面有一个子模块,子模块的存储路径为A/modules,子模块里构造了一个hooks目录,里面有个post-checkout脚本,脚本里放恶意代码
项目中还有一个名为a的符号链接,指向.git目录
当递归克隆这个项目时,由于大小写区分不敏感,导致子模块被写到了.git/modules目录里
而克隆的相关动作会触发post-checkout钩子的执行,而现在的hooks目录下post-checkout脚本里放的是攻击者的恶意代码,于是就导致恶意代码被执行
这个漏洞实际上就是把一些恶意的脚本存放到git仓库中的一个子模块下面,然后它利用Windows系统中目录名称大小写不敏感这种特性,把原本应该写入到一个正常的目录下面,最终写入到.git目录下面,然后它利用了git中提供了hooks脚本的功能,在克隆仓库的时候,触发了这个恶意脚本
修复与防御:
更新git版本
禁用符号链接功能
不要克隆来源不明的仓库
版权归原作者 忆南呦 所有, 如有侵权,请联系我们删除。