تقريبا. العابرة. : تقديم ترجمة لمقال من قبل مهندس أمان تطبيق كبير في شركة ASOS.com البريطانية. معه ، يبدأ سلسلة من المنشورات حول تحسين الأمن في Kubernetes من خلال استخدام seccomp. إذا كان القراء سيحبون المقدمة ، فسوف نتابع المؤلف ونواصل نشر مقالاته المستقبلية حول هذا الموضوع.
هذا المقال هو الأول من سلسلة من المنشورات حول كيفية إنشاء ملفات تعريف seccomp بروح SecDevOps دون اللجوء إلى السحر والسحر. في الجزء الأول ، سأتحدث عن الأساسيات والتفاصيل الداخلية لتنفيذ seccomp في Kubernetes.
يوفر نظام Kubernetes البيئي مجموعة واسعة من الطرق لضمان سلامة الحاويات والعزل. تتناول هذه المقالة وضع الحوسبة الآمنة ، والمعروف أيضًا باسم
seccomp . يكمن جوهرها في دعوات نظام الترشيح المتاحة للحاويات للتنفيذ.
لماذا هذا مهم؟ الحاوية هي مجرد عملية تعمل على جهاز معين. ويستخدم النواة على قدم المساواة مع التطبيقات الأخرى. إذا تمكنت الحاويات من إجراء أي مكالمات للنظام ، فستستغل البرامج الضارة قريبًا جدًا لتجاوز عزل الحاوية والتأثير على التطبيقات الأخرى: اعتراض المعلومات ، وتغيير إعدادات النظام ، إلخ.
تحدد ملفات تعريف seccomp مكالمات النظام التي يجب السماح بها أو رفضها. يعمل وقت تشغيل الحاوية على تنشيطها أثناء إطلاقها ، بحيث تتمكن النواة من التحكم في تنفيذها. يتيح لك استخدام ملفات التعريف هذه الحد من ناقل الهجوم وتقليل الضرر إذا بدأ أي برنامج داخل الحاوية (أي تبعياتك أو تبعياتها) في القيام بما لا يسمح به.
فهم الأساسيات
يتضمن ملف تعريف seccomp الأساسي ثلاثة عناصر:
defaultAction
،
defaultAction
(أو
archMap
) ،
syscalls
:
{ "defaultAction": "SCMP_ACT_ERRNO", "architectures": [ "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32" ], "syscalls": [ { "names": [ "arch_prctl", "sched_yield", "futex", "write", "mmap", "exit_group", "madvise", "rt_sigprocmask", "getpid", "gettid", "tgkill", "rt_sigaction", "read", "getpgrp" ], "action": "SCMP_ACT_ALLOW" } ] }
( متوسطة أساسية- seccomp.json )defaultAction
يحدد المصير الافتراضي لأي مكالمة نظام غير محددة في قسم
syscalls
. لتبسيط المهمة ، نركز على قيمتين رئيسيتين سيتم استخدامهما:
SCMP_ACT_ERRNO
- يمنع تنفيذ مكالمة النظام ،SCMP_ACT_ALLOW
- يسمح.
يسرد قسم البنيات البنى المستهدفة. هذا مهم ، نظرًا لأن المرشح نفسه ، المطبق على مستوى kernel ، يعتمد على معرفات مكالمات النظام ، وليس على أسمائهم المسجلة في ملف التعريف. قبل الاستخدام ، يقوم وقت تشغيل الحاوية بتعيينها إلى معرفات. النقطة المهمة هي أن مكالمات النظام يمكن أن تحتوي على معرفات مختلفة تمامًا ، اعتمادًا على بنية النظام. على سبيل المثال ، استدعاء نظام
recvfrom
(المستخدم للحصول على معلومات من مأخذ توصيل) له معرّف = 64 على أنظمة x64 ومعرف = 517 على x86.
هنا يمكنك العثور على قائمة بجميع استدعاءات النظام لبنية x86-x64.
يسرد قسم
syscalls
جميع مكالمات النظام ويشير إلى ما يجب فعله بها. على سبيل المثال ، يمكنك إنشاء قائمة بيضاء عن طريق تعيين
defaultAction
على
SCMP_ACT_ERRNO
، وتعيين مكالمات إلى قسم
SCMP_ACT_ALLOW
إلى
SCMP_ACT_ALLOW
. وبالتالي ، لا تسمح إلا بالمكالمات المسجلة في قسم
syscalls
وتحظر جميع المكالمات الأخرى. للقائمة السوداء ، يجب عليك تغيير القيم والإجراءات
defaultAction
إلى عكس ذلك.
الآن يجب قول بضع كلمات عن الفروق الدقيقة التي ليست واضحة. يرجى ملاحظة أن التوصيات الواردة أدناه تأتي من حقيقة أنك تقوم بنشر مجموعة من تطبيقات الأعمال في Kubernetes ومن المهم بالنسبة لك أن تعمل بأقل الامتيازات.
1. AllowPrivilegeEscalation = خطأ
يحتوي
securityContext
الحاوية على معلمة
AllowPrivilegeEscalation
. إذا تم تعيينه على "
false
،
no_new_priv
بتنسيق
no_new_priv
على (
on
). يكون معنى هذه المعلمة واضحًا من الاسم: لا يسمح للحاوية ببدء عمليات جديدة بامتيازات أكبر من تلك التي لديها.
يتمثل أحد الآثار الجانبية لهذه المعلمة التي تم تعيينها على
true
(القيمة الافتراضية) في أن وقت تشغيل الحاوية يطبق ملف تعريف seccomp في بداية عملية بدء التشغيل. وبالتالي ، يجب السماح لجميع مكالمات النظام اللازمة لبدء العمليات الداخلية لوقت التشغيل (على سبيل المثال ، تعيين معرفات المستخدم / المجموعة ، وإسقاط بعض القدرات) في ملف التعريف.
ستحتاج الحاوية التي تقوم بتنفيذ
echo hi
العادي إلى الأذونات التالية:
{ "defaultAction": "SCMP_ACT_ERRNO", "architectures": [ "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32" ], "syscalls": [ { "names": [ "arch_prctl", "brk", "capget", "capset", "chdir", "close", "execve", "exit_group", "fstat", "fstatfs", "futex", "getdents64", "getppid", "lstat", "mprotect", "nanosleep", "newfstatat", "openat", "prctl", "read", "rt_sigaction", "statfs", "setgid", "setgroups", "setuid", "stat", "uname", "write" ], "action": "SCMP_ACT_ALLOW" } ] }
( مرحبًا ، seccomp.json )... بدلاً من هذه:
{ "defaultAction": "SCMP_ACT_ERRNO", "architectures": [ "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32" ], "syscalls": [ { "names": [ "arch_prctl", "brk", "close", "execve", "exit_group", "futex", "mprotect", "nanosleep", "stat", "write" ], "action": "SCMP_ACT_ALLOW" } ] }
( hi-container-seccomp.json )ولكن مرة أخرى ، لماذا هذه مشكلة؟ شخصيا ، أتجنب إدراج قائمة المكالمات التالية في النظام (إذا لم تكن هناك حاجة إليها بالفعل):
capset
،
set_tid_address
،
setgid
،
setgroups
و
setuid
. ومع ذلك ، فإن الصعوبة الحقيقية تكمن في أنه من خلال السماح للعمليات التي لا تتحكم فيها مطلقًا ، فإنك تربط الملفات الشخصية في تنفيذ وقت تشغيل الحاوية. بمعنى آخر ، قد تواجهك يومًا ما حقيقة أنه بعد تحديث بيئة وقت تشغيل الحاوية (بواسطتك ، أو على الأرجح من قِبل موفر الخدمة السحابية) ، ستتوقف الحاويات فجأة عن البدء.
نصيحة رقم 1 : تشغيل الحاويات باستخدام
AllowPrivilegeEscaltion=false
. سيؤدي ذلك إلى تقليل حجم ملفات تعريف seccomp وجعلها أقل حساسية للتغييرات في وقت تشغيل الحاوية.
2. إعداد ملفات تعريف حاوية المستوى
يمكن تعيين ملف تعريف seccomp على مستوى جراب:
annotations: seccomp.security.alpha.kubernetes.io/pod: "localhost/profile.json"
... أو على مستوى الحاوية:
annotations: container.security.alpha.kubernetes.io/<container-name>: "localhost/profile.json"
يرجى ملاحظة أن بناء الجملة أعلاه سوف يتغير عندما يصبح Sec Kompnet Kubernet GA (هذا الحدث متوقع في إصدار Kubernetes التالي - 1.18 تقريبًا. الترجمة.).قليل من الناس يعرفون أن Kubernetes كان لديه دائمًا
خطأ نظرًا لأنه تم تطبيق ملفات تعريف seccomp على
حاوية الإيقاف المؤقت . يعوض وقت التشغيل جزئياً عن هذا العيب ، لكن هذه الحاوية لا تختفي من القرون ، حيث يتم استخدامها لتكوين بنيتها الأساسية.
المشكلة هي أن هذه الحاوية تبدأ دائمًا بـ
AllowPrivilegeEscalation=true
، مما يؤدي إلى حدوث المشكلات
AllowPrivilegeEscalation=true
في الفقرة 1 ، ولا يمكن تغيير هذا.
عند تطبيق ملفات تعريف seccomp على مستوى الحاوية ، يمكنك تجنب هذا الفخ ويمكن إنشاء ملف تعريف "سيتم شحذه" لحاوية معينة. يجب القيام بذلك حتى يقوم المطورون بإصلاح الخلل وإتاحة الإصدار الجديد (ربما 1.18؟) للجميع.
نصيحة رقم 2 : تعيين ملفات تعريف seccomp على مستوى الحاوية.
بالمعنى العملي ، عادة ما تكون هذه القاعدة بمثابة إجابة شاملة على السؤال: "لماذا يعمل ملف تعريف seccomp الخاص بي مع
docker run
، لكنه لا يعمل بعد النشر في مجموعة Kubernetes؟"
3. استخدام وقت التشغيل / الافتراضي كحل أخير
لدى Kubernetes خياران لملفات التعريف المضمّنة:
runtime/default
الإعداد الافتراضي والإرساء
docker/default
. يتم تنفيذ كلاهما بواسطة وقت تشغيل الحاوية ، وليس Kubernetes. لذلك ، قد تختلف حسب وقت التشغيل المستخدم وإصداره.
بمعنى آخر ، نتيجة لتغيير وقت التشغيل ، يمكن للحاوية الوصول إلى مجموعة أخرى من مكالمات النظام التي يمكنها استخدامها أو عدم استخدامها. تستخدم معظم أوقات التشغيل
تطبيق Docker . إذا كنت تريد استخدام ملف التعريف هذا ، فتأكد من أنه يناسبك.
تم إهمال ملف التعريف الخاص بالإرساء
docker/default
منذ Kubernetes 1.11 ، لذا تجنب استخدامه.
في رأيي ، ملف تعريف
runtime/default
مثالي للغرض الذي تم إنشاؤه من أجله: لحماية المستخدمين من المخاطر المرتبطة
docker run
على أجهزتهم. ومع ذلك ، إذا تحدثنا عن تطبيقات الأعمال التي يتم تشغيلها في مجموعات Kubernetes ، فإنني أجرؤ على الادعاء بأن ملف التعريف هذا مفتوح للغاية وأن على المطورين التركيز على إنشاء ملفات تعريف لتطبيقاتهم (أو أنواع التطبيقات).
نصيحة رقم 3 : إنشاء ملفات تعريف seccomp لتطبيقات محددة. إذا لم يكن ذلك ممكنًا ، فقم بالتعامل مع ملفات التعريف لأنواع التطبيقات ، على سبيل المثال ، قم بإنشاء ملف تعريف متقدم يتضمن جميع واجهات برمجة تطبيقات Golang web application. فقط كملاذ أخير استخدم وقت التشغيل / الافتراضي.
في المنشورات المستقبلية ، سأخبرك بكيفية إنشاء ملفات تعريف secccomp بروح SecDevOps ، وأتمتة واختبارها في خطوط الأنابيب. بمعنى آخر ، لن يكون لديك أي مبرر لعدم التبديل إلى ملفات التعريف الخاصة بتطبيقات معينة.
4. غير محدود ليس خيارًا
من
أول تدقيق أمني لـ Kubernetes ، اتضح أنه
تم تعطيل seccomp بشكل افتراضي. هذا يعني أنه إذا لم تحدد
PodSecurityPolicy
شأنه أن يمكّنه في الكتلة ، فإن جميع القرون التي لم يتم تعريف ملف تعريف seccomp لها ستعمل في
seccomp=unconfined
.
يعني العمل في هذا الوضع فقدان طبقة كاملة من العزل ، مما يوفر حماية عنقودية. هذا النهج لا ينصح به متخصصو الأمن.
النصيحة رقم 4 : يجب ألا تعمل أي حاوية في كتلة في
seccomp=unconfined
، خاصة في بيئات الإنتاج.
5. "وضع التدقيق"
هذه النقطة ليست فريدة بالنسبة إلى Kubernetes ، لكنها لا تزال تندرج في فئة "ما يجب أن تعرفه قبل أن تبدأ".
لقد حدث أن إنشاء ملفات تعريف seccomp كان دائمًا عملًا صعبًا وكان يعتمد إلى حد كبير على التجربة والخطأ. والحقيقة هي أن المستخدمين ببساطة لا تتاح لهم الفرصة لاختبارها في بيئات الإنتاج دون المخاطرة "بإسقاط" التطبيق.
بعد ظهور kernel Linux 4.14 ، أصبح من الممكن تشغيل أجزاء من الملف الشخصي في وضع التدقيق ، وتسجيل المعلومات حول جميع مكالمات النظام في syslog ، ولكن ليس حظرها. يمكنك تنشيط هذا الوضع باستخدام المعلمة
SCMT_ACT_LOG
:
SCMP_ACT_LOG : لن يؤثر seccomp على تشغيل سلسلة الرسائل التي تجري مكالمة نظام إذا لم تقع ضمن أي قاعدة من عامل التصفية ، ولكن سيتم تسجيل معلومات حول استدعاء النظام.فيما يلي نموذج لاستراتيجية استخدام هذه الميزة:
- اسمح بمكالمات النظام المطلوبة.
- حظر أنظمة الاتصال المعروفة بأنها غير مفيدة.
- تسجيل المعلومات حول جميع المكالمات الأخرى في السجل.
مثال مبسط كالتالي:
{ "defaultAction": "SCMP_ACT_LOG", "architectures": [ "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32" ], "syscalls": [ { "names": [ "arch_prctl", "sched_yield", "futex", "write", "mmap", "exit_group", "madvise", "rt_sigprocmask", "getpid", "gettid", "tgkill", "rt_sigaction", "read", "getpgrp" ], "action": "SCMP_ACT_ALLOW" }, { "names": [ "add_key", "keyctl", "ptrace" ], "action": "SCMP_ACT_ERRNO" } ] }
( متوسطة مختلطة seccomp.json )لكن تذكر أنك بحاجة إلى حظر جميع المكالمات المعروفة بأنها غير مستخدمة والتي قد تضر الكتلة. أساس جيد للإدراج هو
وثائق Docker الرسمية. يشرح بالتفصيل أي مكالمات النظام تم حظرها في ملف التعريف الافتراضي ولماذا.
ومع ذلك ، هناك الصيد واحد. على الرغم من أن
SCMT_ACT_LOG
مدعومًا من قِبل Linux kernel منذ نهاية عام 2017 ، إلا أنه لم يدخل نظام Kubernetes إلا مؤخرًا. لذلك ، لاستخدام هذه الطريقة ، ستحتاج إلى إصدار Linux 4.14 kernel و runC لا يقل عن
v1.0.0-rc9 .
نصيحة رقم 5 : يمكنك إنشاء ملف تعريف وضع التدقيق للاختبار في الإنتاج من خلال الجمع بين القوائم بالأبيض والأسود ، وتسجيل جميع الاستثناءات.
6. استخدام القوائم البيضاء
يتطلب إنشاء قوائم بيضاء بذل جهود إضافية ، حيث يتعين عليك تحديد كل مكالمة قد يحتاج إليها التطبيق ، ولكن هذا الأسلوب يحسن الأمان بشكل كبير:
يوصى بشدة باستخدام نهج القائمة البيضاء لأنه أبسط وأكثر موثوقية. ستحتاج القائمة السوداء إلى تحديث كلما تمت إضافة اتصال نظام يحتمل أن يكون خطيرًا (أو علامة / خيار خطير إذا كانت موجودة في القائمة السوداء). بالإضافة إلى ذلك ، يمكنك غالبًا تغيير عرض المعلمة دون تغيير جوهرها وبالتالي التحايل على قيود القائمة السوداء.
بالنسبة لتطبيقات Go ، قمت بتطوير أداة خاصة ترافق التطبيق وتجمع جميع المكالمات التي تتم في وقت التشغيل. على سبيل المثال ، للتطبيق التالي:
package main import "fmt" func main() { fmt.Println("test") }
... تشغيل
gosystract
مثل هذا:
go install https://github.com/pjbgf/gosystract gosystract --template='{{- range . }}{{printf "\"%s\",\n" .Name}}{{- end}}' application-path
... واحصل على النتيجة التالية:
"sched_yield", "futex", "write", "mmap", "exit_group", "madvise", "rt_sigprocmask", "getpid", "gettid", "tgkill", "rt_sigaction", "read", "getpgrp", "arch_prctl",
هذا حتى الآن مجرد مثال - التفاصيل حول الأدوات ستكون أكثر.
النصيحة رقم 6 : السماح للمكالمات التي تحتاجها حقًا وحظرها على أي شخص آخر.
7. ضع الأساس (أو الاستعداد للسلوك غير المتوقع)
ستراقب النواة الامتثال للملف الشخصي بغض النظر عن ما قمت بتسجيله فيه. حتى لو لم يكن هذا ما أردت. على سبيل المثال ، إذا قمت بحظر الوصول إلى المكالمات مثل
exit
أو
exit_group
، فلن تتمكن الحاوية من إكمال المهمة بشكل صحيح وحتى أمر بسيط مثل
echo hi
سيعلقها لفترة غير محددة. نتيجة لذلك ، سوف تحصل على استخدام وحدة المعالجة المركزية عالية في الكتلة:

في مثل هذه الحالات ، قد تأتي الأداة المساعدة
strace
في عملية الإنقاذ - ستوضح المشكلة التي قد تكون:

sudo strace -c -p 9331
تأكد من أن ملفات التعريف تحتوي على جميع مكالمات النظام التي يحتاجها التطبيق أثناء تشغيله.
نصيحة رقم 7 : انتبه للأشياء الصغيرة وتأكد من أن جميع مكالمات النظام الضرورية مدرجة في القائمة البيضاء.
مع هذا ، ينتهي الجزء الأول من سلسلة من المقالات حول استخدام seccomp في Kubernetes بروح SecDevOps. في الأجزاء التالية سنتحدث عن سبب أهمية ذلك وكيفية أتمتة العملية.
PS من المترجم
اقرأ أيضًا في مدونتنا: