
PoC per CVE-2026-44848: autorizzazione mancante di Portainer sugli endpoint dei plugin Docker -> RCE sull'host (GHSA-rrmm-9v76-h3p4). Python basato solo sulla libreria standard.
Prova di concetto per CVE-2026-44848, una vulnerabilità di autenticazione mancante (CWE-862) in Portainer che consente a un utente non amministratore con accesso all'endpoint Docker di eseguire operazioni privilegiate sui plugin Docker → RCE completa sull'host.
GitHub Security Advisory: GHSA-rrmm-9v76-h3p4 · CVSS 9.4 (Critica).
Portainer applica il controllo degli accessi basato sui ruoli (RBAC) sopra l'API Docker, inoltrando le richieste attraverso handler per-risorsa che eseguono controlli di autorizzazione. Gli endpoint di gestione dei plugin Docker (/plugins/*) non erano registrati con un handler, quindi il livello di autorizzazione non viene mai eseguito per essi. Di conseguenza, un Utente Standard (Ruolo 2) — o qualsiasi ruolo con accesso a livello di endpoint — può chiamare operazioni privilegiate sui plugin direttamente contro il daemon Docker sottostante:
POST /plugins/pull — scarica un plugin arbitrario da qualsiasi registryCAP_SYS_ADMIN e mount di percorsi dell'hostPOST /plugins/{name}/enable — Docker esegue il plugin come root sull'host con tali capacità → accesso completo al filesystem dell'host ed equivalente a root sull'host Docker>= 2.33.0, < 2.33.8>= 2.39.0, < 2.39.2>= 2.40.0, < 2.41.0Il nucleo della vulnerabilità, riproducibile in sicurezza: un utente standard (non amministratore) può raggiungere l'API Docker privilegiata /plugins/* attraverso il proxy di Portainer senza autorizzazione. Lo fa end-to-end contro una reale istanza vulnerabile di Portainer:
POST /api/users/admin/init (tollera il 409 e ripiega sul login).bob, Ruolo 2), tollerando il 409 azzerando la sua password.POST /api/endpoints se non ne esistono) e concede a bob l'accesso tramite PUT /api/endpoints/{id} UserAccessPolicies.bob (l'utente non amministratore) e chiama GET /api/endpoints/1/docker/plugins con il token di bob.# Defaults: https://localhost:9444, random admin password
python3 portainer_plugin_poc.py
# Explicit target + admin password + command
python3 portainer_plugin_poc.py --url https://localhost:9444 --admin-pass 'P@ssw0rd!' --command "id; hostname"
# Write a JSON summary
python3 portainer_plugin_poc.py --url https://localhost:9444 --output out.json
python3 portainer_plugin_poc.py --help
Richiede solo la libreria standard di Python 3. La verifica TLS è disabilitata (certificati autofirmati di laboratorio).
docker run -d --name portainer-lab-cve44848 \
-p 127.0.0.1:9444:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
portainer/portainer-ce:2.39.1 # vulnerable
AUTH-BYPASS CONFIRMED: standard user reached /plugins (HTTP 200)
=> PASS (missing auth / host-RCE primitive confirmed)
Solo per ricerca e test di sicurezza autorizzati. Il passo abilitante (POST /plugins/*) può concedere i privilegi di root sull'host; questo PoC si limita a dimostrare il bypass dell'autorizzazione e non abilita plugin distruttivi o dannosi. Utilizzare solo contro sistemi di cui si è proprietari o per i quali si è autorizzati a eseguire test.