
Forgejo 16.0.5 – Hoch – Remote – Dateilesen – restore-repo folgt dump-seitigem file:// in Anhänge
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-restore-file-open
Write-up: https://abraxaslabs.tech/research/forgejo-restore-file-open
Klasse: Dateilesen Reichweite: Lokal
Forgejo 16.0.5 (8d24b7d) - Forgejo
forgejo restore-repo eines nicht vertrauenswürdigen Dumps schreibt Release-Asset-URLs mit rohem filepath.Join(baseDir, download_url) um und stellt file:// voran. uri.Open ruft weiterhin os.Open auf diesen Pfad auf. Ein leeres --units stellt Releases wieder her. Gitea 1.27.0 fügte localFileURL hinzu und übersprang das Escaping von Einträgen. Dieser Helper ist hier nicht vorhanden.
Das Wiederherstellen eines nicht vertrauenswürdigen Dumps durch den Operator kopiert eine Host-Datei, die die forgejo-UID öffnen kann, in einen Release-Anhang.
| ID | noch keine CVE |
| Klasse | Dateilesen |
| Reichweite | Lokal (Operator forgejo restore-repo eines nicht vertrauenswürdigen Dumps) |
| CWE | CWE-22 / CWE-73 |
| CVSS | Hoch: 7.3 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N |
| Produkt | Forgejo |
| Betroffen | bis v16.0.5 (8d24b7d); lokales Operator-Restore |
| Auth | lokales Operator-Restore eines nicht vertrauenswürdigen Dumps |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
Dem Operator ein Dump-Verzeichnis übergeben (oder bereits INTERNAL_TOKEN und einen Pfad besitzen, den der Server lesen kann). Units umfassen releases / release_assets.
| Privileg | Methode / Sink | Recon / Integrität / Verfügbarkeit | Im Lab nachgewiesen oder abgeleitet |
|---|---|---|---|
Eine Host-Datei lesen, die die forgejo-UID öffnen kann, via .. aus dem Dump heraus | release.yml download_url: ../FORGEJO-FILE-WITNESS.txt; Restore fügt zusammen, uri.Open ruft os.Open auf, Bytes werden als witness.txt gespeichert | Recon (Vertraulichkeit von Host-Dateien) | Im Lab nachgewiesen. Der Anhang-Inhalt ist FORGEJO-RESTORE-FILE-OPEN-WITNESS. Der Decoy im Dump INSIDE-DUMP-NOT-HOST wurde nicht ausgeliefert |
| Gleiches Ergebnis mit einem im Dump platzierten Symlink | Der zusammengefügte Pfad bleibt unter baseDir; os.Open folgt dem Link | Recon | Abgeleitet aus uri.Open file -> os.Open. Das Lab verwendete .., keinen Symlink |
| Gleicher Sink bei PR-Patches | pull_request.yml PatchURL wird auf dieselbe Weise umgeschrieben und dann per uri.Open nach repo/pulls/<n>.patch geschrieben | Recon | Abgeleitet aus restore.go GetPullRequests. Das Lab stellte nur Releases wieder her |
| Leser des wiederhergestellten Repos laden die Host-Datei herunter | GET /<owner>/<repo>/releases/download/<tag>/<name> | Recon | Im Lab nachgewiesen als labadmin Basic auf dem wiederhergestellten öffentlichen Repo |
Typische Host-Dateien: app.ini, INTERNAL_TOKEN, SECRET_KEY, DB-Passwort | Die forgejo-UID kann den Config-Baum lesen | Recon | Abgeleitet. Der Lab-Witness war eine platzierte Datei neben dem Dump, keine echten Secrets |
Hier geschlossen: Live-POST /repos/migrate file:// LFI (DownloadFunc gesetzt; PR PatchURL wird gegen die Clone-HTTP-Basis auf Präfix geprüft). Absolute DownloadURL-Dump-Root-Join-Escape (Go filepath.Join("/dump", "/etc/passwd") bleibt /dump/etc/passwd). Unauth-HTTP-Restore (nur CLI / internes Token). Backup-dump-Packen von app.ini (Secrets by Design, Archivmodus 0600). Kein OS-LPE. Kein Remote-LFI.
Ich hatte zwei Restore-Ideen. Die Gitea-Absolut-Join-Idee habe ich zuerst im Kopf durchgespielt. Go filepath.Join verwirft ein absolutes zweites Argument nicht so wie Python os.path.join. Die funktionierende Eingabe ist relatives ... Giteas localFileURL ist in diesem Tree nicht vorhanden.
Falsche Wege, die bereits festgehalten wurden: Ausbruch aus dem Dump-Root-Join über eine absolute DownloadURL; Live-Migration file:// LFI; X-Forgejo-Internal-Auth (Restore erfolgt per CLI als forgejo-UID, nicht über /api/internal); Restore-HTTP als remote unauth behandelt; eine Reverse Shell. Theater.
python3 forgejo-restore-file-open-Abraxas-Labs.py
oder:
cd lab
./run.sh
Ziel nur http://127.0.0.1:19340. Image codeberg.org/forgejo/forgejo:16.0.5. Witness 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
Zusammengefügte Pfade unter baseDir nach EvalSymlinks einschränken (Gitea PR 38215 localFileURL). .. ablehnen. Keine dump-seitigen Symlinks aus dem Dump heraus verfolgen. file:// aus uri.Open entfernen, außer bei einem dump-verankerten Helper.
restore.go · uri.goGNU Affero GPL v3.0. Siehe LICENSE. Nur Loopback-Lab. Keine Gewährleistung.