
PoC لـ CVE-2019-5736
PoC لـ CVE-2019-5736
تم الإنشاء بمساعدة من @singe، و@_cablethief، و@feexd
تم اختباره على Ubuntu 18.04 و Debian 9 و Arch Linux. إصدارات Docker 18.09.1-ce و 18.03.1-ce. لا يعمل هذا الـ PoC حالياً مع Ubuntu 16.04 و CentOS.
اطلع على كود الاستغلال من Dragon Sector (الأشخاص الذين اكتشفوا الثغرة) هنا.
إنه تطبيق بلغة Go لـ CVE-2019-5736، وهو هروب من الحاوية لـ Docker. يعمل الاستغلال عن طريق استبدال وتنفيذ ثنائي runc للنظام المضيف من داخل الحاوية.
هناك حالتا استخدام (2) للاستغلال. الأولى (وهي ما يمثله هذا المستودع) هي في الأساس فخ. سيحتاج المهاجم إلى تنفيذ أوامر داخل الحاوية وتشغيل برنامج ثنائي خبيث يستمع. عندما يستخدم شخص ما (مهاجم أو ضحية) docker exec للدخول إلى الحاوية، سيؤدي ذلك إلى تفعيل الاستغلال الذي سيسمح بتنفيذ الأكواد بصلاحيات الجذر.

أما الثانية (وهي ليست ما يمثله هذا المستودع) فتقوم بإنشاء صورة Docker خبيثة. عند تشغيل تلك الصورة، سيُفعل الاستغلال. لا حاجة لتنفيذ exec داخل الحاوية. انظر أسفل هذا الملف لمثال بصيغة gif.
لاستغلال هذه الثغرة، تحتاج إلى صلاحيات الجذر (uid 0) داخل الحاوية.
نعم، ستقوم باستبدال تطبيق runc الخاص بك مما سيجعل نظامك غير قادر على تشغيل حاويات Docker. يرجى عمل نسخة احتياطية إما من /usr/bin/docker-runc أو /usr/bin/runc (حسب ما لديك؛ تحقق أيضاً من /usr/sbin).
قم بتعديل الكود كما تراه مناسباً وقم بترجمته باستخدام go build main.go. انقل ذلك الثنائي إلى الحاوية التي تريد الهروب منها. قم بتنفيذ الثنائي، ثم في المرة التالية التي يتصل فيها شخص ما ويستدعي /bin/sh سيُفعل الحمولة الخاصة بك.
تم إنشاء هذا الـ PoC باستخدام شرح ممتاز من هذا الـ commit لمشروع lxc (بالإضافة إلى بعض النصائح المفيدة من الآخرين).
على سبيل المثال، إذا كان الثنائي المستهدف هو /bin/bash، فيمكن استبداله بنص برمجي قابل للتنفيذ يحدد مسار المفسر #!/proc/self/exe (/proc/self/exec هو رابط رمزي ينشئه النواة لكل عملية يشير إلى الثنائي الذي تم تنفيذه لتلك العملية). وبالتالي عند تنفيذ /bin/bash داخل الحاوية، سيتم بدلاً من ذلك تنفيذ هدف /proc/self/exe - والذي سيشير إلى ثنائي runc على المضيف.
نقوم بتنفيذ ذلك عن طريق استبدال /bin/sh في الحاوية بـ #!/proc/self/exe والذي سيشير إلى الثنائي الذي بدأ هذه العملية (Docker exec).

يمكن للمهاجم بعد ذلك متابعة الكتابة إلى هدف /proc/self/exe لمحاولة استبدال ثنائي runc على المضيف. لكن بشكل عام، لن ينجح ذلك لأن النواة لن تسمح باستبداله أثناء تنفيذ runC. لتجاوز ذلك، يمكن للمهاجم بدلاً من ذلك فتح واصف ملف إلى /proc/self/exe باستخدام علم O_PATH ثم متابعة إعادة فتح الثنائي بـ O_WRONLY عبر /proc/self/fd/ ومحاولة الكتابة إليه في حلقة مزدحمة من عملية منفصلة.
ملاحظة: بعض أجزاء القسم السابق ليست دقيقة تماماً. لا تحتاج إلى استخدام علم O_PATH عند الحصول على واصف الملف لـ runcinit. بالإضافة إلى ذلك، لا تحتاج إلى إنشاء حلقة الكتابة في عملية أخرى. نحصل على واصف ملف لـ runcinit عن طريق الحصول على مقبض ملف إلى /proc/PID/exe. من هناك، نستخدم هذا المقبض للحصول على مقبض ملف إلى /proc/self/fd/FILEDESCRIPTOR. هذا هو مقبض الملف الذي سنستخدمه للكتابة.

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