mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-06-12 19:11:44 -07:00
Translated ['src/pentesting-ci-cd/gogs-security/README.md'] to zh
This commit is contained in:
@@ -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 <subcommand> <user-controlled-ref>
|
||||
```
|
||||
防御性代码中期望的更安全模式:
|
||||
```bash
|
||||
git <subcommand> -- <user-controlled-ref>
|
||||
# or
|
||||
git <subcommand> --end-of-options <user-controlled-ref>
|
||||
```
|
||||
一个常见的错误假设是,用 `git rev-parse --verify <ref>` 验证 ref 就足够了。事实并**非如此**:
|
||||
|
||||
- 攻击者可以先**创建一个真实分支**,其名称以 `--` 开头
|
||||
- `rev-parse --verify` 只检查该 ref 是否解析到一个 object
|
||||
- 后续不安全的 Git 调用仍可能将同一个值解析为一个**option**
|
||||
|
||||
这会把任何重用已存储 branch 名称的 Git-hosting 功能变成潜在的 RCE primitive。
|
||||
|
||||
## 利用 `git rebase --exec` 实现 RCE
|
||||
|
||||
`git rebase` 支持 `--exec=<cmd>`,它会在回放 commits 后通过 `sh -c` 运行该命令。因此,如果一个 pull request 的 base branch 触发了类似下面的调用:
|
||||
```bash
|
||||
git rebase --quiet <baseBranch> <headBranch>
|
||||
```
|
||||
而 `<baseBranch>` 是由 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_payload>|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}}
|
||||
Reference in New Issue
Block a user