安全研究 / 蓝队向 writeup。本仓库不包含武器化 PoC。 需要复现的研究者请使用官方 advisory 引用的公开 PoC。
| 项目 | 内容 |
|---|---|
| CVE | CVE-2026-52813 |
| 别名 | GHSA-c39w-43gm-34h5 / GO-2026-5305 |
| 受影响版本 | Gogs < 0.14.3 |
| 修复版本 | 0.14.3 — PR #8334 |
| CVSS 3.1 | 10.0 Critical AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| CWE | CWE-23 Relative Path Traversal → RCE |
| 前置条件 | 一个普通注册账号(默认开放注册时 = 未授权 RCE) |
Gogs 在创建组织时,Web 表单有 AlphaDashDot 字符校验拦截 /,但 REST API POST /api/v1/user/orgs 没有。攻击者通过 API 提交带 ../ 的组织名,绕过校验直达 os.MkdirAll(repoutil.UserPath(org.Name), 0777)(internal/database/org.go:165),把仓库目录写到任意文件系统路径。结合 Gogs 的 Web 编辑器临时工作树(local-r/<repo_id>/),可在另一个仓库的本地 checkout 内落地恶意 hooks/update,由 git 自动执行 → 以 git 用户身份 RCE。
| Gogs 版本 | 状态 |
|---|---|
< 0.14.3 | 受影响,立即升级 |
>= 0.14.3 | 已修复 |
升级是唯一彻底修复手段:
# Docker
docker pull gogs/gogs:0.14.3
# 或源码
git checkout v0.14.3 && go build
临时缓解(无法升级时):
app.ini → [service] DISABLE_REGISTRATION = true),把前置条件从"未授权"降级为"需已存在账号";POST /api/v1/user/orgs、POST /api/v1/org/*/repos 请求体中 username / name 字段含 .. 或 / 的(见 detection/);/data/gogs/data/tmp/ 之外的写权限(selinux/apparmor)。Web 表单(internal/form/org.go,v0.14.2):
type CreateOrg struct {
OrgName string `binding:"Required;AlphaDashDot;MaxSize(35)"` // 正则 ^[a-zA-Z0-9._-]+$
}
API(internal/route/api/v1/org/org.go,v0.14.2):
// api.CreateOrgOption (go-gogs-client) 的绑定 tag:
type CreateOrgOption struct {
UserName string `json:"username" binding:"Required"` // ← 没有 AlphaDashDot!
}
→ POST /api/v1/user/orgs 的 username 字段可携带任意字符直达 DB 层。
internal/database/users.go:1532 isNameAllowed 只拦截保留名/前后缀(如 admin、-bot),不校验字符集,所以 ../ 能过。
internal/repoutil/repoutil.go(v0.14.2):
func UserPath(user string) string {
return filepath.Join(conf.Repository.Root, strings.ToLower(user)) // ← 直接拼接
}
internal/database/org.go:165:
os.MkdirAll(repoutil.UserPath(org.Name), os.ModePerm) // org.Name 含 ../ → 任意路径写入
Gogs 处理 Web/API 文件编辑时,会把仓库 checkout 到 /data/gogs/data/tmp/local-r/<repo_id>/。<repo_id> 恰好等于仓库的数据库 id。攻击者:
writer,得到 id == n;username = "../../../../data/gogs/data/tmp/local-r/n/nested" → 物理目录落在 writer 的工作树内;rce-x → 落在 local-r/n/nested/rce-x.git;writer,把 nested/rce-x.git/hooks/update 作为普通文件提交并 push(它就落在 writer 工作树里);writer 的文件操作 → Gogs 在 local-r/n/ 跑 git → git 执行 hooks/update → RCE。关键点:恶意 hook 是作为普通仓库内容通过正常 push 进入的,不需要
ENABLE_GIT_HOOKS配置——这是它和"传统 git hooks 滥用"路线的区别。
详细补丁 diff 分析见 patch/ANALYSIS.md。
完整规则见 detection/:
../)和成功利用(文件系统落地)最关键的两条:
POST /api/v1/user/orgs 与 POST /api/v1/org/*/repos 的 JSON body 中 username/name 字段含 .. 或 /。/data/gogs/data/tmp/local-r/*/ 下出现非预期子目录(nested/、rce-*.git、hooks/update)。GET /api/v1/version 检查 Gogs 实例是否 < 0.14.3,支持批量扫描、CSV 输出,适合资产盘点。本仓库不提供武器化利用工具。复现请使用 官方 advisory 引用的公开 PoC,并仅在自建隔离环境进行。
detection/ 规则需要在受影响的 Gogs 上验证,lab/docker-compose.yml 提供隔离的 Gogs 0.14.2 环境供蓝队测试检测规则是否命中。请勿暴露到公网,仅本地使用。
| 日期 | 事件 |
|---|---|
| 2026-06-08 | CVE 保留 |
| 2026-06-24 | 公开披露,Gogs 0.14.3 发布 |
| 2026-06-24 | 官方 advisory GHSA-c39w-43gm-34h5 发布 |
网上有把这个 CVE 描述成 "Gogs gitrebase 参数注入远程代码执行" 的——那是错的。本漏洞与 git rebase / gitrebase 无关,根因是 API 路径穿越。本文档按真实漏洞分析。
MIT — 见 LICENSE。