
Концептуальный эксплойт для CVE-2026-78122, демонстрирующий эксфильтрацию файловой системы контейнера и переменных окружения через грубые правила доступа docker-socket-proxy, а также исправленную конфигурацию HAProxy.
Tecnativa docker-socket-proxy ≤ 0.5.0 — Недостаточная гранулярность контроля доступа (CWE-1220)
CVSS 4.0: 8.3 (Высокий) — 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
Вектор атаки — соседняя сеть (
AV:A): атакующему требуется локальный/соседний сетевой доступ к прокси — именно поэтому его размещение вне любых маршрутизируемых интерфейсов является частью мер смягчения.
docker-socket-proxy — это HAProxy-фронтенд для Docker-сокета, всё
назначение которого — предоставлять ограниченный, минимально-привилегированный доступ к Docker API.
Канонический «безопасный, только для чтения» рецепт, который используют операторы:
CONTAINERS=1 # allow listing/inspecting containers
POST=0 # deny everything that mutates state
# every other flag left at its default (0)
Операторы обоснованно полагают, что это даёт метаданные контейнеров только для чтения. Это не так.
В haproxy.cfg
всё пространство имён /containers ограничено одним грубым правилом по префиксу:
http-request allow if { path,url_dec -m reg -i ^(/v[\d\.]+)?/containers } { env(CONTAINERS) -m bool }
Это регулярное выражение соответствует каждому GET-подпути внутри /containers, включая
чувствительные конечные точки чтения, которые никогда не должны были быть частью «списка контейнеров».
Поскольку все они используют GET, защита POST=0 не может их остановить:
Итоговый эффект: при «усиленной» конфигурации CONTAINERS=1, POST=0 любой, кто может
добраться до прокси, может выгрузить секреты и выкрасть полную файловую систему
каждого контейнера на хосте.
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
Требуются Docker + Docker Compose и POSIX-шелл (на Windows подойдёт Git Bash).
./verify.sh
Или по шагам:
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
Прокси привязан только к
127.0.0.1. Никогда не выставляйте прокси Docker-сокета на маршрутизируемый интерфейс.
[+] 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
Каждый пункт выше был получен при всё ещё действующем POST=0.
Настоящее исправление: обновитесь до исправленного релиза (отслеживается в
issue #182 /
PR #183) и перестаньте
полагаться на то, что один лишь CONTAINERS=1 даёт «только чтение».
Этот репозиторий также включает готовый усиленный конфиг
(mitigation/haproxy.patched.cfg), который добавляет
явные правила deny для опасных подпутей до общего разрешающего правила
/containers; каждое из них можно снова включить отдельным флагом
(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 }
Проверено до/после (вывод verify.sh) — та же конфигурация CONTAINERS=1, POST=0:
Легитимные операции list/inspect по-прежнему работают; примитивы эксфильтрации заблокированы.
С эксплуатационной точки зрения также: держите прокси вне любой маршрутизируемой сети, монтируйте docker-сокет в режиме только для чтения и применяйте минимальные привилегии (включайте только те флаги, которые нужны потребителю).
Только для авторизованного тестирования безопасности и обучения. Лаборатория полностью запускается на вашем собственном хосте с контейнерами, которые вы создали.
| Endpoint (GET) | Что утекает |
|---|
/containers/{id}/archive?path=… | Произвольное чтение файлов из любого контейнера |
/containers/{id}/export | Полная файловая система контейнера в виде tar |
/containers/{id}/logs | stdout/stderr контейнера |
/containers/{id}/top | Список процессов с полным argv (может содержать учётные данные) |
/containers/{id}/json | Полный конфиг, включая переменные окружения |
| GET endpoint | Уязвимый (:2375) | Исправленный (:2376) |
|---|
/containers/json (список) | 200 | 200 |
/containers/{id}/json (inspect) | 200 | 200 |
/containers/{id}/archive | 200 | 403 |
/containers/{id}/export | 200 | 403 |
/containers/{id}/logs | 200 | 403 |
/containers/{id}/top | 200 | 403 |