
CVE-2018-4241: تجاوز سعة الكومة في نواة XNU بسبب فحص حدود سيء في MPTCP لنظام iOS 11 - 11.3.1 من إصدار Ian Beer
@i41nbeer
mptcp_usr_connectx هو معالج استدعاء النظام connectx لعائلة المقابس AP_MULTIPATH.
منطق هذه الدالة يفشل في التعامل بشكل صحيح مع عناوين sockaddr المصدر والوجهة التي ليست
AF_INET أو AF_INET6:
// التحقق من sa_len لـ AF_INET:
if (dst->sa_family == AF_INET &&
dst->sa_len != sizeof(mpte->__mpte_dst_v4)) {
mptcplog((LOG_ERR, "%s IPv4 dst len %u\n", __func__, dst->sa_len), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
error = EINVAL;
goto out;
}
// التحقق من sa_len لـ AF_INET6:
if (dst->sa_family == AF_INET6 &&
dst->sa_len != sizeof(mpte->__mpte_dst_v6)) {
mptcplog((LOG_ERR, "%s IPv6 dst len %u\n", __func__, dst->sa_len), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_ERR);
error = EINVAL;
goto out;
}
// الكود لا يخرج إذا كانت sa_family ليست AF_INET ولا AF_INET6
if (!(mpte->mpte_flags & MPTE_SVCTYPE_CHECKED)) {
if (mptcp_entitlement_check(mp_so) < 0) {
error = EPERM;
goto out;
}
mpte->mpte_flags |= MPTE_SVCTYPE_CHECKED;
}
// memcpy مع sa_len يصل إلى 255:
if ((mp_so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0) {
memcpy(&mpte->mpte_dst, dst, dst->sa_len);
}
بالنظر حولك في الهيكل الذي تفيض داخله، ستلاحظ أنه يمكنك الوصول إلى كلا الحقلين هنا:
if (mpte->mpte_itfinfo_size > MPTE_ITFINFO_SIZE) _FREE(mpte->mpte_itfinfo, M_TEMP);
mpte_itfinfo_size يقع مباشرة قبل mpte_itfinfo.
عند تهيئة الهيكل، يشير مؤشر mpte_itfinfo إلى مصفوفة داخلية صغيرة. إذا تمت إضافة تيارات فرعية أكثر مما يتسع لهذه المصفوفة، فإنها توضع بدلاً من ذلك في مخزن مؤقت على الكومة، وسيشير mpte_itfinfo إلى ذلك المخزن.
إذا كان لديك خطأ آخر (مثل خطأ تسريب كومة النواة من async_wake)، يمكنك الكتابة فوق حقل mpte_itfinfo بأي كائن منطقة صالح وسيتم تحريره (في الواقع، يمكنك أيضًا الكتابة فوقه بإزاحة داخل ذلك الكائن لمزيد من المتعة!)
لكن، ليس لدينا ذلك.
بدلاً من ذلك، هناك نهج آخر وهو الكتابة الجزئية فوق المؤشر. إذا قمنا بالكتابة الجزئية فوقه بأصفار، يمكننا توجيهه إلى قيمة محاذاة بـ 256 بايت، أو 65 كيلو بايت، أو 16 ميغابايت، أو 4 غيغابايت.
في هذا الاستغلال، اخترت الكتابة الجزئية بـ 3 بايت من الأصفار، مما سيؤدي إلى تحرير عنوان mpte_itfinfo مقربًا إلى أسفل إلى حدود 16 ميغابايت التالية.
تدفق الاستغلال كالتالي:
قم بتخصيص 16 ميغابايت من ipc_kmsgs بالتناوب مع مجموعة من مقابس mptcp. الهدف هنا هو الحصول على تخصيص kalloc.2048 على حدود 16 ميغابايت تلك.
استخدم الخلل لتحرير أحد ipc_kmsgs، مما ينقل تلك الصفحة إلى القائمة الوسيطة ويضع التخصيص المحاذي لـ 16 ميغابايت على قائمة الصفحات الوسيطة لـ kalloc.2048.
قم بتخصيص مجموعة من أنابيب مملوءة بطول 2047 بايت؛ المخازن المؤقتة الخلفية لهذه الأنابيب ستأتي من kalloc.2048، ونأمل أن تشمل عنواننا المحاذي لـ 16 ميغابايت.
قم بتشغيل الخلل مرة ثانية، مع تحرير نفس العنوان، وهذه المرة قم بتخصيص مجموعة من مخازن ipc_kmsg المخصصة مسبقًا من kalloc.2048.
الآن، نأمل أن يكون لدينا ipc_kmsg (يمكننا إرسال رسائل إليه ثم استقبالها) ومخزن أنبوب مؤقت (يمكننا القراءة والكتابة منه) يتداخلان مع بعضهما البعض.
أستخدم خدعة منفذ الاستثناء للخيط من extra_recipe للحصول على رسائل ترسل إلى مخزن ipc_kmsg المخصص مسبقًا. في كل مرة نتحقق من كل أنبوب لمعرفة ما إذا كان يحتوي على الرسالة. عندما نجد الزوج الصحيح (ipc_kmsg, pipe) يمكننا إعادة كتابة الرسالة لإرسال منفذ مزيف إلى أنفسنا يعيش داخل مخزن الأنبوب المؤقت. أقوم ببناء هذا المنفذ المزيف مثل المنفذ من async_wake (الذي بنيته على yalu 10.2 بواسطة @qwertyoruiopz و @marcograss) لإعطائي بدائية مبكرة لقراءة النواة.
باستخدام بدائية قراءة النواة، أجد مهمة النواة وأصنع منفذًا مزيفًا يسمح بقراءة/كتابة ذاكرة النواة بسهولة أكبر عبر mach_vm_read/mach_vm_write.
ملاحظة: لتوصيل مقابس mptcp، تحتاج إلى صلاحية com.apple.developer.networking.multipath والتي تتطلب شهادة مطور Apple، والتي يمكن لأي شخص شراؤها من Apple.
الموثوقية: هذه أداة بحث أمني وهي بعيدة جدًا عن الكمال. ومع ذلك، يجب أن تعمل في معظم الأوقات، وعندما تعمل، يجب أن تقوم بعمل جيد في التنظيف حتى لا تتعطل لاحقًا.
لتحسين احتمالية عملها:
الأجهزة المدعومة: يجب أن تعمل على iOS 11.0 - 11.3.1 شاملة. اختبرت على: iPod Touch 6g و iPhone 6s و iPhone SE و iPhone 7 و iPhone 8
API: #include "sploit.h" واستدع go() لتشغيل الاستغلال. إذا نجح، يمكنك استخدام الدوال في kmem.h لقراءة وكتابة ذاكرة النواة.
ملاحظات: قام العديد من الأشخاص بنشر تحليل ثنائي لهذه الثغرة من التصحيح (أو تم تصحيح 0day الخاص بهم؛ اقرأ أعمالهم لمزيد من التفاصيل): @elvanderb قدم محادثة خاطفة حول الثغرة في rump.beer في باريس في 31 مايو: https://www.rump.beer/2018/slides/ios_48h.pdf @jaakerblom نشر استغلالاً عملياً على GitHub في 1 يونيو: https://github.com/potmdehex/multipath_kfree تقنية جون مشابهة لتقنيتي لكنه يستخدم تجاوزًا ببايتين بدلاً من ثلاثة، ويستبدل بأشياء مختلفة. عمل رائع!