في الوقت الحالي ، هناك طريقتان رئيسيتان للبحث عن نقاط الضعف في التطبيقات - التحليل الثابت والديناميكي. كلا النهجين لهما إيجابيات وسلبيات. توصل السوق إلى استنتاج مفاده أنه يجب استخدام كلا النهجين - يحلان مشكلات مختلفة قليلاً بنتائج مختلفة. ومع ذلك ، في بعض الحالات ، يكون استخدام التحليل الثابت محدودًا - على سبيل المثال ، عندما لا يكون هناك كود مصدر. في هذه المقالة ، سنتحدث عن تقنية نادرة إلى حد ما ولكنها مفيدة جدًا تتيح لك الجمع بين مزايا الأساليب الثابتة والديناميكية - التحليل الثابت للرمز القابل للتنفيذ.
دعنا نذهب من بعيدوفقًا لشركة McAfee antivirus ، بلغت الأضرار العالمية الناجمة عن جرائم الإنترنت في عام 2017 حوالي 600 مليار دولار ، أي ما يعادل 0.8٪ من الناتج المحلي الإجمالي العالمي. نحن نعيش في عصر تكنولوجيا المعلومات ، والتي خصصت للتكامل السريع للشبكة العالمية وتقنيات الإنترنت في جميع مجالات النشاط البشري. الآن جرائم الإنترنت لم تعد خارجة عن المألوف. تظهر
الإحصاءات زيادة في جرائم الإنترنت أضعافا مضاعفة.
تحولت مشكلة عدم حصانة التطبيقات إلى مشكلة خطيرة: وفقًا لوزارة الأمن الداخلي الأمريكية ، يتم تنفيذ أكثر من 90٪ من الهجمات الإلكترونية الناجحة باستخدام نقاط الضعف المختلفة في التطبيقات. أشهر طرق استغلال الثغرات الأمنية هي:
- حقن SQL
- تجاوز سعة المخزن المؤقت
- البرمجة النصية crossite
- باستخدام تكوين غير آمن.
تحليل البرمجيات (البرمجيات) لوجود قدرات غير معلنة (NDV) ونقاط الضعف هي التكنولوجيا الرئيسية لضمان أمان التطبيق.
الحديث عن التقنيات الكلاسيكية الراسخة لتحليل نقاط الضعف و NDV (من أجل الامتثال لمتطلبات أمن المعلومات) ، يمكننا التمييز بين:
- تحليل الكود الثابت (اختبار أمان التطبيق الثابت) ؛
- تحليل الشفرة الديناميكية (اختبار أمان التطبيق الديناميكي).
هناك IAST (تحليل تفاعلي) ، ومع ذلك ، فإنه ديناميكي بشكل أساسي (في عملية التحليل ، هناك وكيل إضافي يلاحظ ما يحدث أثناء تنفيذ التطبيق). يعد RASP (الدفاع عن تطبيق وقت التشغيل) ، والذي يتم ذكره أيضًا في بعض الأحيان في عدد من أدوات التحليل ، أداة حماية على الأرجح.
التحليل الديناميكي (طريقة "الصندوق الأسود") هو فحص البرنامج أثناء تنفيذه. المزايا التالية يمكن تمييزها عن هذا النهج.
- نظرًا لوجود ثغرات أمنية في البرنامج القابل للتنفيذ ، والكشف عن الخطأ باستخدام التشغيل الخاص به ، فإن إنشاء إيجابيات كاذبة أقل من التحليل الثابت.
- ليس هناك حاجة إلى شفرة المصدر لإجراء التحليل.
ولكن هناك أيضا عيوب.
- تغطية غير كاملة من التعليمات البرمجية ، وبالتالي هناك مخاطر فقدان الثغرات الأمنية. على سبيل المثال ، لا يمكن للتحليل الديناميكي العثور على نقاط الضعف المرتبطة باستخدام تشفير ضعيف أو إشارات مرجعية مثل "قنبلة مؤقتة".
- الحاجة إلى تشغيل التطبيق ، والذي في بعض الحالات يمكن أن يكون صعبا. قد يتطلب تشغيل التطبيق تكوينًا وتكوينًا معقدًا للتكاملات المختلفة. علاوة على ذلك ، لكي تكون النتائج دقيقة قدر الإمكان ، من الضروري إعادة إنتاج "بيئة القتال" ، ولكن تحقيق ذلك تمامًا دون الإضرار بالبرنامج أمر صعب.
التحليل الثابت (طريقة "المربع الأبيض") هو نوع من اختبار البرنامج الذي لا ينفذ فيه البرنامج.
نحن قائمة الفوائد.
- تغطية كاملة للرمز ، مما يؤدي إلى البحث عن المزيد من نقاط الضعف.
- لا يوجد اعتماد على البيئة التي سيتم فيها تنفيذ البرنامج.
- القدرة على تنفيذ الاختبار في المراحل الأولى من كتابة التعليمات البرمجية لوحدة نمطية أو برنامج في حالة عدم وجود ملفات قابلة للتنفيذ. يتيح لك ذلك بالفعل دمج حل مماثل بمرونة في دورة حياة تطوير برمجيات تطوير دورة حياة دورة تطوير البرامج (SDLC) في بداية التطوير.
العيب الوحيد للطريقة هو وجود إيجابيات كاذبة: الحاجة إلى تقييم ما إذا كان المحلل يشير إلى خطأ حقيقي ، أم أنه من المحتمل أن يكون هذا كاذبًا.
كما نرى ، كلتا الطريقتين من التحليل لها مزايا وعيوب. ومع ذلك ، هل من الممكن بأي شكل من الأشكال استخدام مزايا هذه الأساليب ، مع التقليل من العيوب؟ نعم ، إذا قمت بتطبيق التحليل الثنائي - البحث عن نقاط الضعف في الملفات القابلة للتنفيذ عن طريق التحليل الثابت.
تحليل ثنائي أو تقنية تحليل الملفات القابلة للتنفيذ
يسمح التحليل الثنائي بالتحليل الثابت بدون شفرة المصدر ، على سبيل المثال ، في حالة مقاولي الطرف الثالث. علاوة على ذلك ، ستكون تغطية الشفرة كاملة ، على عكس تطبيق طريقة التحليل الديناميكي. باستخدام التحليل الثنائي ، يمكنك التحقق من مكتبات الجهات الخارجية المستخدمة في عملية التطوير التي لا يوجد بها كود مصدر. أيضًا ، باستخدام التحليل الثنائي ، يمكنك إجراء فحص تحكم للإصدار ، ومقارنة نتائج تحليل الشفرة المصدرية من المستودع والرمز القابل للتنفيذ من الخادم القتالي.
في عملية التحليل الثنائي ، يتم تحويل الصورة الثنائية إلى تمثيل وسيط (تمثيل داخلي أو نموذج رمز) لمزيد من التحليل. بعد ذلك ، يتم تطبيق خوارزميات التحليل الثابت على التمثيل الداخلي. نتيجة لذلك ، يُستكمل النموذج الحالي بالمعلومات اللازمة لمزيد من الكشف عن نقاط الضعف و NDV. في المرحلة التالية ، وتطبيق قواعد للبحث عن نقاط الضعف و NDV.
لقد كتبنا المزيد عن مخطط التحليل الثابت
في مقال سابق . على عكس تحليل شفرة المصدر ، والذي يستخدم عناصر نظرية التجميع (التحليل المعجمي والنحوي) لبناء النموذج ، يستخدم التحليل الثنائي نظرية الترجمة العكسي - التفكيك ، إزالة التجميع ، إلغاء التجميع - لبناء النموذج.
قليلا عن الشروط
نحن نتحدث عن تحليل الملفات القابلة للتنفيذ التي لا تحتوي على معلومات التصحيح. مع معلومات التصحيح ، تكون المهمة مبسطة إلى حد كبير ، ولكن إذا كان هناك معلومات تصحيح ، فمن المرجح أن تكون شفرة المصدر هي المهمة وتصبح المهمة غير ذات صلة.
في هذه المقالة ، نسمي تحليل Java bytecode أيضًا التحليل الثنائي ، على الرغم من أن هذا ليس صحيحًا تمامًا. نحن نفعل هذا لتبسيط النص. بطبيعة الحال ، فإن مهمة تحليل كود JVM bytecode أبسط من تحليل كود C / C ++ الثنائي والهدف- C / Swift. لكن مخطط التحليل العام مشابه في حالة الكود الثنائي والرمز الثنائي. تتعلق الصعوبات الرئيسية الموضحة في المقالة بالتحديد بتحليل الشفرة الثنائية.
إلغاء ترجمة هو عملية استرداد التعليمات البرمجية المصدر من التعليمات البرمجية الثنائية. يمكنك التحدث عن عناصر الترجمة العكسية - تفكيك (الحصول على رمز المجمّع من صورة ثنائية) ، وترجمة المجمّع إلى رمز مكون من ثلاثة عناوين أو تمثيل آخر ، واستعادة إنشاءات مستوى شفرة المصدر.
التعتيم - التحويلات التي تحافظ على وظيفة الكود المصدري ، ولكنها تجعل من الصعب فك وفهم الصورة الثنائية الناتجة. Deobfuscation هو التحول العكسي. يمكن تطبيق التعتيم على مستوى الكود المصدر وعلى مستوى الكود الثنائي.
كيف تشاهد النتائج؟
دعنا نبدأ قليلاً من النهاية ، ولكن عادةً ما يتم طرح سؤال عرض نتائج التحليل الثنائي أولاً.
من المهم بالنسبة للمتخصص الذي يقوم بتحليل الشفرة الثنائية تعيين نقاط الضعف و NDV إلى شفرة المصدر. للقيام بذلك ، في المرحلة النهائية ، تبدأ عملية إلغاء التشويش (فك الارتباط) في حالة تطبيق تحويلات مربكة ، وتم فك الشفرة الثنائية إلى المصدر. بمعنى ، يمكن إظهار نقاط الضعف على التعليمات البرمجية decompiled.
في عملية إزالة التجميع ، حتى لو قمنا بفك تشفير رمز JVM ، فإن بعض المعلومات لا تتم استعادتها بشكل صحيح ، لذلك يتم التحليل نفسه على تمثيل قريب من الكود الثنائي. وفقًا لذلك ، فإن السؤال الذي يطرح نفسه: كيف ، العثور على نقاط الضعف في التعليمات البرمجية الثنائية ، توطينها في المصدر؟ تم وصف حل مشكلة كود JVM bytecode
في مقالتنا حول البحث عن نقاط الضعف في Java bytecode . حل الرمز الثنائي مشابه ، أي سؤال فني.
دعنا نكرر التحذير المهم - نحن نتحدث عن تحليل الشفرة الثنائية بدون معلومات التصحيح. في وجود معلومات التصحيح ، يتم تبسيط المهمة إلى حد كبير.
والسؤال الرئيسي الذي نطرحه حول عرض النتائج هو ما إذا كان الكود الذي تم فك شفرةه كافيًا لفهم مشكلة عدم الحصانة وتحديد مكانها.
فيما يلي بعض الأفكار حول هذا الموضوع.
- إذا كنا نتحدث عن رمز JVM bytecode ، فالجواب عمومًا هو "نعم" - جودة فك الشفرة لرمز الشفرة البيني رائعة. دائما تقريبا يمكنك معرفة ما هو الضعف.
- ما يمكن أن يتداخل مع التعريب النوعي للثغرة الأمنية هو تشويش بسيط مثل إعادة تسمية أسماء الفئات ووظائفها. ومع ذلك ، في الممارسة العملية ، يتضح غالبًا أن فهم مشكلة عدم الحصانة أكثر أهمية من تحديد الملف الذي هو عليه. هناك حاجة إلى التعريب عندما يتمكن شخص ما من إصلاح مشكلة عدم الحصانة ، ولكن في هذه الحالة ، سيفهم المطور أيضًا أين توجد مشكلة عدم الحصانة من التعليمة البرمجية التي تم فك ترجمتها.
- عندما نتحدث عن تحليل الشفرة الثنائية (على سبيل المثال ، C ++) ، بالطبع ، كل شيء أكثر تعقيدًا. لا توجد أداة لاسترداد رمز C ++ العشوائي بالكامل. ومع ذلك ، فإن خصوصية حالتنا هي أننا لسنا بحاجة إلى تجميع الشفرة لاحقًا: نحتاج إلى جودة كافية لفهم نقاط الضعف.
- في أغلب الأحيان ، يمكنك تحقيق جودة إزالة ترجمات كافية لفهم نقاط الضعف الموجودة. للقيام بذلك ، تحتاج إلى حل الكثير من المشكلات المعقدة ، ولكن يمكنك حلها (أدناه سنتحدث عنها لفترة وجيزة).
- بالنسبة لـ C / C ++ ، من الأصعب ترجمة مشكلة عدم الحصانة - حيث يتم فقد أسماء الأحرف بطرق عديدة أثناء عملية الترجمة ، لا يمكنك استعادتها.
- الوضع في Objective-C أفضل قليلاً - هناك أسماء وظائف هناك ، ومن الأسهل تحديد موضع الضعف.
- قضايا التعتيم تقف منفصلة. هناك عدد من التحولات المعقدة التي يمكن أن تعقد عملية إزالة التعيين ورسم الثغرات الأمنية. في الممارسة العملية ، اتضح أن برنامج فك تشفير جيد يمكنه التعامل مع معظم التحويلات المربكة (تذكر أننا نحتاج إلى جودة الكود الكودى لفهم الضعف).
كخلاصة - غالبًا ما يتبين أنها تظهر الثغرة الأمنية بحيث يمكن فهمها والتحقق منها.
تعقيدات وتفاصيل التحليل الثنائي
هنا لن نتحدث عن الرمز الفرعي: كل الأشياء المثيرة للاهتمام حوله قد تم ذكرها أعلاه. الشيء الأكثر إثارة للاهتمام هو تحليل الشفرة الثنائية الحقيقية. هنا سنتحدث عن تحليل C / C ++ و Object-C و Swift كمثال.
تنشأ صعوبات كبيرة حتى عند التفكيك. المرحلة الأكثر أهمية هي تقسيم الصورة الثنائية إلى برامج فرعية. بعد ذلك ، حدد إرشادات المجمّع في البرامج الفرعية - مسألة تقنية. لقد كتبنا عن ذلك بالتفصيل
في مقال لمجلة "قضايا الأمن السيبراني رقم 1 (14) - 2016" ، وهنا سنصف بإيجاز.
على سبيل المثال ، سنتحدث عن بنية x86. الإرشادات الموجودة به لا تحتوي على طول ثابت. في الصور الثنائية ، لا يوجد تقسيم واضح إلى أقسام من التعليمات البرمجية والبيانات: جداول الاستيراد ، يمكن أن تكون جداول الوظائف الافتراضية في قسم التعليمات البرمجية ، يمكن أن تكون جداول الانتقال في الفواصل الزمنية بين كتل الوظائف الأساسية في قسم التعليمات البرمجية. وفقًا لذلك ، يجب أن تكون قادرًا على فصل الكود عن البيانات وفهم أين تبدأ الروتين وأين تنتهي الروتين.
الأكثر شيوعًا طريقتان لحل مشكلة تحديد عناوين البدء للبرامج الفرعية. في الطريقة الأولى ، يتم تحديد عناوين البرامج الفرعية بواسطة prolog القياسي (بالنسبة إلى x86 architecture ، يتم الضغط على ebp ؛ mov ebp ، esp). في الطريقة الثانية ، يتم اجتياز قسم من التعليمات البرمجية بشكل متكرر من نقطة الدخول مع التعرف على تعليمات المكالمة الفرعية. يتم الالتفافية من خلال التعرف على تعليمات الفرع. يتم أيضًا استخدام توليفة من الطرق الموصوفة عند بدء اجتياز تكراري من عناوين البدء التي تم العثور عليها بواسطة prolog.
في الممارسة العملية ، اتضح أن مثل هذه الأساليب تعطي نسبة منخفضة إلى حد ما من الشفرة المعترف بها ، لأنه ليس كل الوظائف لها مقدمة قياسية ، وهناك مكالمات انتقالية غير مباشرة.
يمكن تحسين الخوارزميات الأساسية عن طريق الاستدلال التالي.
- في قاعدة اختبار كبيرة من الصور ، ابحث عن قائمة أكثر دقة من prologs (prologs جديدة أو صيغ مختلفة منها).
- يمكنك العثور تلقائيًا على جداول للوظائف الافتراضية ، ومنها لاستلام عناوين البدء للبرامج الفرعية.
- يمكن العثور على عناوين البدء للبرامج الفرعية وبعض الإنشاءات الأخرى على أساس مقاطع من الكود الثنائي المرتبط بآلية معالجة الاستثناء.
- يمكنك التحقق من عناوين البدء عن طريق البحث عن هذه العناوين في الصورة وعن طريق التعرف على إرشادات الاتصال.
- للبحث عن الحدود ، يمكنك القيام بخطوة تكرارية للروتين الفرعي مع التعرف على التعليمات الواردة من عنوان البداية. هناك صعوبة في التحولات غير المباشرة ووظائف عدم العودة. يمكن أن يساعد تحليل جدول الاستيراد والتعرف على بنيات التبديل.
الشيء المهم الآخر الذي يجب القيام به أثناء الترجمة العكسية ، من أجل البحث عن ثغرة أمنية لاحقًا ، هو التعرف على الوظائف القياسية في صورة ثنائية. يمكن ربط الوظائف القياسية بشكل ثابت بالصورة ، أو يمكن أن تكون مضمنة. خوارزمية التعرف الرئيسية هي البحث عن طريق التوقيع مع الاختلافات ؛ بالنسبة للحل ، يمكنك تقديم خوارزمية Aho-Korasik المعدلة. لجمع التواقيع ، تحتاج إلى تحليل مسبق لصور المكتبة التي تم تجميعها بشروط مختلفة ، وتحديدها على أنها بايتات غير متغيرة.
ما التالي
في القسم السابق ، درسنا المرحلة الأولية من الترجمة العكسية للتفكيك الثنائي للصورة. المرحلة ، في الواقع ، هي الأولي ، ولكن تحديد. في هذه المرحلة ، يمكنك أن تفقد بعض الكود ، والذي سيكون له بعد ذلك تأثير كبير على نتائج التحليل.
ثم يحدث الكثير من الأشياء المثيرة للاهتمام. أقول لفترة وجيزة عن المهام الرئيسية. نحن لا نتحدث بالتفصيل: إما الدراية الفنية ، والتي لا يمكننا الكتابة عنها بوضوح هنا ، أو لا توجد حلول تقنية وهندسية مثيرة للاهتمام في التفاصيل.
- تحويل رمز التجميع إلى تمثيل وسيط يمكن إجراء التحليل عليه. يمكنك استخدام مختلف الرموز. بالنسبة إلى لغات C ، يبدو LLVM اختيارًا جيدًا. يتم دعم LLVM وتطويره بشكل نشط من قبل المجتمع ، والبنية التحتية ، بما في ذلك مفيدة للتحليل الثابت ، مؤثرة حاليًا. في هذه المرحلة ، هناك عدد كبير من التفاصيل التي تحتاج إلى الاهتمام بها. على سبيل المثال ، تحتاج إلى الكشف عن المتغيرات التي يتم معالجتها على المكدس حتى لا تضرب الكيانات في العرض الناتج. تحتاج إلى تكوين العرض الأمثل لمجموعات إرشادات المجمّع في تعليمات bytecode.
- استعادة الهياكل عالية المستوى (مثل الحلقات والفروع). كلما زادت دقة إمكانية استعادة الإنشاءات الأصلية من رمز المجمّع ، كانت جودة التحليل أفضل. تتم استعادة هذه الإنشاءات باستخدام عناصر نظرية الرسم البياني على CFG (الرسم البياني لتدفق التحكم) وبعض الرسوم البيانية الأخرى للبرنامج.
- تنفيذ خوارزميات التحليل الثابت. هناك تفاصيل. بشكل عام ، ليس من المهم للغاية ما إذا كنا قد حصلنا على التمثيل الداخلي من المصدر أو من الملف الثنائي - فنحن جميعًا بحاجة أيضًا إلى إنشاء CFG وتطبيق خوارزميات تحليل تدفق البيانات والخوارزميات الأخرى النموذجية للإحصائيات. هناك بعض الميزات عند تحليل طريقة العرض التي تم الحصول عليها من الثنائي ، لكنها أكثر تقنية.
النتائج
تحدثنا عن كيفية القيام بتحليل ثابت عند عدم وجود شفرة المصدر. وفقًا لتجربة التواصل مع العملاء ، اتضح أن التكنولوجيا مطلوبة للغاية. ومع ذلك ، فإن التكنولوجيا نادرة: مشكلة التحليل الثنائي ليست تافهة ، حلها يتطلب خوارزميات معقدة عالية التقنية من التحليل الثابت والترجمة العكسية.
كُتِب هذا المقال بالتعاون مع أنتون بروكوفييف ، محلل تطبيق الطاقة الشمسية