abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitea-hostmatcher-0000-ssrf
Gitea 1.27.3 - Gitea
CVE-2026-22874 添加了 reservedIPNets。CGNAT、TEST-NET、NAT64、Teredo、Azure WireServer。真实网段。不是 RFC 6890 的 0.0.0.0/8,那个旧的“本网络”块。IANA 仍在发布它。Go 的 IsGlobalUnicast 对 0.0.0.1 返回 true。它不是 IsLoopback(127.0.0.0/8)。它不是 IsPrivate。默认外部允许列表将其视为公共互联网。如果该地址在 lo 上,Linux 会将 0.0.0.1 投递到本地套接字。同一个监听器,两个名字。
已登录用户可以将 webhook 指向 http://0.0.0.1,并从 hook 历史记录中读取 HTTP 响应体。同一端口上的 127.0.0.1 会被拒绝。
| ID | 暂无 CVE |
| CWE | CWE-918 |
| CVSS | High: 7.7 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N |
| 产品 | Gitea |
| 受影响版本 | 至 v1.27.3(146cc3e);CVE-2026-22874 的遗留问题 |
| 认证 | 可创建仓库 webhook 的已登录用户 |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
注册(默认开放注册)、创建仓库、将 webhook 指向 http://0.0.0.1:<local-port>/、测试它,然后从 hook 历史记录中读取响应体。这是同一端口上 127.0.0.1 无法访问的环回 HTTP:任何在 Gitea 网络命名空间中监听、且绑定范围比环回更广的服务,包括运维人员因为其屏蔽了 127.0.0.0/8 而误以为“仅限 localhost”的服务。
它不会设置 X-Gitea-Internal-Auth。它本身不是 RCE。它是来自一个仍被允许列表称为外部的地址的完整 HTTP 响应体。
v1.27.3 是关闭 2026 GHSA 浪潮的构建版本。我仍然停留在那个标签上。添加允许列表或拒绝列表的补丁是一份礼物:你阅读列表,然后问 IANA 还有什么被列表遗忘了。这个代码树上已经有两个遗留问题有实验环境(keys IDOR 和 git-redirect SSRF)。那篇文章中的遗留问题表将指向 http://0.0.0.1/ 的 webhook 列为地图。这就是 SUCCESS。
Webhook 投递将 HTTP 响应体存储在 hook 历史记录中。这比 git clone 更好的预言机,后者基本上只是“fetch 是否成功”。我在 Gitea 的网络命名空间中放置了一个监听 8080 端口的预言机,使用 NET_ADMIN 在 lo 上添加了 0.0.0.1/8,并创建了两个 webhook。先做阴性对照。
已记录的弯路:将 webhook 创建返回 HTTP 201 视为预言机(历史记录才是预言机);127.0.0.1 投递成功(那会是另一个 bug——实验环境要求它被拒绝);使用 X-Gitea-Internal-Auth 访问 /api/internal;反向 shell。都是表演。见证者是 hook 历史记录中的 GITEA-0000-SSRF。
cd lab
./run.sh
目标 仅 http://127.0.0.1:18131。预言机与 Gitea 共享网络命名空间,监听 8080 端口。run.sh 在 lo 上添加 0.0.0.1/8。
create-hook name=neg-loopback status=201
negative-control 127.0.0.1 blocked
create-hook name=hit-0000 status=201
poll id=2 witness=True
SUCCESS GITEA-HOSTMATCHER-0000
将 0.0.0.0/8 添加到 reservedIPNets,或者停止将 IsGlobalUnicast 视为“可安全拨号”。0.0.0.1 必须像 127.0.0.1 一样被拒绝。
GNU Affero GPL v3.0。参见 LICENSE。仅限环回实验环境。无担保。