abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-restore-file-open
类别: 文件读取 影响范围: 本地
Forgejo 16.0.5 (8d24b7d) - Forgejo
对不受信任的转储执行 forgejo restore-repo 时,会使用原始的 filepath.Join(baseDir, download_url) 重写发布资产 URL,并加上 file:// 前缀。uri.Open 仍然会 os.Open 该路径。空的 --units 会恢复发布。Gitea 1.27.0 添加了 localFileURL 并跳过了转义条目。该辅助函数在此处不存在。
操作员恢复不受信任的转储时,会将 forgejo uid 可打开的主机文件复制到发布附件中。
| ID | 暂无 CVE |
| 类别 | 文件读取 |
| 影响范围 | 本地(操作员对不受信任的转储执行 forgejo restore-repo) |
| CWE | CWE-22 / CWE-73 |
| CVSS | 高危:7.3 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N |
| 产品 | Forgejo |
| 受影响版本 | 至 v16.0.5(8d24b7d);本地操作员恢复 |
| 认证 | 本地操作员恢复不受信任的转储 |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
将转储目录交给操作员(或已拥有 INTERNAL_TOKEN 以及服务器可读取的路径)。单元包括 releases / release_assets。
| 权限 | 方法 / 汇聚点 | 侦察 / 完整性 / 可用性 | 实验验证或推断 |
|---|---|---|---|
通过 .. 逃逸出转储目录,读取 forgejo uid 可打开的主机文件 | release.yml download_url: ../FORGEJO-FILE-WITNESS.txt;恢复时拼接,uri.Open 执行 os.Open,字节存储为 witness.txt | 侦察(主机文件机密性) | 实验验证。附件内容为 FORGEJO-RESTORE-FILE-OPEN-WITNESS。转储内的诱饵 INSIDE-DUMP-NOT-HOST 未被提供 |
| 在转储内植入符号链接得到相同结果 | 拼接后的路径仍位于 baseDir 下;os.Open 会跟随该链接 | 侦察 | 从 uri.Open file -> os.Open 推断。实验使用的是 ..,而非符号链接 |
| 对 PR 补丁的相同汇聚点 | pull_request.yml PatchURL 以相同方式重写,然后 uri.Open 写入 repo/pulls/<n>.patch | 侦察 | 从 restore.go GetPullRequests 推断。实验仅恢复了发布 |
| 恢复后仓库的读者可下载该主机文件 | GET /<owner>/<repo>/releases/download/<tag>/<name> | 侦察 | 实验验证,以 labadmin Basic 身份访问恢复后的公开仓库 |
典型主机文件:app.ini、INTERNAL_TOKEN、SECRET_KEY、数据库密码 | forgejo uid 可读取配置目录树 | 侦察 | 推断。实验见证文件是放置在转储旁的文件,而非真实机密 |
此处已排除:实时 POST /repos/migrate file:// LFI(已设置 DownloadFunc;PR PatchURL 会针对克隆 HTTP 基址进行前缀检查)。绝对 DownloadURL 转储根拼接逃逸(Go filepath.Join("/dump", "/etc/passwd") 仍为 /dump/etc/passwd)。未认证 HTTP 恢复(仅 CLI / 内部令牌)。备份 dump 打包 app.ini(按设计包含机密,归档模式 0600)。非操作系统 LPE。非远程 LFI。
我有两个恢复思路。我先在脑中实验了 Gitea 的绝对路径拼接。Go 的 filepath.Join 不会像 Python 的 os.path.join 那样丢弃绝对路径的第二个参数。有效的输入是相对路径 ..。Gitea 的 localFileURL 不在此代码树中。
已记录的弯路:通过绝对 DownloadURL 的转储根拼接逃逸;实时迁移 file:// LFI;X-Forgejo-Internal-Auth(恢复是以 forgejo uid 运行的 CLI,而非 /api/internal);将恢复 HTTP 视为远程未认证;反弹 shell。都是花架子。
python3 forgejo-restore-file-open-Abraxas-Labs.py
或:
cd lab
./run.sh
目标仅限 http://127.0.0.1:19340。镜像 codeberg.org/forgejo/forgejo:16.0.5。见证文件 FORGEJO-RESTORE-FILE-OPEN-WITNESS。
IOC asset name='witness.txt' ...
IOC download status=200 bytes=34 snippet=b'FORGEJO-RESTORE-FILE-OPEN-WITNESS\n'
SUCCESS forgejo-restore-file-open how=live ..-join file:// os.Open FORGEJO-RESTORE-FILE-OPEN-WITNESS
在 EvalSymlinks 之后将拼接路径限制在 baseDir 下(Gitea PR 38215 localFileURL)。拒绝 ..。不要跟随转储侧的符号链接逃逸出转储目录。除转储根目录辅助函数外,从 uri.Open 中移除 file://。
restore.go · uri.goGNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。无担保。