
Laboratorio proof-of-concept che dimostra un SSRF autenticato nella allow-list dell'hostmatcher di Gitea, dove un webhook verso http://0.0.0.1 raggiunge servizi loopback che 127.0.0.1 non può raggiungere.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · gitea-hostmatcher-0000-ssrf
Gitea 1.27.3 - Gitea
CVE-2026-22874 ha aggiunto reservedIPNets. CGNAT, TEST-NET, NAT64, Teredo, Azure WireServer. Range reali. Non RFC 6890 0.0.0.0/8, il vecchio blocco "this network". IANA lo pubblica ancora. Go IsGlobalUnicast è true per 0.0.0.1. Non è IsLoopback (127.0.0.0/8). Non è IsPrivate. La allow-list esterna predefinita lo tratta come internet pubblico. Linux consegnerà 0.0.0.1 a un socket locale se quell'indirizzo è su lo. Stesso listener, due nomi.
Un utente autenticato può inviare un webhook a http://0.0.0.1 e leggere il corpo HTTP dalla cronologia degli hook. 127.0.0.1 sulla stessa porta viene negato.
| ID | nessun CVE al momento |
| CWE | CWE-918 |
| CVSS | High: 7.7 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N |
| Prodotto | Gitea |
| Affetto | fino alla v1.27.3 (146cc3e); residuo di CVE-2026-22874 |
| Auth | utente autenticato che può creare un webhook di repository |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Registrarsi (registrazione aperta predefinita), creare un repository, puntare un webhook a http://0.0.0.1:<local-port>/, testarlo e leggere il corpo della risposta dalla cronologia degli hook. Si tratta di HTTP su loopback che 127.0.0.1 sulla stessa porta non riesce a raggiungere: qualsiasi cosa in ascolto nel netns di Gitea che si sia associata in modo più ampio del loopback, inclusi servizi che l'operatore riteneva "solo localhost" perché bloccavano 127.0.0.0/8.
Non imposta X-Gitea-Internal-Auth. Non è RCE di per sé. È un corpo HTTP completo da un indirizzo che la allow-list continua a chiamare esterno.
La v1.27.3 è la build che ha chiuso l'ondata di GHSA del 2026. Mi sono comunque soffermato su quel tag. Le patch che aggiungono una allow-list o una deny-list sono un regalo: leggi la lista, poi ti chiedi cosa IANA ha ancora che la lista ha dimenticato. Due residui avevano già dei lab su questo albero (keys IDOR e git-redirect SSRF). La tabella dei residui in quel post elencava un webhook a http://0.0.0.1/ come mappa. Questo è il SUCCESS.
La consegna del webhook memorizza il corpo HTTP nella cronologia degli hook. È un oracolo migliore del git clone, che è per lo più "il fetch ha funzionato". Ho messo un oracolo nel netns di Gitea sulla porta 8080, ho aggiunto 0.0.0.1/8 su lo con NET_ADMIN e ho creato due webhook. Prima il controllo negativo.
Vicoli ciechi già registrati: trattare l'HTTP 201 di creazione webhook come oracolo (la cronologia è l'oracolo); la consegna a 127.0.0.1 che riesce (sarebbe un bug diverso - il lab richiede che venga negata); colpire /api/internal con X-Gitea-Internal-Auth; una reverse shell. Teatro. Il testimone è GITEA-0000-SSRF nella cronologia degli hook.
cd lab
./run.sh
Target solo http://127.0.0.1:18131. L'oracolo condivide il netns di Gitea sulla porta 8080. run.sh aggiunge 0.0.0.1/8 su lo.
create-hook name=neg-loopback status=201
negative-control 127.0.0.1 blocked
create-hook name=hit-0000 status=201
poll id=2 witness=True
SUCCESS GITEA-HOSTMATCHER-0000
Aggiungere 0.0.0.0/8 a reservedIPNets, oppure smettere di trattare IsGlobalUnicast come "sicuro da contattare". 0.0.0.1 deve essere negato allo stesso modo di 127.0.0.1.
hostmatcher.goGNU Affero GPL v3.0. Vedi LICENSE. Solo lab su loopback. Nessuna garanzia.