diff --git a/src/pentesting-ci-cd/gogs-security/README.md b/src/pentesting-ci-cd/gogs-security/README.md new file mode 100644 index 000000000..5387858f5 --- /dev/null +++ b/src/pentesting-ci-cd/gogs-security/README.md @@ -0,0 +1,103 @@ +# Gogs Security + +{{#include ../../banners/hacktricks-training.md}} + +## 什么是 Gogs + +**Gogs** 是一个用 Go 编写的**self-hosted 轻量级 Git service**。从攻击者的角度看,可以将其视为一个**multi-tenant Git hosting platform**,即使低权限用户也可能控制 branch names、pull requests、webhooks、tokens 和 repository settings。 + +## 通过 refs / branch names 进行 Git option 注入 + +如果应用程序将攻击者控制的 **ref name** 直接传给 Git command,**而没有使用 `--` 或 `--end-of-options`**,那么以 `--` 开头的 branch 可能会被解析为 **Git option**,而不是数据。 + +Typical dangerous pattern: +```bash +git +``` +防御性代码中期望的更安全模式: +```bash +git -- +# or +git --end-of-options +``` +一个常见的错误假设是,用 `git rev-parse --verify ` 验证 ref 就足够了。事实并**非如此**: + +- 攻击者可以先**创建一个真实分支**,其名称以 `--` 开头 +- `rev-parse --verify` 只检查该 ref 是否解析到一个 object +- 后续不安全的 Git 调用仍可能将同一个值解析为一个**option** + +这会把任何重用已存储 branch 名称的 Git-hosting 功能变成潜在的 RCE primitive。 + +## 利用 `git rebase --exec` 实现 RCE + +`git rebase` 支持 `--exec=`,它会在回放 commits 后通过 `sh -c` 运行该命令。因此,如果一个 pull request 的 base branch 触发了类似下面的调用: +```bash +git rebase --quiet +``` +而 `` 是由 attacker 控制的,一个诸如以下的 branch: +```bash +--exec=touch${IFS}/tmp/rce_proof +``` +可以被解释为一个 **Git flag**,而不是一个 branch name。 + +### 为什么 `${IFS}` 重要 + +Git refs 不能包含字面上的空格,但当 Git 通过 `sh -c` 执行 `--exec` 时,shell expansion 仍然会发生。`${IFS}` 会在运行时展开为空白,因此可以使用如下 payload: +```bash +--exec=touch${IFS}/tmp/rce_proof +--exec=id${IFS}>/tmp/out +``` +对于需要 Git 禁止字符(`:`, `~`, `^`, `?`, `*`, `[`, `\\`, `//`)的 payload,将真实命令进行编码,并在执行时解码: +```bash +--exec=echo${IFS}|base64${IFS}-d|sh +``` +## Windows-specific payload delivery + +在 Windows 上,inline payloads 受限更多,因为 Git 将 branch refs 存储为文件,而 NTFS 禁止在文件名中使用诸如 `|` 之类的字符。一个实用的替代方法是: + +1. 将一个 payload script 提交到 repository 中(例如 `.abcdef`) +2. 创建一个 branch,如: +```bash +--exec=sh${IFS}.abcdef +``` +如果 Git for Windows 通过 **MSYS2 `sh`** 启动 payload,PowerShell 元字符可能会被破坏。一个实用的 workaround 是让已提交的 script 调用: +```bash +cmd.exe //c .abcdef.bat +``` +where `//c` is the MSYS2-safe form of Windows `/c`. + +## Merge / PR state-machine abuse + +When testing Git-hosting platforms, do not only review the final dangerous command. Also review **earlier validation paths** and **background rechecks**. + +A useful exploitation pattern is: + +1. Initial validation path uses a **safe** clone/fetch flow with `--end-of-options`, so the malicious branch is accepted as data +2. The pull request becomes **mergeable** +3. A later merge or checkout path reuses the stored branch name in an **unsafe** Git call +4. Code execution happens even if a later step fails and the UI returns **HTTP 500** + +This means a feature can be exploitable even when the final merge ends in an error, and the target repository may be left in a **corrupted partial rebase state** after the payload already ran. + +## Practical hunting ideas + +When reviewing a Gogs instance or similar Git service, check for: + +- Branch names beginning with `--` +- Merge failures involving `git checkout '--exec=...'` +- Pull requests stuck as mergeable even though later branch validation fails +- Repositories left in partial rebase / broken Git state after failed merges +- Unexpected committed helper files on Windows payload paths (for example dotfiles plus `.bat` launchers) +- Suspicious API tokens created shortly before failed PR merges + +Example log artifact: +```text +merge: git checkout '--exec=<...>': exit status 128 - error: unknown option `exec=<...>' +``` +## References + +- [Rapid7 - 通过 Gogs 中的 Argument Injection 实现经过身份验证的 RCE(NOT FIXED)](https://www.rapid7.com/blog/post/ve-authenticated-rce-via-argument-injection-gogs-unfixed) +- [Metasploit module PR for Gogs rebase argument injection](https://github.com/rapid7/metasploit-framework/pull/21515) +- [Git rebase documentation (`--exec`)](https://git-scm.com/docs/git-rebase) + +{{#include ../../banners/hacktricks-training.md}}