
CVE-2023-20938 के लिए स्थानीय विशेषाधिकार वृद्धि प्रमाण-अवधारणा, एंड्रॉइड बाइंडर में उपयोग-के-बाद-मुक्त, कमजोर परीक्षण बिल्ड पर रूट प्राप्त करना और SELinux अक्षम करना।
यह CVE-2023-20938 के लिए एक स्थानीय विशेषाधिकार वृद्धि प्रूफ-ऑफ-कॉन्सेप्ट है, जो Android बाइंडर ड्राइवर में एक use-after-free दोष है। एक अनप्रिविलेज्ड शेल से यह uid 0 प्राप्त करता है और SELinux को permissive पर सेट करता है, फिर एक रूट शेल लॉन्च करता है।
इस बिल्ड का लक्ष्य: Android Cuttlefish / Goldfish AVD, x86_64, कर्नेल 5.10.107।
⚠️ केवल अधिकृत अनुसंधान / शैक्षिक उपयोग के लिए। इसे केवल अपने स्वयं के परीक्षण उपकरणों और एमुलेटरों पर चलाएं। यह बग वर्तमान Android में ठीक कर दिया गया है; यह PoC एक पुराने, जानबूझकर कमजोर परीक्षण बिल्ड को लक्षित करता है। कोई वारंटी नहीं।

रिकॉर्ड किया गया 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 के refcount को अत्यधिक घटाने, इसे मुक्त करने का कारण बनता है जबकि एक डेंगलिंग संदर्भ अभी भी जीवित है।
एक्सप्लॉइट एक क्रॉस-कैश लीक को एक आर्बिट्रेरी रीड और एक नियंत्रित राइट में जोड़ता है, फिर क्रेडेंशियल्स को फिर से लिखता है। चरण दर चरण (poc_cf.c में main() देखें):
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.
UAF को चलाने के लिए दो अनप्रिविलेज्ड प्रक्रियाओं को एक binder node साझा करने की आवश्यकता होती है; hwservicemanager के ITokenManager (createToken /get-by-token) के माध्यम से।
clang -static -Wall -Wextra -o poc_cf poc_cf.c -lpthread
binder.h को poc_cf.c के साथ होना चाहिए। बिल्ड जानबूझकर स्टैटिक है ताकि एकल बाइनरी बिना किसी टूलचेन के लक्ष्य पर चल सके।
अपने Cuttlefish होस्ट पैकेज निर्देशिका से, मैचिंग कर्नेल + इनिट्रामफ्स के साथ AVD लॉन्च करें:
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
एक सफल रन चरणों से गुज़रता है और एक रूट शेल में समाप्त होता है:
यह एक्सप्लॉइट संभाव्य (प्रोबेबिलिस्टिक) है। प्रत्येक चरण आंतरिक रूप से पुनः प्रयास करता है।
इसलिए चाहे आप एक साफ बेल (clean bail) देखें या गेस्ट पैनिक, बस फिर से चलाएं (AVD का /data रीबूट पर मिट जाता है, इसलिए पैनिक के बाद बाइनरी को फिर से पुश करें)।
यदि धीमे या व्यस्त लक्ष्य पर रिक्लेम हिट-रेट खराब है, तो प्रतीक्षा समय को बढ़ाएं या स्प्रे काउंट बढ़ाएं (poc_cf.c के शीर्ष के पास #defines):
स्ट्रक्ट ऑफसेट और अनरैंडमाइज्ड सिंबल बेसलाइन (*_NOKASLR) इस विशेष 5.10.107 बिल्ड के लिए विशिष्ट हैं और कहीं और काम नहीं करेंगे। किसी भिन्न कर्नेल पर पोर्ट करने के लिए, poc_cf.c के शीर्ष के पास ऑफसेट ब्लॉक और सिंबल ब्लॉक को मैचिंग vmlinux के मानों से अपडेट करें। मैंने इसे Pixel 7 पर ऑफसेट निकालने के बाद आज़माया।
Google का Android Offensive Security ब्लॉग [https://androidoffsec.withgoogle.com/posts/attacking-android-binder-analysis-and-exploitation-of-cve-2023-20938/]
| Macro | Default | Meaning |
|---|
SETTLE_US | 5000 | नोड मुक्त होने के बाद, स्प्रे करने से पहले रुकें |
FAKE_SPRAY_COUNT | 8 | रिक्लेम करने के लिए प्रतिस्पर्धा कर रहे अवरुद्ध sendmsg() कॉल्स |
FAKE_WAIT_US | 10000 | स्प्रे जारी करने के बाद, अनलिंक से पहले रुकें |
PRESKIP_US | 1000 | बलिदानी पहले sendmsg के बाद रुकें |
KW_RETRY_COUNT | 8 | प्रति एकल अनलिंक राइट प्रयास |
STAGE_C_TRIES | 8 | आर्बिट्रेरी-रीड ऑनलाइन लाने के प्रयास |