
CVE-2017-13868: تسريب معلومات لبيانات غير مهيأة من كومة النواة في XNU.
دالة ctl_ctloutput في macOS High Sierra 10.13 تتجاهل القيمة المرجعة من استدعاء sooptcopyin، مما يفتح نافذة سباق لتسريب بيانات غير مهيأة من كومة النواة إلى مساحة المستخدم. ctl_ctloutput-leak هو إثبات مفهوم يحاول تشغيل هذا التسريب للمعلومات. يتطلب الاستغلال صلاحيات الجذر.
تم تأكيد عمل هذا الاستغلال على macOS High Sierra 10.13.1 Beta 17B25c و iOS 10.1.1 14B100 (تحت mach_portal).
هذا هو الجزء ذو الصلة من ctl_ctloutput على macOS High Sierra 10.13:
if (sopt->sopt_valsize && sopt->sopt_val) {
MALLOC(data, void *, sopt->sopt_valsize, M_TEMP, // (a) يتم تخصيص data
M_WAITOK); // بدون M_ZERO.
if (data == NULL)
return (ENOMEM);
/*
* 4108337 - نسخ بيانات المستخدم في حالة
* احتياج التحكم بالنواة إليها
*/
error = sooptcopyin(sopt, data, // (b) يتم استدعاء
sopt->sopt_valsize, sopt->sopt_valsize); // sooptcopyin() لملء
} // المخزن المؤقت؛ يتم تجاهل
len = sopt->sopt_valsize; // القيمة المرجعة.
socket_unlock(so, 0);
error = (*kctl->getopt)(kctl->kctlref, kcb->unit, // (c) يتم استدعاء تنفيذ
kcb->userdata, sopt->sopt_name, // getsockopt()
data, &len); // لمعالجة المخزن المؤقت.
if (data != NULL && len > sopt->sopt_valsize) //
panic_plain("ctl_ctloutput: ctl %s returned "
"len (%lu) > sopt_valsize (%lu)\n",
kcb->kctl->name, len,
sopt->sopt_valsize);
socket_lock(so, 0);
if (error == 0) {
if (data != NULL)
error = sooptcopyout(sopt, data, len); // (d) إذا نجح (c)،
else // يتم نسخ مخزن البيانات
sopt->sopt_valsize = len; // إلى مساحة المستخدم.
} //
يقوم هذا الكود بما يلي:
data الخاص بـ getsockopt، دون تحديد العلم M_ZERO لمسح البايتات المخصصة.getsockopt من مساحة المستخدم باستخدام sooptcopyin، لملء المخزن المؤقت المخصص حديثًا. من المفترض أن يغطي هذا النسخ البيانات المخصصة بالكامل، ولهذا لم يكن العلم M_ZERO ضروريًا. ومع ذلك، لا يتم التحقق من القيمة المرجعة لـ sooptcopyin، مما يعني أنه من الممكن أن يفشل النسخ، تاركًا بيانات غير مهيأة في المخزن المؤقت. يمكن أن يفشل النسخ إذا، على سبيل المثال، مرر البرنامج عنوانًا غير معيّن إلى getsockopt.getsockopt لهذا المقبس التحكمي بالنواة. يجب أن يعالج هذا التنفيذ المخزن المؤقت للإدخال، وربما يعدله ويقصره، ويعيد رمز نتيجة. ومع ذلك، يمكن للتنفيذ أن يفترض أن المخزن المؤقت المقدم قد تمت تهيئته بالفعل (نظريًا لأنه يأتي من مساحة المستخدم)، وبالتالي فإن العديد من التطبيقات لا تعدل المخزن المؤقت على الإطلاق. دالة NECP necp_ctl_getopt، على سبيل المثال، تعيد 0 فقط دون معالجة مخزن البيانات على الإطلاق.getsockopt خطأً، يستدعي دالة لنسخ مخزن البيانات مرة أخرى إلى مساحة المستخدم.وبالتالي، من خلال تحديد عنوان بيانات غير معيّن لـ getsockopt، يمكننا التسبب في تخصيص مخزن مؤقت على الكومة بحجم مُتحكم فيه، ومنع تهيئة محتويات هذا المخزن، ثم الوصول إلى استدعاء sooptcopyout الذي يحاول كتابة ذلك المخزن مرة أخرى إلى العنوان غير المعيّن. كل ما نحتاج إليه لنجاح النسخ هو إعادة تعيين ذلك العنوان بين استدعاءات sooptcopyin و sooptcopyout. إذا تمكنا من فعل ذلك، فسنسرب بيانات غير مهيأة من كومة النواة إلى مساحة المستخدم.
اتضح أن هذا سباق سهل الفوز نسبيًا. أثناء الاختبار على جهاز Macbook Pro 2015 الخاص بي، لم يكن متوسط عدد المحاولات للفوز بالسباق أكثر من 600، ولم يكن الوسيط أكثر من 5. على iOS 10.1.1 على iPhone 7 كان السباق أسهل في الفوز، حيث يستغرق عادةً لا أكثر من محاولتين. (تم إجراء هذا الاختبار مع إيقاف DEBUG، لأن تعليمات printf تبطئ الاستغلال بشكل كبير.)
للبناء، قم بتشغيل make. راجع أعلى ملف Makefile لخيارات البناء المختلفة.
قم بتشغيل الاستغلال عن طريق تحديد حجم التسريب المستهدف في سطر الأوامر:
$ sudo ./ctl_ctloutput-leak 128
000000: ef be ad de ef be ad de 00 00 00 00 00 00 00 00
000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000020: 00 00 00 00 00 00 00 00 01 00 00 00 40 80 00 00
000030: de 28 45 00 04 00 00 00 a0 ff 4a 26 80 ff ff ff
000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000050: 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000070: 00 00 00 00 00 00 00 00 ef be ad de ef be ad de
أبلغت Apple بهذه المشكلة في 7 أكتوبر 2017. تم تخصيص CVE-2017-13868 لها. أصلحت Apple المشكلات في macOS 10.13.2 و iOS 11.2.
كود ctl_ctloutput-leak يُطرح في المجال العام. كمجاملة أطلب منك إذا أشرت أو استخدمت أيًا من هذا الكود أن تنسبه إلي.
ctl_ctloutputsooptcopyout