abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitea-user-keys-idor
Gitea 1.27.3 - Gitea
GET /api/v1/user/keys/{id} 位于当前用户组(reqToken、rejectPublicOnly)中。该处理程序仍然按数字 ID 加载记录,且没有所有者检查。同一张表存放用户密钥、部署密钥和主体。GPG 的同类实现则做得正确:GetGPGKeyForUserByID(ctx, ctx.Doer.ID, id)。私有字段受到保护。但公钥材料、标题和指纹没有。ID 是顺序的。
一个 read:user 令牌遍历 1、2、3,就能清点他人的 SSH 密钥和部署密钥。开放注册使这成为一个新账号即可利用的漏洞。
| ID | 暂无 CVE |
| CWE | CWE-639 |
| CVSS | 高危:7.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| 产品 | Gitea |
| 受影响版本 | 至 v1.27.3(146cc3e) |
| 认证 | 已认证(read:user 令牌) |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
注册(默认开放注册),生成一个 read:user 令牌,遍历 /api/v1/user/keys/{id}。他们就能获取不属于自己的密钥的标题、指纹和公钥材料,包括部署密钥。他们拿不到私钥。他们拿不到 shell。他们清点谁对什么有访问权限。
1.27.3 的密钥 GHSA 是按用户名限定的列表加上 individualPermsChecker。并不是这个查询。
同一标签下的遗留问题:git HTTP 重定向 SSRF。
v1.27.3 关闭了 2026 年的 GHSA 浪潮。我仍然停留在那个标签上,把当前用户密钥处理程序与 GPG 对照阅读。GPG 对外来 ID 返回 404。SSH 则不会。
seed.sh 植入受害者密钥标题 GHSA-GITEA-KEY-IDOR-WITNESS 和一个攻击者密钥。攻击者自己的列表不包含该见证项。以攻击者身份执行 GET /user/keys/1 则包含。GPG 对外来 ID 返回 404。这就是全部论据。
已记录的弯路:把攻击者自己的列表当作泄露点(并非如此——列表是有作用域的,按 ID 的 GET 则不是);一个反向 shell。纯属表演。
客户端 bug 看起来像产品 bug。一个遮蔽 http.client 的辅助程序从不发送数据包。对 HTTPResponse 调用 .recv() 不是 .read()。我提一次是因为它耗费了时间,并且有一分钟看起来像是 1.27.3 已经完成了修复。
cd lab
./run.sh
目标仅限 http://127.0.0.1:18101。
add-key user=victim status=201 title=GHSA-GITEA-KEY-IDOR-WITNESS id=1
add-key user=attacker status=201 id=2
attacker-list status=200 ids=[2] (no witness)
get id=1 status=200 snippet contains GHSA-GITEA-KEY-IDOR-WITNESS
SUCCESS Gitea #1 user/keys IDOR
除非 key.OwnerID == ctx.Doer.ID(或站点管理员),否则返回 404。拒绝部署/主体类型。与 GPG 保持一致。
GetPublicKeyGNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。无担保。