
Forgejo 16.0.5 - Alta - Remota - IDOR - GET /api/v1/user/keys/{id} restituisce le chiavi SSH e deploy di altri utenti
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · forgejo-keys-idor
Classe: IDOR Portata: Remota
Forgejo 16.0.5 (8d24b7d) - Forgejo
GET /api/v1/user/keys/{id} si trova nel gruppo dell'utente corrente (reqToken, scope utente). L'handler carica comunque public_key tramite ID numerico senza alcun controllo del proprietario. La stessa tabella contiene chiavi utente, deploy key e principal. GPG su questa versione lo fa correttamente: GetGPGKeyForUserByID(ctx, ctx.Doer().ID, id). I campi extra privati sono protetti. Il materiale della chiave pubblica, il titolo e il fingerprint non lo sono. Gli ID sono sequenziali.
Un token read:user scorre 1, 2, 3 e inventaria le chiavi SSH e deploy di altre persone.
| ID | nessuna CVE al momento |
| Classe | IDOR |
| Portata | Remota (autenticato read:user / sessione) |
| CWE | CWE-639 |
| CVSS | Alto: 7.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| Prodotto | Forgejo |
| Affetto | fino alla v16.0.5 (8d24b7d) |
| Auth | autenticato (token read:user o sessione) |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Registrare o usare qualsiasi account, generare un token read:user (o usare un cookie di sessione), scorrere /api/v1/user/keys/{id}. Ottiene titoli, fingerprint e materiale della chiave pubblica per chiavi che non possiede. Non ottiene la chiave privata. Non ottiene una shell. Inventaria chi ha accesso a cosa.
| Privilegio | Metodo / sink | Recon / integrità / disponibilità | Provato in lab o dedotto |
|---|---|---|---|
| Leggere titolo, fingerprint e materiale della chiave pubblica SSH di un altro utente | GET /api/v1/user/keys/{id} come proprietario estraneo | Recon (riservatezza dell'inventario delle chiavi pubbliche) | Provato in lab. Titolo witness FORGEJO-KEYS-IDOR-WITNESS su id 1; la lista dell'attaccante contiene solo id 2 |
| Inventariare le deploy key allo stesso modo | Stesso handler, righe KeyTypeDeploy in public_key (OwnerID 0) | Recon | Dedotto dalla tabella. Il lab ha piazzato una chiave SSH utente, non una deploy key |
| Leggere i principal dei certificati SSH | Stesso handler, righe KeyTypePrincipal. ListPublicKeys esclude questo tipo | Recon | Dedotto dalla tabella |
| Vedere chiavi che appartengono a utenti limitati o privati | Nessun controllo di visibilità su questa lookup | Recon | Dedotto dall'handler |
JSON extra (user, key_type, read_only) | appendPrivateInformation solo se admin o proprietario | Recon | Provato in lab chiuso: la risposta per non-proprietario non aveva il campo user |
Chiusi su questa route: materiale della chiave privata, una shell, GET /users/{username}/keys (lista pubblica con scope per username), GPG GET /api/v1/user/gpg_keys/{id} (404 su un id estraneo), DeletePublicKey (403 per proprietario/admin). Cross-repo GET /repos/{owner}/{repo}/keys/{id} restituisce 404 quando RepoID non corrisponde.
Le patch di sicurezza della v16.0.5 (#14370) erano RCE via git-apply e CSRF su OpenID. Non hanno chiuso questa lookup. Stessa classe di gitea-user-keys-idor, indipendentemente ancora aperta qui.
Ho fissato Forgejo v16.0.5 dopo l'ondata del 2026-09. Gitea 1.27.3 aveva ancora questa lookup. Forgejo si è diversificato, quindi ho riletto l'handler delle chiavi dell'utente corrente accanto a GPG invece di copiare il pacchetto Gitea. GPG restituisce 404 su un id estraneo. SSH no.
Vicoli ciechi già registrati: trattare la lista dell'attaccante stesso come la fuga (non lo è - la lista ha scope, il GET-by-id no); trattare DISABLE_REGISTRATION=true sull'installer come una chiusura (qualsiasi account esistente è sufficiente); una reverse shell. Teatro.
python3 forgejo-keys-idor-Abraxas-Labs.py
oppure:
cd lab
./run.sh
Target solo http://127.0.0.1:19310. Immagine codeberg.org/forgejo/forgejo:16.0.5. Due account. Witness FORGEJO-KEYS-IDOR-WITNESS.
IOC planted victim-id=1 attacker-id=2
IOC attacker-list status=200 ... title=attacker-own-key
IOC get id=1 status=200 ... FORGEJO-KEYS-IDOR-WITNESS
IOC gpg-neg id=1 status=404
SUCCESS forgejo-keys-idor victim-id=1 get-http=200 list-has-id=no gpg-http=404 FORGEJO-KEYS-IDOR-WITNESS
404 a meno che key.OwnerID == ctx.Doer().ID (o site admin). Rifiutare KeyTypeDeploy / KeyTypePrincipal su questa route. Allinearsi a GetGPGKeyForUserByID.
GetPublicKeyGNU Affero GPL v3.0. Vedi LICENSE. Solo lab su loopback. Nessuna garanzia.