Proof-of-concept e lab per un IDOR di Gitea (CWE-639) in GET /api/v1/user/keys/{id}, che consente a un token autenticato read:user di enumerare le chiavi SSH e deploy di altri utenti.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitea-user-keys-idor
Gitea 1.27.3 - Gitea
GET /api/v1/user/keys/{id} si trova nel gruppo dell'utente corrente (reqToken, rejectPublicOnly). Il gestore carica comunque la riga tramite ID numerico senza alcun controllo del proprietario. La stessa tabella contiene chiavi utente, deploy key e principal. La controparte GPG lo fa correttamente: GetGPGKeyForUserByID(ctx, ctx.Doer.ID, id). I campi privati sono protetti. Il materiale della chiave pubblica, il titolo e l'impronta 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. La registrazione aperta rende tutto ciò un bug da nuovo account.
| ID | nessuna CVE al momento |
| 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 | Gitea |
| Affetto | fino alla v1.27.3 (146cc3e) |
| Auth | autenticato (token read:user) |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Registrarsi (registrazione aperta predefinita), generare un token read:user, scorrere /api/v1/user/keys/{id}. Ottiene titoli, impronte e materiale di chiavi pubbliche per chiavi che non possiede, incluse le deploy key. Non ottiene la chiave privata. Non ottiene una shell. Inventaria chi ha accesso a cosa.
La GHSA delle chiavi della 1.27.3 era una lista con ambito username più individualPermsChecker. Non era questa ricerca.
Stesso tag, residuo: git HTTP redirect SSRF.
La v1.27.3 ha chiuso l'ondata di GHSA del 2026. Mi sono comunque soffermato su quel tag e ho letto il gestore delle chiavi dell'utente corrente accanto a quello GPG. GPG restituisce 404 per un id estraneo. SSH no.
seed.sh inserisce il titolo della chiave della vittima GHSA-GITEA-KEY-IDOR-WITNESS e una chiave dell'attaccante. La lista dell'attaccante non contiene il witness. GET /user/keys/1 come attaccante sì. GPG con un id estraneo restituisce 404. Questo è l'intero argomento.
Vicoli ciechi già registrati: trattare la lista dell'attaccante stesso come la fuga (non lo è - la lista è con ambito, il GET-by-id no); una reverse shell. Teatro.
I bug del client sembrano bug del prodotto. Un helper che fa shadowing di http.client non invia mai un pacchetto. .recv() su un HTTPResponse non è .read(). Lo menziono una volta perché è costato tempo e per un minuto è sembrato che la 1.27.3 avesse completato il lavoro.
cd lab
./run.sh
Target solo http://127.0.0.1:18101.
add-key user=victim status=201 title=GHSA-GITEA-KEY-IDOR-WITNESS id=1
add-key user=attacker status=201 id=2
attacker-list status=200 ids=[2] (no witness)
get id=1 status=200 snippet contains GHSA-GITEA-KEY-IDOR-WITNESS
SUCCESS Gitea #1 user/keys IDOR
404 a meno che key.OwnerID == ctx.Doer.ID (o amministratore del sito). Rifiutare i tipi deploy/principal. Allinearsi a GPG.
GetPublicKeyGNU Affero GPL v3.0. Vedi LICENSE. Solo lab su loopback. Nessuna garanzia.