
هذا استغلال لـ CVE-2017-7047، يعمل على الإصدار 10.3.2 وما دونه.
triple_fetch - ianbeer [https://bugs.chromium.org/p/project-zero/issues/detail?id=1247]
هذا هو استغلال لـ CVE-2017-7047، وهو خطأ منطقي في libxpc سمح لمرسلي الرسائل الخبيثة بإرسال كائنات xpc_data مدعومة بذاكرة مشتركة. لا يبدو أن مستهلكي رسائل xpc كانوا يتوقعون أن المخازن الخلفية لكائنات xpc_data يمكن تعديلها من قبل المرسل أثناء معالجتها من قبل المستقبل.
يستغل هذا المشروع CVE-2017-7047 لبناء قالب خادم تصحيح lldb عن بُعد (remote lldb debugserver stub) كنموذج إثبات، قادر على الإرفاق بجميع عمليات مساحة المستخدم على iOS والسماح بتصحيحها عن بُعد.
هذه نظرة عامة رفيعة المستوى على الاستغلال، وقد تتبعها كتابة متعمقة في وقت لاحق. في الوقت الحالي، يرجى الاطلاع على الكود لمزيد من التفاصيل :)
الجزء الأول
يستهدف الاستغلال NSXPC، وهي تنفيذ للاستدعاء الإجرائي عن بُعد في Objective-C تستخدمه العديد من خدمات iOS (1). تتكون رسالة NSXPC من كائن bplist16 متسلسل داخل كائن xpc_data متسلسل عبر xpc داخل رسالة mach.
من بين أمور أخرى، يحتوي كائن bplist16 على سلسلة ترميز الأنواع في Objective-C (2) والتي سيتم تحليلها بواسطة الدالة ___NSMS1 في CoreFoundation. لا تتوقع هذه الدالة أن يتغير محتوى السلسلة التي تقوم بتحليلها، ويستخدم هذا الاستغلال ذلك لبناء أولية تجاوز سعة الكومة من خلال استغلال حقيقة أن جزءًا معينًا من السلسلة سيتم جلبها من الذاكرة ثلاث مرات. من خلال التبديل بين ثلاث قيم مختلفة ومختارة بعناية، نتمكن من تجاوز حجم تخصيص كومة محدد ببايتات عشوائية.
يحتوي minibplist16.c على تنفيذ بسيط لتسلسل bplist ومناقشة حول كيفية عمله.
تحتوي رسالة xpc الخارجية على تمشيط الكومة (heap groom). تستخدم تنفيذًا مخصصًا لبروتوكول تسلسل XPC لتمشيط الكومة عن طريق صياغة قواميس xpc بمفاتيح متصادمة لبناء أوليات التخصيص والتحرير. تحتوي رسالة xpc الخارجية أيضًا على رش الكومة (باستخدام نسخ متعددة من كائن ذاكرة مشتركة للحفاظ على انخفاض استخدام الذاكرة) ورش أسماء حقوق إرسال منافذ mach.
يوجّه تجاوز السعة مؤشر isa Class لكائن Objective-C إلى كائن مزيف مبعثر في الكومة بحيث عندما يتم استدعاء طريقة على ذلك الكائن المزيف، يتم تحويل المكدس إلى مكدس ROP صغير. يقوم ROP باختبار جميع أسماء حقوق إرسال منافذ mach المبعثرة في محاولة لإرسال حق إرسال الهدف إلى منفذ المهمة الخاص به إلى كل اسم حق إرسال مرشح مبعثر. يستمع الاستغلال على جميع المنافذ المبعثرة، وإذا نجح الاستغلال، فإنه يستقبل حق إرسال إلى منفذ مهمة الهدف، وعندها يتحكم بالكامل في مهمة الهدف.
فاصل
يستهدف الاستغلال خدمة com.apple.CoreAuthentication.daemon التي يستضيفها الخفي coreauthd والذي يعمل بصلاحيات الجذر. يمكن الوصول إلى هذه الخدمة من صندوق الرمل الخاص بالتطبيق. أظهرت بعض التجارب بعد أن جعلت الاستغلال يعمل في البداية أنه من سياق coreauthd يمكن لواجهة برمجة التطبيقات processor_set_tasks الحصول على حقوق إرسال لمنافذ المهام لجميع عمليات مساحة المستخدم التي تعمل على الجهاز. هذه معلومة عامة معروفة منذ عام 2012 على الأقل، ويغطي الباحث البارز في الأنظمة الداخلية لـ iOS جوناثان ليفين هذا التاريخ بعمق على موقعه (3). الكود الذي رفعه ليفين في عام 2015 لا يزال يعمل حتى اليوم - لا يتطلب جهازًا مكسور الحماية، فقط صلاحيات الجذر على جهاز قياسي.
الجزء الثاني
كان الهدف الرئيسي لمصحح الأخطاء الذي أردت بناءه بهذا الاستغلال هو القدرة على الإرفاق بعملية عشوائية، وتعيين نقاط التوقف، وفحص وتعديل حالة السجلات والذاكرة عند الوصول إليها. بدلاً من تنفيذ بروتوكول gdb أو lldb البعيد من الصفر، قررت إجراء التعديلات المطلوبة على مشروع lldb debugserver ثم استخدام الاستغلال لتشغيله.
بدلاً من استخدام نقاط توقف برمجية تتطلب إما تعطيل توقيع الكود أو التغلب عليه، تم تصحيح debugserver لاستخدام نقاط توقف الأجهزة حصريًا. يحتوي ARM64 على 16 سجلًا لنقاط توقف الأجهزة، مما يعني أنه يمكنك الحصول على 16 نقطة توقف نشطة كحد أقصى.
كان الدعم الأولي لنقاط توقف أجهزة ARM موجودًا في كود lldb debugserver، لكنه تطلب بعض الاختراق ليعمل. على سبيل المثال، كان عليّ إضافة كود يصحح مؤشر الدالة pthread_introspection_hook في الضحية ليتعطل دائمًا حتى أتمكن من اكتشاف إنشاء خيوط جديدة ونشر حالة نقاط توقف الأجهزة إلى الخيوط المنشأة حديثًا والمتابعة كما لو أنها لم تتعطل أبدًا.
لقد قمت أيضًا بتصحيح كود الإرفاق والمتابعة لتعليق واستئناف المهمة مباشرة عبر منفذ المهمة بدلاً من استخدام ptrace والإشارات.
نصائح البناء
كل شيء يجب أن يعمل مع جميع أجهزة iOS التي تعمل بنظام 10.0 إلى 10.3.2 شاملة. لقد اختبرت على:
iPhone 7 + 10.3.2 iPod Touch + 10.1.1 iPad Mini 2 + 10.2
لقد أدرجت ثنائي debugserver مبنيًا مسبقًا وأقترح أن تستخدمه، لكن تصحيح debugserver الخاص بـ lldb مضمّن أيضًا في debugserver.diff.
بناء debugserver ليس صعبًا جدًا. كنت أعمل على المراجعات التالية من git: lldb: 0db640c4cd1ec4e4c2580336fa5f53be029c5bc7 llvm: ec48fd127774a4b67c72ea7c3057b5c964375e77 clang: b6e778e0bfa2fc32f8821c6b33762f5cb6724659
قم بتطبيق debugserver.diff المرفق.
للبناء ستحتاج إلى cmake و ninja (إصدار حديث)، يمكنك الحصول عليهما من المصدر أو كثنائيات من مدير الحزم المفضل لديك على Mac.
(4) يحتوي على دليل لإعداد بناء llvm عادي على MacOS وقد يكون مفيدًا.
ستحتاج إلى إنشاء روابط رمزية لمجموعة من ملفات الرأس في iOS SDK الخاص بك، على الأقل:
xpc/ launchd.h libproc.h sys/proc_info.h sys/kern_control.h net/route.h mach/mach_vm.h mach/shared_region.h sys/ptrace.h crt_externs.h
يجب أن تمنحك صيغة cmake التالية كل التلميحات التي تحتاجها:
cmake -G "Ninja" -DCMAKE_OSX_ARCHITECTURES="armv7;armv7s;arm64" -DCMAKE_TOOLCHAIN_FILE=../cmake/platforms/iOS.cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_BUILD_RUNTIME=Off -DLLVM_INCLUDE_TESTS=Off -DLLVM_INCLUDE_EXAMPLES=Off -DLLVM_ENABLE_BACKTRACES=Off ../
ninja debugserver
ستحتاج بعد ذلك إلى توقيع أو توقيع زائف لثنائي debugserver واستبدال الثنائي الموجود في مشروع xcode المرفق.
توقيع الكود
مشروع الاستغلال بشكل افتراضي سيثبت نسخة محسنة من خطاف mach_portal amfid (هذه المرة مع دعم كامل للملفات السمينة fat files وبدون إزاحات ثابتة مكتوبة بجدول :) )
إذا كنت ترغب فقط في تصحيح الأشياء، يجب أن تتمكن من توقيع ثنائي debugserver بشهادتك الخاصة وتعطيل خطاف amfid.
إذا كنت تستخدم خطاف amfid، فتذكر أن التطبيق الذي يعمل فيه لا يزال خاضعًا لقيود تنفيذ الكود في الخلفية. يطلب التطبيق مزيدًا من الوقت عبر beginBackgroundTaskWithName.
الاستخدام:
قم بتوصيل جهاز المضيف وجهاز iDevice الهدف بنفس الشبكة اللاسلكية ولاحظ عنوان IP الخاص بـ iDevice.
قم ببناء وتشغيل تطبيق الاستغلال. أوصي بالقيام بذلك داخل xcode لكنه سيعمل بشكل مستقل.
انتظر قليلاً. إذا لم يعمل بعد بضع دقائق، أعد تشغيل الجهاز إعادة تشغيل صلبة، ثم انتظر قليلاً وحاول مرة أخرى.
إذا نجح، يجب أن يطبع “patched debugserver listening on port 1234”
إذا نقرت على زر “get process listing” فيجب أن ترى مخرجات ps
(يسهل رؤية المخرجات إذا استخدمت xcode لكن الاستغلال سيعرض المخرجات أيضًا)
ابحث عن العملية الهدف التي تهتم بتصحيحها ولاحظ رقمها pid.
على المضيف، قم بإطلاق lldb من سطر الأوامر: $ lldb (lldb)
اضبط المنصة إلى ios remote: (lldb) platform select remote-ios
اتصل بقالب debugserver: (lldb) process connect connect://192.168.0.172:1234
(حيث 192.168.0.172 هو عنوان IP الخاص بـ iDevice)
أرفق بالعملية التي تهتم بها: (lldb) attach 55
...انتظر قليلاً، debugserver يعمل في وضع الإسهاب...
Process 55 stopped
Executable module set to "/usr/libexec/backboardd".
لقد تم الإرفاق :)
عيّن نقطة توقف: (lldb) break set --name malloc Breakpoint 1: 4 locations.
تابع:
(lldb) c Process 55 resuming Process 55 stopped
malloc libsystem_malloc.dylibmalloc:
-> 0x1936161e0 <+0>: stp x20, x19, [sp, #-0x20]!
0x1936161e4 <+4>: stp x29, x30, [sp, #0x10]
0x1936161e8 <+8>: add x29, sp, #0x10 ; =0x10احصل على تتبع المكدس: