Cybersecurity24 مايو 202610 min read

تأمين الحاويات و Kubernetes: قائمة فحص ميدانية عملية

معظم اختراقات Kubernetes ليست ثغرات zero day، بل إعدادات افتراضية لم يغيرها أحد. هذه قائمة الفحص التي نطبقها فعليا على clusters عملائنا.

بقلم Innovation T Team


معظم اختراقات Kubernetes لا تبدأ بثغرة zero day. تبدأ بحاوية تعمل بصلاحيات root، أو service account يحمل cluster-admin، أو لوحة تحكم عرضها أحدهم للإنترنت سنة 2023 ثم نسي أمرها. التقوية الأمنية (hardening) ليست منتجا تشتريه، بل مجموعة إعدادات افتراضية ترفض قبولها كما هي. ومع اندفاع الشركات في تونس والمنطقة نحو الرقمنة، من منصات التجارة الإلكترونية إلى تطبيقات الدفع والخدمات البنكية، أصبحت هذه هي القائمة التي نمر عليها بندا بندا كلما استلمنا cluster جديدا.

نموذج التهديد في فقرة واحدة

المهاجم الذي ينجح في الوصول إلى داخل حاوية يريد ثلاثة أشياء: تصعيد صلاحياته داخل الحاوية، أو الهروب إلى العقدة (node)، أو التحرك الجانبي عبر شبكة الـ cluster وواجهة Kubernetes API. كل ضابط أمني في هذا المقال موجود لقطع أحد هذه المسارات الثلاثة. وإن لم تستطع تحديد المسار الذي يقطعه ضابط معين، فالأرجح أنك لا تحتاجه بعد. هذا الإطار يبقي عمل التقوية صادقا مع نفسه، ويمنع الفرق من الغرق في بنود CIS benchmark التي لا تغير شيئا في النتائج الفعلية.

ابدأ من الصورة (image) لا من الـ cluster

أرخص الثغرات إصلاحا هي تلك التي لا تشحنها أصلا. نظافة الصور هي المكان الذي تؤتي فيه التقوية ثمارها أولا.

قلص سطح الهجوم

صورة node:20 الافتراضية تأتي محملة بمئات حزم نظام التشغيل، مع shell ومدير حزم، وعادة بمئات الثغرات المعروفة (CVEs) يوم الفحص. كل ملف تنفيذي في الصورة هو أداة إضافية بيد المهاجم بعد الاختراق. خياراتك، بترتيب تقريبي حسب الجهد:

  • النسخ المصغرة (-slim و -alpine): مكاسب سريعة، لكن مكتبة musl libc في Alpine تكسر أحيانا الاعتمادات الأصلية (native dependencies) وسلوك DNS بطرق خفية. اختبر جيدا قبل أن تلتزم.
  • Distroless (صور Google على gcr.io/distroless): لا shell ولا مدير حزم. تصحيح الأخطاء يمر عبر الحاويات المؤقتة (kubectl debug)، وهذا تغيير في أسلوب العمل يجب أن يتدرب عليه فريقك قبل وقوع الحادث، لا أثناءه.
  • صور مبنية على Chainguard أو Wolfi: يعاد بناؤها يوميا، وتكون عادة شبه خالية من CVEs المعروفة، مع SBOMs مرفقة. المقابل هو الارتباط بإيقاع بناء مزود خارجي، وتكاليف ترخيص في بعض الصور.

ابنِ على مراحل متعددة وشغل بدون root

سلسلة أدوات البناء لا مكان لها في صورة التشغيل. المترجمات (compilers) و npm و git و curl هي بالضبط ما يحتاجه أي reverse shell.

FROM golang:1.23 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app ./cmd/api

FROM gcr.io/distroless/static:nonroot
COPY --from=build /app /app
USER 65532:65532
ENTRYPOINT ["/app"]

الصورة النهائية هنا تحتوي ملفا تنفيذيا واحدا، بلا shell، وبمستخدم غير root. المهاجم الذي يستغل عملية التطبيق يجد نفسه في غرفة فارغة بلا أدوات.

افحص، ووقع، وثبت

الفحص بلا سياسة مجرد مسرحية. اربطه بالـ pipeline عبر بوابة حقيقية:

  • Trivy أو Grype في CI، مع إفشال البناء عند وجود ثغرات critical أو high قابلة للإصلاح. اسمح باستثناءات موثقة ومحددة المدة، لا بتجاهل صامت.
  • Cosign لتوقيع الصور وقت البناء، مع سياسة admission في الـ cluster ترفض الصور غير الموقعة. هذا يغلق ثغرة "أحدهم دفع صورة من حاسوبه الشخصي".
  • تثبيت الـ digest للصور الأساسية (FROM node@sha256:...) حتى تكون عمليات البناء قابلة لإعادة الإنتاج، ولا يتسلل tag مسموم.
  • توليد SBOM عبر Syft وتخزينه كأثر بناء (artifact)، حتى إذا وقع الحدث القادم على غرار Log4j تجيب عن سؤال "هل نحن معرضون؟" في دقائق، لا في أيام.

هذه مشكلة pipeline بقدر ما هي مشكلة أمنية. غطينا جانب CI بالتفصيل في دليلنا حول بناء pipeline DevSecOps.

أحكم إغلاق مواصفات الـ Pod

الإعدادات الافتراضية في Kubernetes مصممة لهدف "أن يعمل التطبيق"، لا "أن يكون آمنا". حقل securityContext في الـ Pod هو المكان الذي تصحح فيه ذلك، وبكلفة شبه معدومة وقت التشغيل.

securityContext:
  runAsNonRoot: true
  runAsUser: 10001
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  seccompProfile:
    type: RuntimeDefault
  capabilities:
    drop: ["ALL"]

ما يشتريه لك كل سطر فعليا:

  • runAsNonRoot مع UID ثابت: تقنيات الهروب من الحاوية التي تعتمد على root داخلها تتوقف عن العمل في أغلبها.
  • allowPrivilegeEscalation: false: يمنع ملفات setuid من رفع الصلاحيات، ما يقضي على صنف كامل من التصعيد المحلي.
  • readOnlyRootFilesystem: true: البرمجيات الخبيثة لا تستطيع كتابة حمولاتها على القرص. اربط emptyDir على /tmp للتطبيقات التي تحتاج مساحة عمل مؤقتة.
  • seccompProfile: RuntimeDefault: يرشح قرابة 60 من الـ syscalls غير الشائعة. كل عمليات الهروب من الحاويات على مستوى النواة (kernel) تقريبا في السنوات الأخيرة احتاجت syscall يحجبه هذا الملف.
  • إسقاط كل الـ capabilities عبر drop: ["ALL"]: أعد فقط ما تستطيع تبريره، وكن شديد الريبة من أي طلب لـ NET_ADMIN أو SYS_ADMIN. الـ Pod الذي يملك SYS_ADMIN أو privileged: true هو عمليا root على العقدة.

افرض كل ما سبق عبر Pod Security Admission على مستوى الـ namespace. ضع على كل namespace تطبيقي الوسم pod-security.kubernetes.io/enforce: restricted، وعامل الاستثناءات كتذاكر لها مالك وتاريخ انتهاء. من تجربتنا، تكشف هذه الهجرة عن حفنة من الأحمال القديمة التي تحتاج فعلا صلاحيات مرتفعة (وكلاء CNI، جامعو السجلات، تعريفات التخزين). اعزل تلك الأحمال في namespaces مخصصة بدل تخفيف السياسة على الجميع.

حاصر نطاق الضرر

افترض أن أحد الـ Pods سيخترق يوما ما. السؤال الحقيقي: ماذا يستطيع المهاجم الوصول إليه بعدها؟

RBAC: أقل الصلاحيات ولا شيء غيرها

النتيجة الأكثر تكرارا في مراجعاتنا للـ clusters، سواء لدى شركات ناشئة في تونس أو مؤسسات في الخليج: حسابات service accounts بصلاحيات لا يستطيع أحد تفسيرها. القواعد بسيطة ومملة:

  • لا تربط cluster-admin بأي حمل تشغيلي أبدا. ولا حتى أدوات النشر في CI.
  • حساب service account واحد لكل حمل، محصور في الـ namespace الخاص به، وبالأفعال (verbs) التي يستعملها فعلا.
  • فعل automountServiceAccountToken: false افتراضيا. أغلب الـ Pods التطبيقية لا تستدعي Kubernetes API أصلا، ومع ذلك يشحن كل واحد منها ببيانات اعتماد API صالحة مركبة في مسار معروف. ذلك الـ token هو أول ما يقرأه المهاجم.
  • دقق دوريا عبر kubectl auth can-i --list --as=system:serviceaccount:ns:name أو بأدوات مثل rbac-tool. الرموز العامة (wildcards) في الأفعال أو الموارد هي ملاحظات تدقيق، لا تسهيلات.

سياسات الشبكة: امنع افتراضيا ثم اسمح

خارج الصندوق، كل Pod يستطيع التحدث إلى كل Pod آخر عبر كل الـ namespaces. هذه الشبكة المسطحة هي السبب في أن اختراق واجهة أمامية واحدة يتحول إلى اختراق لقاعدة البيانات. ابدأ كل namespace بمنع افتراضي:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes: ["Ingress", "Egress"]

ثم اسمح بالتدفقات المحددة: الواجهة الأمامية إلى الـ API على المنفذ 8080، والـ API إلى Postgres على 5432، والجميع إلى DNS. سياسة الـ egress لا تقل أهمية عن الـ ingress، لأنها ما يحول "مهاجم داخل Pod" إلى "مهاجم داخل Pod لا يستطيع الوصول إلى خادم C2 الخاص به ولا إلى نقطة metadata السحابية". حجب وصول الـ Pods إلى 169.254.169.254 ما لم يحتجه الحمل فعلا أوقف مسارات حقيقية لسرقة بيانات الاعتماد السحابية. هذا هو مبدأ Zero Trust مطبقا على مستوى الـ Pod، والمنطق نفسه الذي فصلناه في شرح معمارية Zero Trust.

المقابل: سياسات الشبكة قاسية عند التصحيح حين يتعطل نشر لأن أحدهم نسي قاعدة egress الخاصة بـ DNS. وزع مكتبة سياسات مختبرة ضمن قوالب المنصة بدل أن تطلب من كل فريق كتابة سياساته بنفسه.

الأسرار (Secrets): كفى ادعاء أن Base64 تشفير

أسرار Kubernetes مرمزة بـ Base64، لا مشفرة، وأي شخص يملك صلاحية قراءة الأسرار في namespace يملك النص الصريح. الحد الأدنى المقبول:

  1. فعل التشفير أثناء السكون (encryption at rest) لـ etcd عبر مزود KMS. وفي الـ clusters المدارة: تحقق بنفسك، لا تفترض.
  2. فضل تركيب الأسرار كـ volumes على متغيرات البيئة. متغيرات البيئة تتسرب إلى crash dumps وإلى kubectl describe وإلى العمليات الفرعية.
  3. لأي شيء جدي، اسحب الأسرار من مدير خارجي (Vault أو AWS Secrets Manager أو GCP Secret Manager) عبر External Secrets Operator أو CSI driver، حتى لا يتطلب تدوير المفاتيح إعادة نشر كل شيء. وإذا كنت خاضعا لمتطلبات إقامة البيانات (data residency) لدى جهة تنظيمية في تونس أو الخليج، فاختيار مدير أسرار مستضاف في المنطقة المناسبة يسهل عليك الامتثال أيضا.
  4. أحكم صلاحيات RBAC على مورد الـ Secret نفسه. صلاحية get secrets على مستوى الـ cluster هي صلاحية مدير نطاق (domain admin) في ثوب متنكر.

قو حماية مستوى التحكم والعقد

على Kubernetes المدار (EKS و GKE و AKS)، وهو الخيار الغالب لدى شركات المنطقة سواء على مناطق الخليج السحابية أو على مزودين أوروبيين تعتمدهم كثير من الشركات التونسية، يملك المزود etcd وملفات API server التنفيذية، لكنك ما زلت تملك الإعدادات التي تصنع الفارق:

  • نقطة API خاصة (private endpoint)، أو على الأقل قوائم سماح CIDR صارمة. خوادم الـ API المكشوفة على الإنترنت تفحص آليا خلال دقائق من إنشائها.
  • تفعيل سجلات التدقيق (audit logs) وشحنها إلى مكان قابل للبحث. بدونها، ستعيد بناء تحركات المهاجم بعد الحادث من الذاكرة.
  • نظام تشغيل العقد: استعمل صورا مصغرة محسنة للحاويات (Bottlerocket أو COS أو Flatcar)، وأبق مجموعات العقد على إيقاع ترقية آلي، ولا تسمح أبدا بـ SSH إلى العقد كممارسة اعتيادية.
  • مواكبة الإصدارات: النسخ الفرعية من Kubernetes تخرج من الدعم خلال سنة تقريبا. الـ clusters المتأخرة بأكثر من نسختين فرعيتين تراكم ثغرات بلا ترقيع وجرف ترقية مرعبا. رقِ قليلا وباستمرار.

اكشف أثناء التشغيل، لأن الوقاية تفشل

كل ما سبق يخفض الاحتمال. الكشف أثناء التشغيل يتكفل بما تبقى. أدوات مثل Falco أو Tetragon تراقب الـ syscalls عبر eBPF وترصد سلوكا لا ينبغي أن يحدث أبدا في حمل مقوى: shell ينطلق داخل حاوية distroless، اتصال خارجي غير متوقع، عملية تقرأ token الخاص بالـ service account، أو كتابة في /etc/passwd.

جودة الإشارة هنا عالية على نحو غير معتاد، وتحديدا لأن التقوية أزالت الضجيج. إذا كانت صورتك بلا shell، فإن "تم تنفيذ shell" ليس درجة شذوذ إحصائية، بل حادث أمني. اربط هذه التنبيهات بمسار استجابة له مالك وكتيبات تشغيل (runbooks). تنبيه يسقط في مجموعة WhatsApp مزدحمة ثم يضيع بين الرسائل، كما نرى كثيرا لدى فرق المنطقة، ليس مسار استجابة. إن لم تكن هذه العضلة مبنية عندكم بعد، ابدأ من دليل الاستجابة للحوادث.

أنماط الفشل التي نراها باستمرار

  • تقوية تطبق على الخدمات الجديدة بينما يحتفظ الـ namespace القديم بـ privileged: true "مؤقتا"، منذ سنتين.
  • ماسح ثغرات في CI بعتبة فشل معطلة، ينتج تقارير لا يقرؤها أحد.
  • سياسات شبكة تنشر بدون قاعدة egress لـ DNS، فتكسر الإنتاج، ثم تلغى بالكامل بدل أن تصلح.
  • سياسات admission في وضع audit إلى الأبد لأن أحدا لم يجدول موعد التحول إلى الفرض.
  • أسرار "هاجرت إلى Vault" لكن أسرار Kubernetes القديمة لم تحذف قط، ما زالت مقروءة وما زالت صالحة.

النمط الجامع للخمسة: التعامل مع التقوية كمشروع له تاريخ نهاية بدل اعتبارها إعدادات افتراضية مفروضة. محركات السياسات (Kyverno، أو ValidatingAdmissionPolicy الأصلية مع CEL) وجدت لتجعل المسار الآمن هو المسار الوحيد.

قائمة الفحص الميدانية

مر عليها من الأعلى إلى الأسفل. كل بند إجابته نعم أو لا، و"تقريبا" تحسب لا.

  1. كل صور التشغيل مصغرة (distroless أو Chainguard أو slim) ومبنية على مراحل متعددة.
  2. الـ CI يفشل البناء عند ثغرات critical و high القابلة للإصلاح، مع استثناءات محددة المدة فقط.
  3. الصور موقعة بـ Cosign والـ cluster يرفض الصور غير الموقعة.
  4. الصور الأساسية مثبتة بالـ digest ويولد SBOM لكل عملية بناء.
  5. كل حمل يعمل بدون root مع allowPrivilegeEscalation: false وإسقاط الـ capabilities و seccomp بوضع RuntimeDefault ونظام ملفات جذري للقراءة فقط.
  6. Pod Security Admission يفرض restricted على كل الـ namespaces التطبيقية.
  7. لا service account لأي حمل يملك cluster-admin، والتركيب الآلي للـ token معطل افتراضيا.
  8. كل namespace فيه سياسات منع افتراضي للـ ingress والـ egress، بما في ذلك حجب نقطة الـ metadata.
  9. تشفير etcd أثناء السكون يعتمد KMS، والأسرار تعيش في مدير خارجي مع تدوير دوري.
  10. خادم الـ API خاص أو مقيد بـ CIDR، وسجلات التدقيق تشحن إلى تخزين قابل للبحث.
  11. العقد تعمل بنظام تشغيل محسن للحاويات مع ترقيع آلي، والـ cluster ضمن نسختين فرعيتين من الإصدار الحالي.
  12. الكشف أثناء التشغيل (Falco أو Tetragon) منشور والتنبيهات موجهة إلى عملية استجابة لها مالك.
  13. سياسات admission تفرض كل ما سبق حتى لا يحدث الانحراف في صمت.

إذا حققت اثني عشر بندا أو أكثر فأنت متقدم على الأغلبية الساحقة من الـ clusters التي نقيمها. وإذا كانت نتيجتك أقل من ثمانية فعامل الأمر كأولوية هذا الربع من السنة، لأن المهاجمين يؤتمتون اكتشاف هذه الثغرات بالذات.

كيف تساعدكم Innovation T

تصمم Innovation T المنصات المبنية على الحاويات وتبنيها وتقويها لشركات في أوروبا والخليج وشمال إفريقيا. ننفذ تقييمات أمنية للـ clusters وفق هذه القائمة بالضبط، ثم نقوم بالعمل غير اللامع: ترحيل الأحمال إلى pod security بوضع restricted، وكتابة مكتبة السياسات، وربط توقيع الصور بالـ CI، وترك فريقكم مع إعدادات افتراضية مفروضة بدل تقرير PDF يوضع على الرف.

إذا كان الـ cluster عندكم قد نما أسرع من حواجز الأمان حوله، اطلعوا على خدمات السحابة والأمن السيبراني أو تحدثوا إلى مهندسينا. سنخبركم بصراحة أي بنود هذه القائمة الثلاثة عشر هو الأهم لبيئتكم، وأيها يمكن أن ينتظر.

#أمن الحاويات#Kubernetes#التقوية الأمنية#DevSecOps

جاهز للبناء مع Innovation T؟

سواء كان الأمر يتعلق بالأمن أو النمو أو الهندسة، يمكن لفريقنا مساعدتك على تنفيذه بإتقان.