
PoC pubblico e rilevatore per CVE-2026-20896 ("Gitea Docker: Un Header, Qualsiasi Utente")
L'immagine Docker ufficiale di Gitea (fino alla 1.26.2 inclusa) include
REVERSE_PROXY_TRUSTED_PROXIES = * nella sua configurazione predefinita. Se attivi
il login tramite reverse proxy, quel carattere jolly fa sì che ogni IP sorgente venga trattato come un proxy
affidabile, quindi chiunque possa raggiungere la porta può inviare un header X-WEBAUTH-USER e
accedere come chi vuole. Niente password, niente token.
L'ho segnalato a Gitea ed è stato corretto nelle versioni 1.26.3 / 1.26.4. Questa repo è la mia analisi personale, un PoC funzionante e uno strumento di verifica. Riguarda un bug pubblico e già corretto.
Gitea supporta l'autenticazione tramite reverse proxy: lo metti dietro un proxy che imposta
X-WEBAUTH-USER e Gitea si fida di quell'header per il nome utente. Va bene finché
solo il tuo proxy può impostarlo. L'impostazione che dovrebbe garantirlo
è REVERSE_PROXY_TRUSTED_PROXIES, una lista consentita di IP. Gitea onora l'header solo
quando l'IP sorgente della richiesta rientra in quella lista.
Il default documentato come sicuro, quello in app.example.ini, è
127.0.0.0/8,::1/128: solo loopback, quindi di default si fida solo del proxy
locale. L'immagine Docker ufficiale non lo usa. Il suo template app.ini
codifica direttamente * (docker/root/etc/templates/app.ini:55, e
docker/rootless/etc/templates/app.ini:52 per l'immagine rootless). * corrisponde a
ogni IP sorgente, quindi il controllo della lista consentita non fa nulla. Attiva il login tramite reverse proxy
e ora chiunque possa raggiungere la porta può inviare l'header, non solo il tuo proxy.
Con l'auto-registrazione attiva, l'account viene creato al volo. Invia il nome utente di un amministratore
e sei l'amministratore.
Quindi il codice non è sbagliato: lo è il default incluso, ed è specifico delle immagini
Docker. Un'installazione binaria o compilata manualmente che segue app.example.ini mantiene il
default loopback e non è vulnerabile.
Richiede Docker e Python 3 (solo libreria standard, niente da installare).
docker compose up -d # boots vulnerable gitea/gitea:1.26.2
# give it ~30-60s to finish first-run setup, then:
python3 poc.py # random new victim, shows auto-registration
python3 poc.py http://localhost:3000 admin # impersonate a chosen username
docker compose down -v # clean up
Ecco cosa succede con l'immagine inclusa:
1) /user/settings with no header -> HTTP 303 (redirect to login = not authed)
2) /user/settings with X-WEBAUTH-USER -> HTTP 200
logged in as 'pocadmin' - no password, no token, any source IP
3) /pocadmin profile page -> HTTP 200 (account created on the fly)
Il bypass funziona sulla sessione web, non sull'API token /api/v1/..., che
ignora l'header.
detect.py invia una sonda innocua e la confronta con una richiesta normale. Non
tocca nulla.
python3 detect.py https://gitea.example.com
Stampa VULNERABLE, looks-safe o inconclusive. Eseguilo solo contro qualcosa di cui sei proprietario o che sei autorizzato a testare.
Aggiorna alla 1.26.3 / 1.26.4 o successiva. L'autenticazione tramite reverse proxy ora è opt-in e
l'immagine non include più il carattere jolly. Se non puoi ancora aggiornare, imposta
REVERSE_PROXY_TRUSTED_PROXIES sull'IP o CIDR effettivo del tuo proxy (mai *), oppure
disattiva ENABLE_REVERSE_PROXY_AUTHENTICATION se non lo usi.
Ho trovato questo bug e l'ho segnalato a Gitea il 2026-05-26. Sono il segnalatore citato nell'advisory di Gitea, GHSA-f75j-4cw6-rmx4.
Alcuni articoli hanno accreditato la repo Exploitarium per questo invece che a me. È sbagliato, ed è una cosa diversa da ciò che quella repo ha pubblicato. Nel frattempo ho fatto correggere diversi di quei blog; alcuni sono ancora sbagliati.
Con licenza MIT. Vedi LICENSE.