اكتشاف الثغرات الأمنية في مكتبات مفتوحة المصدر: تحليل CVE-2020-11863

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

في الجزء الأول من سلسلة المدونات هذه ، وصفنا بالتفصيل أهمية البحث مفتوح المصدر ، من خلال تحديد نقاط الضعف التي أبلغنا عنها في مكتبة libEMF. أبرزنا أيضًا أهمية تجميع الشفرة باستخدام معقمات الذاكرة وكيف يمكن أن تساعد في اكتشاف مجموعة متنوعة من أخطاء تلف الذاكرة. باختصار ، يعترض Address Sanitizer (ASAN) وظائف تخصيص / إلغاء تخصيص الذاكرة مثل malloc () / free () ويملأ الذاكرة ببايتات التعبئة الخاصة بها (malloc_fill_byte / free_fill_byte). كما أنه يراقب القراءة والكتابة في مواقع الذاكرة هذه ، مما يساعد على اكتشاف الوصول الخاطئ أثناء وقت التشغيل.

في هذه المدونة ، نقدم تحليلاً أكثر تفصيلاً لإحدى نقاط الضعف التي تم الإبلاغ عنها ، CVE-2020-11863 ، والتي كانت ناتجة عن استخدام ذاكرة غير مهيأة. ترتبط هذه الثغرة الأمنية بـ CVE-2020-11865 ، وهو ناقل كائن عالمي خارج حدود الوصول إلى الذاكرة في الوظيفة GlobalObject :: Find () في libEMF. ومع ذلك ، تبين أن مكدس مكالمات الأعطال مختلف ، ولهذا قررنا فحص هذا الأمر بشكل أكبر وإنتاج مدونة الغوص العميق هذه.

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

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

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

بالإشارة إلى وثائق Address Sanitizer ، اتضح أن ASAN يكتب 0xbe إلى الذاكرة المخصصة حديثًا بشكل افتراضي ، مما يعني بشكل أساسي أن قيمة 64 بت قد تمت كتابتها ولكن لم تتم تهيئة الذاكرة. تسمي ASAN هذا باسم malloc_fill_byte. كما أنه يفعل الشيء نفسه عن طريق ملء الذاكرة بـ free_fill_byte عندما يتم تحريرها. يساعد هذا في النهاية في تحديد أخطاء الوصول إلى الذاكرة.

يمكن أيضًا التحقق من طبيعة ASAN في مصدر libsanitizer هنا. يوجد أدناه مقتطف من ملف المصدر.

بالنظر إلى تتبع المكدس في نقطة التعطل كما هو موضح أدناه ، حدث العطل في وظيفة SelectObject (). هذا الجزء من الكود مسؤول عن معالجة بنية السجل EMR_SELECTOBJECT لملف Enhanced Meta File (EMF) ومقبض كائن الرسومات الذي تم تمريره إلى الوظيفة هو 0x80000018. نريد التحقيق في تدفق الكود للتحقق مما إذا كان هذا شيء يأتي مباشرة من ملف EMF المدخل ويمكن للمهاجم التحكم فيه.

في وظيفة SelectObject () ، أثناء معالجة بنية السجل EMR_SELECTOBJECT ، يتم تمرير المقبض إلى كائن GDI إلى GlobalObjects.find () كما هو موضح في مقتطف الشفرة أعلاه ، والذي بدوره يصل إلى العمومية كائن الأسهم المتجه عن طريق إخفاء البت ذي الترتيب الأعلى من مقبض كائن GDI وتحويله إلى الفهرس ، وفي النهاية يتم إرجاع مرجع كائن المخزون من متجه الكائن باستخدام رقم الفهرس المحول. يحدد تعداد كائن المخزون فهارس الكائنات الرسومية المنطقية المحددة مسبقًا والتي يمكن استخدامها في عمليات الرسومات الموثقة في وثائق MS. على سبيل المثال ، إذا كان مؤشر الكائن هو 0x8000018 ، فسيتم استخدام AND مع 0x7FFFFFFF ، مما ينتج عنه 0x18 ، والذي سيتم استخدامه كفهرس لمتجه كائن الأسهم العالمية. يتم بعد ذلك تحويل مرجع كائن المخزون هذا ديناميكيًا إلى كائن الرسومات ، وبعد ذلك وظيفة العضو EMF :: GRAPHICSOBJECT getType () يتم استدعاؤه لتحديد نوع الكائن الرسومي ، وبعد ذلك ، لاحقًا في هذه الوظيفة ، يتم تحويله مرة أخرى إلى كائن رسومي مناسب (BRUSH ، PEN ، FONT ، PALETTE ، EXTPEN) ، كما هو موضح في مقتطف الشفرة أدناه.

EMF :: GRAPHICSOBJECT هي الفئة المشتقة من EMF :: OBJECT ومخطط الوراثة لفئة EMF :: OBJECT كما هو موضح أدناه.

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

كما نلاحظ هنا ، ihObject هو عدد صحيح بدون إشارة مكون من 4 بايت يحدد فهرس تعداد كائن المخزون. في هذه الحالة ، يتم الاحتفاظ بمراجع كائن المخزون في متجه الكائنات العام. هنا ، يشير مؤشر الكائن 0x80000018 إلى أنه سيتم استخدام الفهرس 0x18 للوصول إلى متجه كائن الأسهم العالمية. إذا كان طول متجه الكائن ، خلال هذا الوقت ، أقل من 0x18 ولم يتم فحص الطول قبل الوصول إلى متجه الكائن ، فسيؤدي ذلك إلى الوصول إلى الذاكرة خارج الحدود.

يوجد أدناه التمثيل المرئي لمعالجة سجل ملف التعريف EMR_SELECTOBJECT.

أثناء تصحيح هذه المشكلة ، نقوم بتمكين نقطة توقف في GlobalObjects.find () والاستمرار حتى يكون لدينا مقبض الكائن 0x80000018 ؛ بشكل أساسي ، نصل إلى النقطة التي تتم فيها معالجة سجل EMR_SELECTOBJECT المميز أعلاه. كما هو موضح أدناه ، يتم تحويل مقبض الكائن إلى الفهرس (0x18 = 24) للوصول إلى متجه الكائن بالحجم (0x16 = 22) ، مما يؤدي إلى الوصول خارج الحدود ، والذي أبلغنا عنه باسم CVE-2020-11865.

مزيد من التقدم في الكود ، يدخل مكتبة STL vector stl_vector.h التي تنفذ التوسع الديناميكي لمتجهات الأمراض المنقولة جنسياً. نظرًا لأن متجه الكائنات في هذا الوقت يحتوي على 22 عنصرًا فقط ، فإن متجه STL سوف يوسع المتجه إلى الحجم المشار إليه بواسطة المعلمة المميزة ، والوصول إلى المتجه بواسطة الفهرس الذي تم تمريره ، وسيعيد القيمة عند مرجع الكائن هذا ، كما هو موضح في مقتطف الشفرة أدناه ، والذي سيظهر ليكون 0xbebebebebebebee كما تم ملؤه بواسطة ASAN.

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

كما هو مذكور في مدونتنا السابقة ، تم إصدار إصلاحات المكتبة في إصدار لاحق ، متاح هنا.

خاتمة

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

قد يعجبك ايضا