Forgejo 16.0.5 - 高危 - 远程 - SSRF - OpenID 发现机制会获取攻击者控制的 URL
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-openid-discovery-ssrf
类别: SSRF 可达性: 远程
Forgejo 16.0.5 (8d24b7d) - Forgejo
当 [openid] ENABLE_OPENID_SIGNIN 开启时,未认证的 POST /user/login/openid 会将攻击者提供的 URL 交给 yohcop openid-go v1.0.1。该库的包级辅助函数使用 http.DefaultClient。此路径上没有 hostmatcher。Webhook 和迁移会过滤出站 HTTP。OpenID 不会。
任何能访问登录表单的人都可以从 Forgejo 主机向 loopback、RFC1918、CGNAT 和 IMDS 发起 Yadis GET 请求。
| ID | 暂无 CVE |
| 类别 | SSRF |
| 可达性 | 远程(未认证,当 OpenID 登录启用时) |
| CWE | CWE-918 |
| CVSS | 高危:8.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N |
| 产品 | Forgejo |
| 受影响版本 | 至 v16.0.5(8d24b7d)且启用 ENABLE_OPENID_SIGNIN;Gitea CVE-2026-58314 的遗留问题 |
| 认证 | 未认证 |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
无需账户。POST 一个 OpenID URL。Forgejo 主机会获取它。
| 权限 | 方法 / 汇聚点 | 侦察 / 完整性 / 可用性 | 实验验证或推断 |
|---|---|---|---|
| 向 loopback 发起 Yadis GET | 未认证 POST /user/login/openid,携带 openid=http://127.0.0.1:18080/ | 侦察(从 Forgejo 主机发出的出站 HTTP) | 实验验证。Oracle 观察到来自 127.0.0.1 的 GET /,带有 Accept: application/xrds+xml |
| 探测 RFC1918、CGNAT、链路本地、IMDS | 同一 http.DefaultClient Discover,无 IP 过滤 | 侦察 | 从客户端推断。实验仅使用 loopback |
| 从已登录的添加 OpenID 重复 | POST /user/settings/security/openid 也调用 RedirectURL 并跳过 allowedOpenIDURI | 侦察 | 从处理器推断。实验使用未认证登录 POST |
| 在登录错误中读取响应体 | CVE-2021-45325 之后,错误不再转储获取内容 | 侦察 | 实验验证已关闭。此遗留问题是请求,而非 HTML 泄露 |
在此版本上已关闭:OpenID 关联 CSRF(openIDState 会话 nonce)、webhook/migrate hostmatcher(仍在那里使用)、git followRedirects=false、migrate LookupIP CVE-2026-82556。实验不完成 OpenID 登录,也不返回 shell。
Web 安装程序复选框默认开启(未锁定时 EnableOpenIDSignIn = MustBool(!InstallLock),然后写入 app.ini)。锁定后,省略的键为 false。Docker app.ini 模板没有 [openid] 部分,因此没有向导的预锁定镜像默认关闭,除非操作员设置该键。空的 WHITELISTED_URIS 允许所有 URI。
v16.0.5 关闭了 OpenID 关联 CSRF。我仍然关注那个攻击面。Gitea PR 38406 / CVE-2026-58314 将 hostmatcher 过滤的客户端放入专用的 openid-go 实例。此版本仍然调用包级辅助函数。
已记录的弯路:重新提交关联 CSRF(该 nonce 已在代码树中);将 Docker 预锁定镜像视为默认(向导会写入复选框);期望旧的 OpenID 错误字符串泄露;反向 shell。都是表演。
python3 forgejo-openid-discovery-ssrf-Abraxas-Labs.py
或:
cd lab
./run.sh
目标仅为 http://127.0.0.1:19330。镜像 codeberg.org/forgejo/forgejo:16.0.5。Oracle 共享 Forgejo netns 并绑定 127.0.0.1:18080。
IOC post-openid status=200
IOC xrds-hits count=1
SUCCESS forgejo-openid-discovery-ssrf how=live post=/user/login/openid openid=http://127.0.0.1:18080/ path=/ accept=application/xrds+xml peer=127.0.0.1 post-status=200 FORGEJO-OPENID-DISCOVERY-WITNESS
与 Gitea PR 38406 相同:将 hostmatcher 过滤的 http.Client 放入专用的 openid-go 实例。保留 WHITELISTED_URIS 作为第二道门。阻止 loopback、RFC1918、CGNAT、链路本地和元数据。
modules/auth/openid/openid.goGNU Affero GPL v3.0。参见 LICENSE。仅限 loopback 实验环境。无担保。