
Forgejo 16.0.5 - Alto - Remoto - Lettura di file - restore-repo segue file:// lato dump negli allegati
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-restore-file-open
Classe: Lettura di file Reach: Locale
Forgejo 16.0.5 (8d24b7d) - Forgejo
forgejo restore-repo di un dump non attendibile riscrive gli URL degli asset di release con filepath.Join(baseDir, download_url) grezzo e antepone file://. uri.Open esegue comunque os.Open su quel percorso. Un --units vuoto ripristina le release. Gitea 1.27.0 ha aggiunto localFileURL e ha saltato l'escaping delle voci. Quell'helper qui non c'è.
Il ripristino da parte dell'operatore di un dump non attendibile copia un file dell'host che l'uid forgejo può aprire in un allegato di release.
| ID | nessuna CVE al momento |
| Classe | Lettura di file |
| Reach | Locale (operatore forgejo restore-repo di un dump non attendibile) |
| CWE | CWE-22 / CWE-73 |
| CVSS | Alto: 7.3 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N |
| Prodotto | Forgejo |
| Affetto | fino alla v16.0.5 (8d24b7d); ripristino locale da parte dell'operatore |
| Auth | ripristino locale da parte dell'operatore di un dump non attendibile |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Consegnare all'operatore una directory di dump (o disporre già di INTERNAL_TOKEN e di un percorso che il server può leggere). Le unità includono releases / release_assets.
| Privilegio | Metodo / sink | Recon / integrità / disponibilità | Provato in lab o dedotto |
|---|---|---|---|
Leggere un file dell'host che l'uid forgejo può aprire, tramite .. fuori dal dump | release.yml download_url: ../FORGEJO-FILE-WITNESS.txt; il ripristino esegue il join, uri.Open esegue os.Open, i byte vengono memorizzati come witness.txt | Recon (riservatezza dei file dell'host) | Provato in lab. Il corpo dell'allegato è FORGEJO-RESTORE-FILE-OPEN-WITNESS. Il decoy nel dump INSIDE-DUMP-NOT-HOST non è stato servito |
| Stesso risultato con un symlink piantato dentro il dump | Il percorso risultante dal join resta sotto baseDir; os.Open segue il link | Recon | Dedotto da uri.Open file -> os.Open. Il lab ha usato .., non un symlink |
| Stesso sink sulle patch delle PR | pull_request.yml PatchURL viene riscritto allo stesso modo, poi uri.Open in repo/pulls/<n>.patch | Recon | Dedotto da restore.go GetPullRequests. Il lab ha ripristinato solo le release |
| I lettori del repo ripristinato scaricano il file dell'host | GET /<owner>/<repo>/releases/download/<tag>/<name> | Recon | Provato in lab come labadmin Basic sul repo pubblico ripristinato |
File tipici dell'host: app.ini, INTERNAL_TOKEN, SECRET_KEY, password del DB | l'uid forgejo può leggere l'albero di configurazione | Recon | Dedotto. Il witness del lab era un file piantato accanto al dump, non segreti reali |
Chiusi qui: LFI file:// live su POST /repos/migrate (DownloadFunc impostato; PatchURL delle PR verificato con prefisso rispetto alla base HTTP del clone). Escape dal join della radice del dump con DownloadURL assoluto (in Go filepath.Join("/dump", "/etc/passwd") resta /dump/etc/passwd). Ripristino HTTP non autenticato (solo CLI / token interno). Backup dump che impacchetta app.ini (segreti by design, modalità archivio 0600). Non è OS LPE. Non è LFI remoto.
Avevo due idee di ripristino. Ho prima ragionato mentalmente sul join assoluto di Gitea. In Go filepath.Join non scarta un secondo argomento assoluto come fa os.path.join di Python. L'input che funziona è il relativo ... Il localFileURL di Gitea non è in questo albero.
Vicoli ciechi già registrati: escape dal join della radice del dump tramite un DownloadURL assoluto; LFI file:// su migrate live; X-Forgejo-Internal-Auth (il ripristino è CLI come uid forgejo, non /api/internal); trattare il ripristino HTTP come remoto non autenticato; una reverse shell. Teatro.
python3 forgejo-restore-file-open-Abraxas-Labs.py
oppure:
cd lab
./run.sh
Target solo http://127.0.0.1:19340. Immagine 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
Contenere i percorsi risultanti dal join sotto baseDir dopo EvalSymlinks (Gitea PR 38215 localFileURL). Rifiutare ... Non seguire symlink lato dump fuori dal dump. Rimuovere file:// da uri.Open tranne che per un helper con radice nel dump.
restore.go · uri.goGNU Affero GPL v3.0. Vedi LICENSE. Solo lab su loopback. Nessuna garanzia.