
CVE-2016-6187 के लिए कर्नेल शोषण (स्थानीय विशेषाधिकार वृद्धि)
CVE-2016-6187 के लिए कर्नेल एक्सप्लॉइट (स्थानीय विशेषाधिकार वृद्धि) (प्रभावित संस्करण: < 4.6.5)
एक्सप्लॉइट को एक कस्टम संकलित 4.6 कर्नेल + बिल्डरूट के विरुद्ध विकसित किया गया था (kconfig जल्द ही आ रहा है)
और KASLR, SMEP, SMAP को बायपास करता है (KPTI 4.6 के लिए उपलब्ध नहीं है)
शोषित भेद्यता AppArmor के LSM हुक (setprocattr) में एक हीट-आधारित सिंगल नलबाइट ओवरफ्लो है। देखें https://nvd.nist.gov/vuln/detail/CVE-2016-6187
प्रारंभिक माप 94.44% संभावना दर्शाते हैं कि रूट शेल प्राप्त होगा। 18 में से 1 मामले में, एक्सप्लॉइट कर्नेल को oops कर देगा। रूट एक्सेस प्राप्त करने के बाद कर्नेल को पूरी तरह से स्थिर करने के लिए और कार्य की आवश्यकता है।
हम kmalloc-128 में फ्रीलिस्ट पॉइंटर के LSB को भ्रष्ट करने के लिए नलबाइट ओवरफ्लो का दुरुपयोग करते हैं, जिससे यह
एक पहले से आवंटित ऑब्जेक्ट की ओर इंगित करता है। उसके बाद, हम उस आवंटित ऑब्जेक्ट को मुक्त करते हैं, जिससे डबल फ्री की स्थिति उत्पन्न होती है।
अब हम kmalloc-128 कैश से दो ओवरलैपिंग संरचनाएँ आवंटित कर सकते हैं। पहली संरचना एक ऑब्जेक्ट है
जिसकी सामग्री को उपयोगकर्ता-स्थान द्वारा वापस पढ़ा जा सकता है। इसके लिए, मैंने ip6_sf_socklist चुना है। दूसरी संरचना,
जो ip6_sf_socklist के शीर्ष पर आवंटित की जाएगी, में कर्नेल पॉइंटर्स होने चाहिए - rfkill_data एक अच्छा फिट है।
इसमें एक हीट पॉइंटर (खाली rfkill_data.events सूची) और एक वैश्विक डेटा पॉइंटर rfkill_fds (rfkill_data.list.prev) होता है।
एक बार rfkill_data को ip6_sf_socklist के शीर्ष पर आवंटित करने के बाद, हम getsockopt(sock, IPPROTO_IPV6, MCAST_MSFILTER, gsf, &optlen) को कॉल करके कर्नेल पॉइंटर्स प्राप्त कर सकते हैं। कर्नेल टेक्स्ट बेस को तब rfkill_fds से प्राप्त किया जा सकता है।
फिर हम एक दूसरी डबल फ्री स्थिति उत्पन्न करते हैं, लेकिन इस बार हम फ्रीलिस्ट पॉइंटर को ओवरराइट करने के लिए संदेश कतार की लिंकिंग प्रक्रिया का दुरुपयोग करते हैं और एलोकेटर को धोखा देते हैं कि वह हमें kmalloc-96 से एक चंक लौटाए जब हम वास्तव में kmalloc-128 से एक चंक का अनुरोध कर रहे हैं।
हम तब आकार की असंगति का लाभ उठाकर kmalloc-96 चंक के फ्रीलिस्ट पॉइंटर में ओवरफ्लो कर सकते हैं, जिससे हमें मनमाने पतों को आवंटित करने का आदिम प्राप्त होता है। हमारे मामले में, हम ptmx_fops संरचना के लिए जाते हैं और ptmx_fops.unlocked_ioctl कॉलबैक को अपने स्टैक पिवट गैजेट के पॉइंटर से ओवरराइट करते हैं।
/dev/ptmx पर ioctl कॉल करने से पिवट गैजेट सक्रिय होता है और हम स्टैक को kmalloc-128 में एक नकली स्टैक पर ले जाते हैं जहाँ हमने पहले से अपनी पहली चरण की ROP श्रृंखला तैयार की है।
चूंकि हमारे पास kmalloc-128 नकली स्टैक पर सीमित स्थान है (हम नहीं जानते कि अगला चंक उसी slab पर होगा या नहीं), पहली चरण की ROP श्रृंखला का कार्य उपयोगकर्ता-स्थान से दूसरी चरण की ROP श्रृंखला को कर्नेल dmesg लॉग बफर (__log_buf) में कॉपी करना और स्टैक को __log_buf पर ले जाना है।
दूसरी चरण की ROP श्रृंखला तब विशेषाधिकार बढ़ाने के लिए commit_creds(prepare_kernel_cred(NULL)) को कॉल करने से पहले कर्नेल की मरम्मत (ptmx_fops को पुनर्स्थापित करना, ...) करने का प्रयास करती है।
और अंत में यह iretq के माध्यम से कर्नेलस्पेस से बाहर निकलता है और हम, बढ़े हुए विशेषाधिकारों के साथ, अपने execve("/bin/sh", 0, 0) उपप्रोग्राम पर लौटते हैं।
गैर-विशेषाधिकार प्राप्त उपयोगकर्ताओं को कम से कम /dev/rfkill खोलने में सक्षम होना चाहिए। कुछ डिस्ट्रो इसकी अनुमति नहीं दे सकते हैं। मैंने Ubuntu और Fedora की जाँच की है, दोनों गैर-विशेषाधिकार प्राप्त उपयोगकर्ताओं को /dev/rfkill खोलने की अनुमति देते हैं (हालांकि Fedora AppArmor के बजाय SELinux का उपयोग कर रहा है)।
निम्न अनुभाग qemu-x86_64 में स्थानीय विशेषाधिकार वृद्धि को पुन: उत्पन्न करने का तरीका बताता है।
पहले, आपको initrd और bzImage कर्नेल प्राप्त करना होगा। दो तरीके हैं:
सबसे आसान और तेज़ तरीका। आप सभी आवश्यक घटकों को prebuilt/ में पा सकते हैं।
या, वैकल्पिक रूप से, आप घटकों को स्वयं भी बना सकते हैं। बस 4.6 कर्नेल प्राप्त करें और config/ में दिए गए x86_64_vuln_kern_defconfig का उपयोग करके bzImage को संकलित करें।
initrd के लिए, उदाहरण के लिए, आप buildroot का उपयोग कर सकते हैं। बस अपने init में /dev/rfkill के लिए सही अनुमतियाँ सेट करना सुनिश्चित करें
chmod 664 /dev/rfkill
यह Ubuntu-16.04 और कई अन्य डिस्ट्रो के समान है। साथ ही, एक्सप्लॉइट को संकलित करना और इसे अपने initrd में डालना न भूलें
make
एक बार जब आप घटकों को प्राप्त कर लें, तो असुरक्षित मशीन को बूट करें
./boot.sh <path/to/bzImage> <path/to/rootfs.cpio>
और एक्सप्लॉइट निष्पादित करें
./exploit
आपको एक्सप्लॉइट को कई बार चलाने की आवश्यकता हो सकती है, यह इस बात पर निर्भर करता है कि क्या हमने पहले से शून्य LSB को null किया है। यह भी ध्यान दें कि रूट एक्सेस प्राप्त करने के बाद भी क्रैश होने की थोड़ी संभावना (शायद 10%-20%?) है - मैं इस पर काम कर रहा हूँ।
मज़े करें।
ptmx_fops की मरम्मत करेंkmalloc-128 फ्रीलिस्ट की मरम्मत करें