
إثبات مفهوم لتصعيد الامتيازات المحلية لـ CVE-2023-20938، استخدام بعد التحرير في Android binder، يحقق الجذر ويعطل SELinux على إصدارات الاختبار الضعيفة.
إثبات مفهوم لتصعيد امتيازات محلي لثغرة CVE-2023-20938، وهي ثغرة استخدام بعد التحرير (use-after-free) في مشغّل binder في أندرويد. من قشرة shell بصلاحيات غير مميزة يكتسب uid 0 ويخفض SELinux إلى الوضع المتساهل، ثم يطلق قشرة shell بصلاحيات الجذر.
هدف هذا البناء: Android Cuttlefish / Goldfish AVD، x86_64، نواة 5.10.107.
⚠️ للاستخدام البحثي / التعليمي المصرّح به فقط. شغّل هذا فقط على أجهزة الاختبار والمحاكيات الخاصة بك. الثغرة مُصلَحة في أندرويد الحالي؛ هذا إثبات المفهوم يستهدف بناء اختبار قديماً وهشّاً عمداً. بدون أي ضمان.

تم التسجيل باستخدام asciinema وتحويله إلى GIF باستخدام
agg:
drivers/android/binder.c, binder_transaction_buffer_release()الدالة binder_transaction_buffer_release() تثق في offsets_size الذي يقدّمه
المهاجم. إرسال معاملة يكون فيها offsets_size أقصر ببايت واحد من إدخال كامل
(sizeof(offset) - 1 == 7) يجعل مسار التحرير يخطئ في تحليل
flat_binder_object الختامي ويُفرط في إنقاص عداد مراجع binder_node،
محرّراً إياه بينما لا يزال هناك مرجع معلّق نشط.
يحوّل الاستغلال تسريباً عبر التخزين المؤقت (cross-cache) إلى قراءة عشوائية
وكتابة محكومة، ثم يعيد كتابة بيانات الاعتماد. مرحلة بمرحلة (انظر main() في
poc_cf.c):
B. Cross-cache leak
free a wave of binder_nodes (kmalloc-128) -> page returns to the buddy
allocator -> reclaim the page with eventpoll epitems (eventpoll_epi cache,
0x80-byte objects). A dangling binder transaction now reads kernel
pointers out of an epitem, leaking a struct file and its epitem address.
C. Arbitrary read
re-trigger the UAF and use a sprayed fake binder_node to turn binder's
hlist_del unlink into a controlled *(where) = what write. Two writes
redirect a victim file's f_inode at a fake inode overlaid on the epitem
and mark it S_PRIVATE. FIGETBSZ on the file then returns
*(epitem.event.data + 24): a steerable 4-byte read.
D/E/F. Privilege escalation
defeat KASLR (leak eventfd_fops via f_op), walk init_task's task list to
the launcher's cred, zero its uid/gid set and seccomp.mode, then zero
selinux_state to drop SELinux to permissive.
G. A pre-forked, eventfd-free launcher execs a root shell.
تحتاج عمليتان بصلاحيات غير مميزة إلى مشاركة عقدة binder لقيادة استغلال UAF؛
عبر ITokenManager الخاص بـ hwservicemanager (createToken /get-by-token).
clang -static -Wall -Wextra -o poc_cf poc_cf.c -lpthread
يجب أن يكون binder.h بجوار poc_cf.c. البناء ثابت (static) عن قصد حتى
يعمل الملف الثنائي المفرد على الهدف دون وجود سلسلة أدوات (toolchain).
من دليل حزمة مضيف Cuttlefish لديك، شغّل الـ AVD مع النواة و initramfs المطابقين:
HOME=$PWD ./bin/launch_cvd \
--kernel_path=bzImage \
--initramfs_path=initramfs.img
adb push poc_cf /data/local/tmp/
adb shell /data/local/tmp/poc_cf
يمر التشغيل الناجح عبر المراحل وينتهي بقشرة shell بصلاحيات الجذر:
الاستغلال احتمالي. كل مرحلة تعيد المحاولة داخلياً.
لذا سواء رأيت خروجاً نظيفاً أو انهياراً (panic) للضيف، فقط أعد التشغيل
(يتم مسح /data في الـ AVD عند إعادة الإقلاع، لذا أعد دفع الملف الثنائي بعد
أي انهيار).
إذا كان معدل نجاح استرداد الصفحات ضعيفاً على هدف أبطأ أو أكثر ازدحاماً، فوسّع
فترات الانتظار أو ارفع عدد الرشّ (تعريفات #defines قرب أعلى poc_cf.c):
إزاحات البنى وخط الأساس الرمزي دون تعشية (*_NOKASLR) خاصة بهذا البناء
5.10.107 بالضبط ولن تعمل في أي مكان آخر. لنقل الاستغلال إلى نواة مختلفة،
حدّث كتلة الإزاحات وكتلة الرموز قرب أعلى poc_cf.c بقيم من vmlinux
المطابق. لقد جرّبته على Pixel 7 بعد استخراج الإزاحات.
| الماكرو | الافتراضي | المعنى |
|---|
SETTLE_US | 5000 | توقّف بعد تحرير العقدة، قبل الرشّ |
FAKE_SPRAY_COUNT | 8 | استدعاءات sendmsg()s المحجوبة التي تتسابق على استرداد الفتحة |
FAKE_WAIT_US | 10000 | توقّف بعد إطلاق الرشّات، قبل إجراء unlink |
PRESKIP_US | 1000 | توقّف بعد أول sendmsg مُضحًّى به |
KW_RETRY_COUNT | 8 | محاولات لكل كتابة unlink واحدة |
STAGE_C_TRIES | 8 | محاولات لتفعيل القراءة العشوائية |