
RCE (Remote Code Execution، تنفيذ التعليمات البرمجية عن بُعد) هي ثغرة تسمح للمهاجم بتنفيذ تعليمات برمجية عشوائية داخل النظام أو التطبيق عن بُعد، وهي مطابقة لـ CWE-94: Improper Control of Generation of Code ('Code Injection').
PyTorch Lightning هي مكتبة تساعد على إدارة تدريب نماذج التعلم العميق القائمة على PyTorch بسهولة، وDeepDiff هي مكتبة تقارن بين كائنين من Python لتحليل الاختلافات.
CVE-2024-5452 هي ثغرة تحدث عند استخدام DeepDiff وLightning في وظائف تطبيق الويب المتعلقة بأوزان نماذج الذكاء الاصطناعي في Lightning، وتؤدي إلى RCE أثناء إلغاء التسلسل (Deserialization) من خلال التحقق الضعيف من الترويسات في DeepDiff وتلويث خصائص الدلتا (Delta).
من خلال هذا، سنستعرض مسار الكود الذي يؤدي إلى ثغرة تسمح للمهاجم بحقن كائنات عشوائية أو تنفيذ تعليمات برمجية عن بُعد (RCE)، وسنبحث عن الإجراءات المضادة لذلك.
يمكن للمهاجم استهداف إحدى نقاط نهاية DeepDiff في شيفرة تطبيق الويب في pytorch-lightning، وتحديدًا /api/v1/delta، عن طريق إرسال خصائص دلتا ملوثة.
سنستعرض مثالًا لفهم كيفية تلويث خصائص dunder في delta وما يؤدي إليه من إحداث ثغرة إلغاء تسلسل الكائنات.
الطلب الأول هو مثال هجوم العميل، إعداد التلويث -> التحقق الضعيف من الترويسات في /api/v1/delta في DeepDiff -> حفظ الحالة من خلال إعداد التلويث.
[الشكل 1] POC - هجوم نقطة النهاية (Endpoint)
[الشكل 2] POC - حقن الثغرة / محتوى إعداد التلويث الكامل
[الشكل 3] lightning/api/core/api.py / جزء منطق فحص الترويسات الضعيف
[الشكل 4] lightning/api/core/app.py / قسم الإعداد
[الشكل 5] lightning/api/core/app.py / قسم حفظ الإعداد
يقوم الطلب الأول بتجاوز التحقق من الترويسة في /api/v1/delta الموضح في [الشكل 3] عبر [الشكل 1]، ثم حقن إعدادات التلويث (دلتا) المعدلة كما في [الشكل 2]، ويحفظ الإعدادات من خلال [الشكل 4] و[الشكل 5].
الآن دعونا نرى كيف تعمل إعدادات الدلتا المعدلة هذه في الطلب الثاني.
[الشكل 6] lightning/api/core/app.py / تدفق المسار الأولي
يُظهر [الشكل 6] تدفق الطلب الثاني بعد إعداد الدلتا، عبر run_once() -> maybe_apply_change() -> _collect_deltas_from_ui_and_work_queues()
[الشكل 7] حالة تلويث isinstance
في [الشكل 7]، يتم تمرير فحص isinstance داخل _collect_deltas_from_ui_and_work_queues() باستخدام الإعداد الملوث (isinstance(delta, _DeltaRequest) == False)، وبالتالي يتجه الفرع إلى else.
[الشكل 8] حالة تلويث isinstance 1
في [الشكل 8]، ولتسهيل الفهم، يتم عرض نتائج isinstance(delta, _DeltaRequest) و delta و _DeltaRequest(النوع). الطلب الأول هو طلب إعداد، وهو طبيعي لأنه يتم إعداد التعديل؛ أما الطلب التالي فتم تلويث نوع _DeltaRequest إلى str، مما يتجاوز الشرط. الآن دعونا نلقي نظرة على مثال _process_requests، وهو الهدف التالي في التدفق.
[الشكل 9] حالة تلويث isinstance 2
كما نرى في [الشكل 9]، وبنفس ما سبق، نجح _process_requests في تجاوز فحص isinstance(request, _APIRequest) باستخدام الإعداد الملوث من كود POC للعميل على اليمين؛ هذا التلويث هو حالة يجعل استدعاء isinstance لسلسلة نصية (str) مقابل مثيل OrderSet يُرجع قيمة true. لقد رأينا حتى الآن نوعين من تلويث isinstance، وفي ما بعد سيتم إنشاء إعدادات تسمح باستدعاء الخصائص عبر التلويث.
[الشكل 10] حالة تلويث isinstance 3
بعد الانتهاء من تجاوز isinstance وإعداد الدوال في [الشكل 10]، يتم ضبط "تثبيت الحالة الداخلية" (_INTERNAL_STATE_VARS: ()) لتكون فارغة، مما يجعل من المستحيل التحقق من حالة الإعدادات الداخلية في [الشكل 11].
[الشكل 11_1] دالة فحص _INTERNAL_STATE_VARS في /lightning/app/core/flow.py
[الشكل 11_2] __setattr__ في /lightning/app/core/flow.py
بعد [الشكل 11]، اكتمل التلويث والإعداد الشامل.
[الشكل 12] أمر RCE
[الشكل 13] استجابة RCE
أخيرًا، في [الشكل 13]، يتم استدعاء exec بصلاحيات الجذر لتنفيذ الأمر من [الشكل 12] لإنهاء الهجوم.
لقد استعرضنا حتى الآن تدفق تنفيذ ثغرة RCE عبر إلغاء تسلسل الكائنات (CVE-2024-5452) في بيئة lightning. وبما أن طريقة الهجوم هذه تتمثل في الاستيلاء على الخادم نفسه، فإن الإجراءات المضادة مهمة. لذا نقدم تحديث الإصدار الأحدث.


لقد استعرضنا حتى الآن ثغرة تسبب RCE من خلال تلويث خصائص Dunder عبر Lightning وDeepDiff. هذه الثغرة تنشأ أولاً من التحقق الضعيف من الترويسات، ثم من فحص خصائص delta الضعيف في إلغاء تسلسل الكائنات.
(poc) https://security.snyk.io/vuln/SNYK-PYTHON-PYTORCHLIGHTNING-7218866
(nist) https://nvd.nist.gov/vuln/detail/CVE-2024-5452