لماذا لا تعمل العمليات في حاويات Docker كجذر

نشرت: 2022-08-19

رسم يظهر شعار Docker

لا ينبغي تشغيل العمليات في حاوية Docker كجذر. يعد تشغيل تطبيقاتك أكثر أمانًا كمستخدم غير جذر تحدده كجزء من Dockerfile الخاص بك أو عند استخدام docker docker run . هذا يقلل من المخاطر من خلال تقديم سطح هجوم منخفض لأي تهديدات في الحاوية الخاصة بك.

في هذه المقالة ، ستتعرف على مخاطر تشغيل التطبيقات ذات الحاويات كجذر. سترى أيضًا كيفية إنشاء مستخدم غير جذر وإعداد مسافات الأسماء في المواقف التي لا يكون فيها ذلك ممكنًا.

لماذا يعتبر الجري كجذر خطير؟

يتم تشغيل الحاويات كجذر افتراضيًا. يتم تنفيذ Docker daemon كجذر على مضيفك وستكون الحاويات قيد التشغيل أيضًا.

على الرغم من أنه قد يبدو أن الجذر داخل الحاوية هو مستخدم مستقل ، إلا أنه في الواقع يشبه حساب الجذر على مضيفك. يتم توفير الفصل فقط من خلال آليات عزل حاوية Docker. ليس هناك حدود جسدية قوية. الحاوية الخاصة بك هي عملية أخرى يديرها المستخدم الجذر على نواة مضيفك. هذا يعني أن وجود ثغرة أمنية في تطبيقك ، أو وقت تشغيل Docker ، أو Linux kernel قد يسمح للمهاجمين بالخروج من الحاوية وتنفيذ عمليات بامتياز الجذر على جهازك.

هناك بعض وسائل الحماية المضمنة التي تقلل من خطر حدوث ذلك. الجذر داخل الحاوية ليس له امتيازات ولديه قدرات مقيدة. هذا يمنع الحاوية من استخدام أوامر إدارة النظام ما لم تضيف إمكانيات يدويًا أو تستخدم الوضع المميز عند بدء تشغيل الحاويات الخاصة بك.

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

تشغيل التطبيقات ذات الحاوية كمستخدم غير جذر

من أفضل الممارسات أن يتم تشغيل التطبيقات المعبأة في حاويات كمستخدم عادي. لا تحتاج معظم البرامج إلى الوصول إلى الجذر ، لذا فإن تغيير المستخدم يوفر طبقة دفاع فورية ضد اختراق الحاوية.

يجب عليك إنشاء حساب مستخدم جديد كواحدة من المراحل النهائية في Dockerfile الخاص بك. يمكنك تحقيق ذلك من خلال تعليمات USER :

 من الصورة الأساسية: الأحدث
تشغيل apt install demo-package
المستخدم التجريبي للمستخدم: المجموعة التجريبية
ENTRYPOINT ["عرض ثنائي"]

سيتم تشغيل الحاويات التي بدأت من هذه الصورة كمستخدم demo-user . سيكون المستخدم عضوًا في demo-group . يمكنك حذف اسم المجموعة إذا لم تكن بحاجة إلى أن يكون المستخدم في مجموعة:

 مستخدم تجريبي للمستخدم

يمكنك تحديد معرف المستخدم (UID) ومعرف المجموعة (GID) بدلاً من الأسماء:

 المستخدم 950: 950

عادةً ما يكون تخصيص معرّف UID و GID معروفين هو الطريقة الأكثر أمانًا للمتابعة. يمنع المستخدم في الحاوية من التعيين إلى حساب مضيف ذي امتيازات زائدة.

غالبًا ما يتم تحديد USER كمرحلة ما قبل الأخيرة في Dockerfile. هذا يعني أنه لا يزال بإمكانك تشغيل العمليات التي تتطلب الجذر في وقت سابق في بناء الصورة. تعليمات apt install في المثال أعلاه لها حاجة مشروعة إلى الجذر. إذا تم وضع تعليمات USER فوقها ، فسيتم تشغيل apt كمستخدم demo-user والذي قد يفتقر إلى الأذونات اللازمة. نظرًا لأن إرشادات Dockerfile تنطبق فقط على إنشاءات الصور ، وليس الحاويات قيد التشغيل ، فمن الآمن ترك تغيير المستخدم حتى وقت لاحق في Dockerfile الخاص بك.

قد يتطلب تغيير المستخدم الذي تشغله الحاوية منك تحديث الأذونات على الملفات والمجلدات التي تصل إليها. عيّن الملكية على أي مسارات سيستخدمها تطبيقك:

 نسخ الأولي config.yaml /data/config.yaml

المستخدم التجريبي للمستخدم: المجموعة التجريبية
RUN chown demo-user: المجموعة التجريبية / البيانات

في هذا المثال ، يجب أن يكون الدليل /data مملوكًا demo-user حتى يتمكن التطبيق من إجراء تغييرات على ملف التكوين الخاص به. ستكون عبارة COPY السابقة قد نسخت الملف كجذر. يتوفر الاختصار باستخدام العلامة --chown مع copy :

 نسخة - chown = demo-user: demo-group initial-config.yaml /data/config.yaml

تغيير المستخدم عند بدء تشغيل الحاوية

بينما يمكنك بسهولة تغيير المستخدم في Dockerfiles الخاصة بك ، فإن العديد من تطبيقات الطرف الثالث تستمر في العمل كجذر. يمكنك تقليل المخاطر المرتبطة باستخدام هذه عن طريق تعيين علامة --user في كل مرة تقوم فيها باستدعاء docker docker run . هذا يتجاوز المستخدم الذي تم تعيينه في ملف Docker الخاص بالصورة.

 $ docker run -d --user demo-user: demo-group demo-image: الأحدث
$ docker run -d --user demo-user demo-image: الأحدث
$ docker run -d --user 950: 950 صورة توضيحية: الأحدث

تقوم علامة --user بتشغيل عملية الحاوية كمستخدم محدد. إنه أقل أمانًا من تعليمات Dockerfile USER لأنه يتعين عليك تطبيقه بشكل فردي على كل أمر docker run . الخيار الأفضل للصور المستخدمة بانتظام هو إنشاء صورة مشتقة خاصة بك يمكنها تعيين حساب مستخدم جديد:

 من الصورة التي تعمل كجذر: الأحدث
مستخدم تجريبي للمستخدم
 بناء عامل ميناء. -t الصورة-التي-الآن-تعمل- كجذر: الأحدث

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

معالجة التطبيقات التي يجب أن تعمل كجذر

تعد مساحة أسماء المستخدمين تقنية للتعامل مع التطبيقات التي تحتاج إلى بعض امتيازات الجذر. يتيح لك تعيين جذر داخل حاوية إلى مستخدم غير جذر على مضيفك. يمتلك الجذر المحاكي داخل الحاوية الامتيازات التي يحتاجها ولكن الاختراق لن يوفر وصولاً إلى الجذر للمضيف.

يتم تنشيط إعادة تعيين مساحة الاسم عن طريق إضافة حقل userns-remap إلى ملف /etc/docker/daemon.json الخاص بك:

 {
    "userns-remap": "افتراضي"
}

يؤدي استخدام الإعداد default كقيمة لـ userns-remap إلى توجيه Docker لإنشاء مستخدم جديد تلقائيًا على مضيفك يسمى dockremap . سيتم إعادة تعيين الجذر داخل الحاويات إلى dockremap على مضيفك. يمكنك اختياريًا تحديد مستخدم ومجموعة حاليين بدلاً من ذلك ، باستخدام UID / GID أو تركيبة اسم المستخدم / المجموعة:

 {
    "userns-remap": "demo-user"
}

أعد تشغيل Docker daemon بعد تطبيق التغيير:

 sudo service docker إعادة تشغيل

إذا كنت تستخدم nsuser-remap: default ، يجب أن يكون مستخدم dockremap موجودًا الآن على مضيفك:

 $ id dockremap

uid = 140 (dockremap) gid = 119 (dockremap) مجموعات = 119 (dockremap)

يجب أن يظهر المستخدم أيضًا في /etc/subuid و /etc/subgid :

 خريطة dockremap $: 231500: 65535

تم تخصيص نطاق من 65.535 معرفًا فرعيًا للمستخدم بدءًا من 231500. ضمن مساحة اسم المستخدم ، تم تعيين المعرف 231500 إلى 0 ، مما يجعله المستخدم الأساسي في الحاويات الخاصة بك. نظرًا لكونه رقمًا تعريفيًا عاليًا ، فإن 231500 ليس له امتيازات على المضيف ، لذا لن تتمكن هجمات اختراق الحاوية من إلحاق الكثير من الضرر.

سيتم تشغيل جميع الحاويات التي تبدأها باستخدام مساحة اسم المستخدم المعاد تعيينها ما لم تقم بإلغاء الاشتراك باستخدام docker run --userns=host . تعمل الآلية من خلال إنشاء أدلة بمساحة اسم داخل /var/lib/docker مملوكة من قبل UID و GID التابعين للمستخدم ذي مساحة الاسم:

 $ sudo ls -l /var/lib/docker/231500.231500

إجمالي 14
drwx ------ 5 231500 231500 13 يوليو 22 19:00 aufs
drwx ------ 3 231500 231500 13 يوليو 22 19:00 حاويات
...

تعد مسافة أسماء المستخدمين طريقة فعالة لزيادة عزل الحاوية ، وتجنب الاختراقات ، والحفاظ على التوافق مع التطبيقات التي تحتاج إلى امتيازات الجذر. على الرغم من ذلك ، هناك بعض المفاضلات: تعمل الميزة بشكل أفضل على مثيل Docker جديد ، ويجب تعديل أذونات وحدات التخزين التي يتم تحميلها من المضيف ، ولا تدعم بعض برامج تشغيل التخزين الخارجية تعيين المستخدم على الإطلاق. يجب عليك مراجعة الوثائق قبل اعتماد هذا الخيار.

ملخص

يعد تشغيل التطبيقات المعبأة في حاويات كجذر مخاطرة أمنية. على الرغم من سهولة التغاضي عنه ، إلا أن العزلة التي توفرها الحاويات ليست قوية بما يكفي لفصل مستخدمي النواة تمامًا عن مستخدمي الحاويات. الجذر في الحاوية هو نفسه الجذر على مضيفك ، لذا فإن التسوية الناجحة يمكن أن توفر التحكم في جهازك.

بصفتك مؤلف صورة ، يجب عليك تضمين تعليمات USER في Dockerfile الخاص بك حتى يتم تشغيل التطبيق الخاص بك بدون جذر. يمكن لمستخدمي الصورة تجاوز هذا باستخدام docker run --user لتعيين UID و GID معين. يساعد هذا في التخفيف من الحالات التي تستخدم فيها الصورة الجذر عادةً.

يمكنك زيادة تشديد الأمان عن طريق إسقاط جميع الإمكانات من الحاوية باستخدام --cap-drop=ALL ، ثم إدراج تلك المطلوبة في القائمة البيضاء مع --cap-add flags. سيؤدي الجمع بين هذه الأساليب إلى تشغيل تطبيقك كمستخدم غير جذر مع الحد الأدنى من مجموعة الامتيازات التي يحتاجها ، مما يؤدي إلى تحسين وضع الأمان لديك.