
Forgejo 16.0.5 - Alta - Remota - Lectura de archivos - restore-repo sigue file:// del lado del volcado hacia los adjuntos
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-restore-file-open
Write-up: https://abraxaslabs.tech/research/forgejo-restore-file-open
Clase: Lectura de archivos Alcance: Local
Forgejo 16.0.5 (8d24b7d) - Forgejo
forgejo restore-repo de un volcado no confiable reescribe las URL de los recursos de las releases con filepath.Join(baseDir, download_url) en crudo y les antepone file://. uri.Open sigue haciendo os.Open sobre esa ruta. Un --units vacío restaura las releases. Gitea 1.27.0 añadió localFileURL y omitió el escapado de entradas. Ese helper no está aquí.
La restauración por parte del operador de un volcado no confiable copia un archivo del host que el uid de forgejo puede abrir dentro de un adjunto de release.
| ID | aún sin CVE |
| Clase | Lectura de archivos |
| Alcance | Local (forgejo restore-repo del operador sobre un volcado no confiable) |
| 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 |
| Producto | Forgejo |
| Afectado | hasta v16.0.5 (8d24b7d); restauración local por el operador |
| Autenticación | restauración local por el operador de un volcado no confiable |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1 |
Entregar al operador un directorio de volcado (o disponer ya de INTERNAL_TOKEN y una ruta que el servidor pueda leer). Las unidades incluyen releases / release_assets.
| Privilegio | Método / sink | Reconocimiento / integridad / disponibilidad | Demostrado en laboratorio o inferido |
|---|---|---|---|
Leer un archivo del host que el uid de forgejo puede abrir, mediante .. fuera del volcado | release.yml download_url: ../FORGEJO-FILE-WITNESS.txt; la restauración une las rutas, uri.Open hace os.Open, los bytes se almacenan como witness.txt | Reconocimiento (confidencialidad de archivos del host) | Demostrado en laboratorio. El cuerpo del adjunto es FORGEJO-RESTORE-FILE-OPEN-WITNESS. El señuelo dentro del volcado INSIDE-DUMP-NOT-HOST no fue servido |
| Mismo resultado con un enlace simbólico plantado dentro del volcado | La ruta unida permanece bajo baseDir; os.Open sigue el enlace | Reconocimiento | Inferido de uri.Open file -> os.Open. El laboratorio usó .., no un enlace simbólico |
| Mismo sink en los parches de PR | pull_request.yml PatchURL se reescribe de la misma forma, y luego uri.Open hacia repo/pulls/<n>.patch | Reconocimiento | Inferido de restore.go GetPullRequests. El laboratorio solo restauró releases |
| Los lectores del repositorio restaurado descargan el archivo del host | GET /<owner>/<repo>/releases/download/<tag>/<name> | Reconocimiento | Demostrado en laboratorio como labadmin Basic sobre el repositorio público restaurado |
Archivos típicos del host: app.ini, INTERNAL_TOKEN, SECRET_KEY, contraseña de la BD | el uid de forgejo puede leer el árbol de configuración | Reconocimiento | Inferido. El testigo del laboratorio era un archivo plantado junto al volcado, no secretos reales |
Descartado aquí: LFI file:// en vivo vía POST /repos/migrate (DownloadFunc establecido; PatchURL de PR verificado por prefijo contra la base HTTP del clon). Escape de la unión con la raíz del volcado mediante DownloadURL absoluto (en Go filepath.Join("/dump", "/etc/passwd") permanece /dump/etc/passwd). Restauración HTTP sin autenticación (solo CLI / token interno). Empaquetado de app.ini en el dump de respaldo (secretos por diseño, modo de archivo 0600). No es LPE del SO. No es LFI remoto.
Tenía dos ideas de restauración. Primero probé mentalmente la unión absoluta de Gitea. filepath.Join de Go no descarta un segundo argumento absoluto como lo hace os.path.join de Python. La entrada que funciona es .. relativo. El localFileURL de Gitea no está en este árbol.
Ya se han registrado giros erróneos: escape de unión de raíz de volcado mediante un DownloadURL absoluto; LFI de file:// en migración en vivo; X-Forgejo-Internal-Auth (la restauración es CLI como el uid de forgejo, no /api/internal); tratar la restauración HTTP como remota sin autenticación; una reverse shell. Teatro.
python3 forgejo-restore-file-open-Abraxas-Labs.py
o:
cd lab
./run.sh
Dirígete solo a http://127.0.0.1:19340. Imagen codeberg.org/forgejo/forgejo:16.0.5. Testigo 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
Contener las rutas unidas bajo baseDir después de EvalSymlinks (Gitea PR 38215 localFileURL). Rechazar ... No seguir enlaces simbólicos del lado del volcado fuera del volcado. Eliminar file:// de uri.Open excepto un helper con raíz en el volcado.
restore.go · uri.goGNU Affero GPL v3.0. Véase LICENSE. Solo para laboratorio en loopback. Sin garantía.