
استغلال نواة أندرويد 14 لأجهزة Pixel7/8 Pro
تقدم هذه المقالة تحليلاً متعمقاً لثغرتين في نواة معالج Mali GPU، يمكن الوصول إليهما من بيئة التطبيقات الافتراضية المعزولة (sandbox)، وقد اكتشفتُهما بشكل مستقل وأبلغت جوجل بهما. وتتضمن استغلالاً للنواة (kernel exploit) يحقق قدرات قراءة/كتابة عشوائية في النواة. ونتيجةً لذلك، فإنه يعطّل SELinux ويرفع الامتيازات إلى صلاحيات الجذر (root) على أجهزة Google Pixel 7 و8 Pro التي تعمل بالإصدارات التالية من Android 14:
google/husky/husky:14/UD1A.231105.004/11010374:user/release-keysgoogle/cheetah/cheetah:14/UP1A.231105.003/11010452:user/release-keysgoogle/cheetah/cheetah:14/UP1A.231005.007/10754064:user/release-keysgoogle/panther/panther:14/UP1A.231105.003/11010452:user/release-keys (بواسطة m4b4 (Marcel))يعتمد هذا الاستغلال على ثغرتين: تجاوز عدد صحيح (integer overflow) ناتج عن تصحيح غير مكتمل في أمر ioctl الخاص بـ gpu_pixel_handle_buffer_liveness_update_ioctl، وتسريب معلومات داخل مخازن رسائل تدفق الخط الزمني (timeline stream).
عالجت جوجل تجاوز العدد الصحيح في أمر ioctl الخاص بـ gpu_pixel_handle_buffer_liveness_update_ioctl في هذا الالتزام. في البداية، عندما أبلغت عن هذه المشكلة، ظننت أن الخطأ ناتج عن مشكلة في التصحيح الموصوف سابقاً. وبعد مراجعة التقرير، أدركت أن تحليلي للثغرة كان غير دقيق. وعلى الرغم من افتراضي الأول بأن التصحيح غير مكتمل، فإنه يحل فعلياً ويمنع حدوث تجاوز سفلي في العملية الحسابية. قادني هذا إلى الاشتباه في أن التغيير لم يُطبَّق في إصدارات الإنتاج. ومع ذلك، على الرغم من أنني أستطيع التسبب في تجاوز سفلي في العملية الحسابية، فلا يمكنني التسبب في تجاوز علوي. يشير هذا إلى أن أمر ioctl قد تم إصلاحه جزئياً، وإن لم يكن بالتصحيح المعروض أعلاه. كشف الفحص باستخدام IDA أنه تم شحن تصحيح غير مكتمل آخر في إصدارات الإنتاج، وهذا التصحيح غير موجود في أي فرع git من وحدة نواة معالج mali gpu.
تم اكتشاف هذه الثغرة لأول مرة في أحدث إصدار من Android وأُبلغ عنها في 19 نوفمبر 2023. وأخبرتني جوجل لاحقاً أنها كانت قد حددتها داخلياً بالفعل، وأنها خصصت لها CVE-2023-48409 في نشرة أمان Android لشهر ديسمبر، وصنفتها كمشكلة مكررة.
على الرغم من أنني تمكنت من التحقق من أن الخطأ قد تم تحديده داخلياً قبل أشهر من تقريري (استناداً إلى تاريخ الالتزام حوالي 30 أغسطس)، إلا أنه لا تزال هناك بعض الالتباسات. وتحديداً، من الغريب أن مستويات تصحيح الأمان (SPL) لشهرَي أكتوبر ونوفمبر على أحدث الأجهزة كانت لا تزال متأثرة بهذه الثغرة — ولم أتحقق من الإصدارات السابقة لهذه. لذلك، لا أستطيع الجزم بشكل قاطع ما إذا كانت هذه مشكلة مكررة فعلاً، وما إذا كان التصحيح المناسب قد جُدول بالفعل لشهر ديسمبر قبل تقديمي، أم كان هناك سهو في معالجة هذه الثغرة.
على أي حال، ما يجعل هذه الثغرة قوية هو ما يلي:
info.live_ranges تحت سيطرة المستخدم بالكامل.info.live_ranges عند إزاحة عشوائية قبل بداية عنوان النواة للمخزن buff.تتقاسم هذه الثغرة أوجه تشابه مع ثغرة التجاوز السفلي للمخزن المؤقت DeCxt::RasterizeScaleBiasData() التي اكتشفتُها واستغللتها في نواة iOS 15 في عام 2022.
يُنفذ معالج Mali GPU تدفق خط زمني (timeline stream) مخصصاً مصمماً لجمع المعلومات وتسلسلها ثم كتابتها في مخزن حلقي (ring buffer) وفق تنسيق محدد. يمكن للمستخدمين استدعاء أمر ioctl kbase_api_tlstream_acquire للحصول على واصف ملف (file descriptor)، مما يمكنهم من القراءة من هذا المخزن الحلقي. تنسيق الرسائل هو كما يلي:
على سبيل المثال، تقوم الدالة __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_wait بتسلسل مؤشرات النواة kbase_kcpu_command_queue وdma_fence في مخزن الرسائل، مما يؤدي إلى تسريب مؤشرات النواة إلى عمليات مساحة المستخدم.```c
void __kbase_tlstream_tl_kbase_kcpuqueue_enqueue_fence_wait(
struct kbase_tlstream *stream,
const void *kcpu_queue,
const void *fence
)
{
const u32 msg_id = KBASE_TL_KBASE_KCPUQUEUE_ENQUEUE_FENCE_WAIT;
const size_t msg_size = sizeof(msg_id) + sizeof(u64)
+ sizeof(kcpu_queue)
+ sizeof(fence)
;
char *buffer;
unsigned long acq_flags;
size_t pos = 0;
buffer = kbase_tlstream_msgbuf_acquire(stream, msg_size, &acq_flags);
pos = kbasep_serialize_bytes(buffer, pos, &msg_id, sizeof(msg_id));
pos = kbasep_serialize_timestamp(buffer, pos);
pos = kbasep_serialize_bytes(buffer,
pos, &kcpu_queue, sizeof(kcpu_queue));
pos = kbasep_serialize_bytes(buffer,
pos, &fence, sizeof(fence));
kbase_tlstream_msgbuf_release(stream, acq_flags);
}
يكشف استغلال إثبات المفهوم عن عنوان كائن `kbase_kcpu_command_queue` من خلال مراقبة معرف الرسالة `KBASE_TL_KBASE_NEW_KCPUQUEUE` الذي يتم إرساله بواسطة الدالة `kbasep_kcpu_queue_new` كلما تم تخصيص كائن طابور kcpu جديد.
أبلغني Google أن الثغرة تم الإبلاغ عنها في مارس 2023 وتم تعيينها [CVE-2023-26083](https://source.android.com/docs/security/bulletin/2023-07-01) في نشرة الأمان الخاصة به. ومع ذلك، تمكنت من تكرار المشكلة على أحدث أجهزة Pixel التي تم تزويدها بمستويات تصحيح الأمان (SPL) لشهر أكتوبر ونوفمبر، مما يشير إلى أن الإصلاح لم يتم تطبيقه بشكل صحيح أو لم يتم تطبيقه على الإطلاق. بعد ذلك، عالجت Google المشكلة بسرعة في نشرة تحديث الأمان لشهر ديسمبر دون منح الفضل، وأخبرتني لاحقًا أن المشكلة اعتُبرت مكررة. لكن المبرر وراء تصنيف هذه المشكلة على أنها مكررة لا يزال موضع تساؤل.
## الاستغلال
---
إذن لدي ثغرتان مثيرتان للاهتمام. الأولى توفر قدرة قوية على تعديل محتوى أي عنوان نواة محاذٍ لـ 16 بايت يقع قبل عنوان ~buff~ المخصص. أما الثغرة الثانية فتوفر تلميحات حول المواقع المحتملة للكائنات داخل ذاكرة النواة.