تجاوز سعة المخزن المؤقت القائم على المكدس في R 3.4.4. استغلال كامل على x86، ولكن فقط التحكم في RIP مع تحليل الأدوات على x64 بسبب قيود البرنامج. نفس الثغرة عبر معماريتين، مما يؤدي إلى مسارات استغلال مختلفة.
تجاوز سعة المخزن المؤقت المستند إلى المكدس في R 3.4.4. استغلال كامل على x86، ولكن فقط التحكم في RIP مع تحليل القطع على x64 بسبب قيود البرنامج. نفس الثغرة عبر معماريتين، مما يؤدي إلى مسارات استغلال مختلفة.
هذا المستودع جزء من المواد التي أستخدمها عند تدريس استغلال تلف الذاكرة (بالإضافة إلى عملي المعتاد، أدرس أيضًا في دورات مختلفة في الأمن السيبراني حيث أساعد في تدريب الجيل القادم من مهندسي الهندسة العكسية).
CVE-2019-25485 هي الحالة التي أستخدمها عندما أريد من الطلاب العمل على نفس الثغرة على معماريتين مختلفتين ورؤية ما يتغير بينهما بأنفسهم. يأتي R 3.4.4 في إصدارات x86 و x64، ونفس التجاوز موجود في كليهما، نفس حقل واجهة المستخدم الرسومية، نفس معالج الإدخال، نفس التعطل. تم توثيق كليهما واستغلالهما هنا كتمرينين منفصلين:
R 3.4.4 هو تطبيق حوسبة إحصائية، وليس خدمة شبكة أو متصفح. يتم تشغيل التجاوز من خلال حقل واجهة مستخدم رسومية سطح المكتب، مما يعني أن سطح الهجوم مختلف تمامًا عن كل حالة أخرى أقوم بتدريسها. ما يجعل هذه الحالة مفيدة للتدريس:
R هي بيئة حوسبة إحصائية ورسومية متاحة لأنظمة Windows و macOS و Linux. الثغرة موجودة في مربع حوار تفضيلات واجهة المستخدم الرسومية، وتحديدًا حقل اللغة للقوائم والرسائل، الذي ينسخ إدخال المستخدم إلى مخزن مؤقت على المكدس بحجم ثابت دون التحقق من طوله.
تفاصيل فنية رئيسية:
يقوم R 3.4.4 بمعالجة حقل اللغة للقوائم والرسائل عن طريق نسخ السلسلة المقدمة إلى مخزن مؤقت على المكدس بحجم ثابت دون التحقق من طولها. يبدو إصدار مبسط من المنطق القابل للاستغلال كالتالي:
char language_buffer[256];
strcpy(language_buffer, user_input);
إرسال سلسلة طويلة بما يكفي يتسبب في نسخ يتجاوز نهاية المخزن المؤقت، مما يفسد المكدس حتى يتم تجاوز عنوان العودة المحفوظ. عندما تعود الدالة، يقوم المعالج بتحميل القيمة التي يتحكم فيها المهاجم من المكدس إلى RIP ويحاول القفز إليها.
على x64، يفرض Windows التحقق من العنوان القانوني قبل أي قفزة. قيمة غير قانونية مثل 0x4141414141414141 تؤدي فورًا إلى انتهاك الوصول قبل تحميل RIP، مما يعني أن التعطل يبدو مختلفًا عن x86، لا يوجد RIP = 4141414141414141 نظيف. يجب العثور على الإزاحة عن طريق قراءة النمط الدوري من المكدس بعد التعطل بدلاً من قراءتها مباشرة من RIP.
يمكن إعادة إنتاج التعطل عن طريق لصق سلسلة طويلة في حقل اللغة. لا يلزم مصادقة. مثال باستخدام بايثون لتوليد الحمولة:
import struct
payload = b'A' * 400
with open('payload.txt', 'wb') as f:
f.write(payload)
افتح R 3.4.4 x64
Edit -> GUI Preferences
ألصق محتويات payload.txt في Language for menus and messages
انقر OK
الهدف من هذا المستودع ليس فقط إظهار التعطل، بل السير خلال عملية الاستغلال الكاملة على كلتا المعماريتين، وتوثيق ما ينجح على x86، وما ينهار على x64، والأهم من ذلك، لماذا.
للحفاظ على نظافة README الرئيسي، تم وضع الملاحظات التفصيلية للاستغلال والبرامج النصية وخطوات المٌصحح داخل مجلد Vulnerability 📂 في هذا المستودع، منظمة في مجلدات فرعية منفصلة x86 و x64.
هناك ستجد سير العمل الكامل لكلا المعماريتين:
x86 - الاستغلال الكامل:
x64 - التحكم في RIP وتحليل الاستغلال: