
CVE-2018-4280: iOS 11.2.6 पर launchd में Mach port प्रतिस्थापन भेद्यता जो सैंडबॉक्स एस्केप, विशेषाधिकार वृद्धि और कोडसाइनिंग बाईपास की ओर ले जाती है।
Blanket एक सैंडबॉक्स एस्केप है जो iOS 11.2.6 को लक्षित करता है, हालांकि मुख्य कमजोरी को केवल iOS 11.4.1 में पैच किया गया था। यह launchd में एक Mach पोर्ट रिप्लेसमेंट कमजोरी (CVE-2018-4280) का शोषण करता है, साथ ही अन्य सेवाओं में कई छोटी कमजोरियों का, ReportCrash प्रक्रिया के अंदर कोड निष्पादित करने के लिए, जो बिना सैंडबॉक्स के है, रूट के रूप में चलती है, और इसमें task_for_pid-allow एंटाइटलमेंट है। यह blanket को फोन पर चलने वाली हर प्रक्रिया पर नियंत्रण प्रदान करता है, जिसमें amfid जैसी सुरक्षा-महत्वपूर्ण प्रक्रियाएं भी शामिल हैं।
एक्सप्लॉइट में कई चरण शामिल हैं। यह README मुख्य कमजोरी और सैंडबॉक्स एस्केप के चरणों को चरण-दर-चरण समझाएगा।
iOS पर क्रैश रिपोर्टिंग पर शोध करते समय, मैंने launchd में एक Mach पोर्ट रिप्लेसमेंट कमजोरी की खोज की। एक विशेष तरीके से क्रैश होने पर, एक प्रक्रिया कर्नेल को launchd को एक Mach संदेश भेजने के लिए प्रेरित कर सकती है, जिससे launchd अपने IPC नेमस्पेस में एक Mach पोर्ट के लिए एक भेजने के अधिकार को अधिक-डीलोकेट कर देता है। यह एक हमलावर को किसी भी launchd सेवा का प्रतिरूपण करने की अनुमति देता है जिसे वह सिस्टम के बाकी हिस्सों में देख सकता है, जो विशेषाधिकार वृद्धि के लिए कई रास्ते खोलता है।
यह कमजोरी macOS पर भी मौजूद है, लेकिन iOS पर कमजोरी को ट्रिगर करना अधिक कठिन है क्योंकि launchd में जांच होती है जो सुनिश्चित करती है कि Mach अपवाद संदेश कर्नेल से आता है।
Launchd अपने मुख्य पोर्ट पर कई अलग-अलग Mach संदेश हैंडलरों को मल्टीप्लेक्स करता है, जिसमें अपवाद संदेशों के लिए एक MIG हैंडलर भी शामिल है। यदि कोई प्रक्रिया अपने स्वयं के बूटस्ट्रैप पोर्ट पर mach_exception_raise या mach_exception_raise_state_identity संदेश भेजती है, तो launchd उस संदेश को होस्ट-स्तरीय अपवाद के रूप में प्राप्त और संसाधित करेगा।
दुर्भाग्य से, इन संदेशों को संभालने में launchd का व्यवहार बगी है। यदि अपवाद प्रकार EXC_CRASH है, तो launchd संदेश में भेजे गए थ्रेड और टास्क पोर्ट को डीलोकेट करेगा और फिर सेवा रूटीन से KERN_FAILURE लौटाएगा, जिससे MIG सिस्टम थ्रेड और टास्क पोर्ट को फिर से डीलोकेट करेगा। (धारणा यह है कि यदि कोई सेवा रूटीन सफलता लौटाती है, तो उसने Mach संदेश में सभी संसाधनों का स्वामित्व ले लिया है, जबकि यदि सेवा रूटीन त्रुटि लौटाती है, तो उसने कोई भी संसाधन नहीं लिया है।)
यहाँ launchd की mach_exception_raise संदेशों के लिए सेवा रूटीन का कोड है, जिसे IDA/Hex-Rays का उपयोग करके डीकंपाइल किया गया है और पठनीयता के लिए हल्के से संपादित किया गया है:```C
kern_return_t __fastcall
catch_mach_exception_raise( // (a) The service routine is
mach_port_t exception_port, // called with values directly
mach_port_t thread, // from the Mach message
mach_port_t task, // sent by the client. The
exception_type_t exception, // thread and task ports could
mach_exception_data_t code, // be arbitrary send rights.
mach_msg_type_number_t codeCnt)
{
__int64 __stack_guard; // ST28_8@1
kern_return_t kr; // w0@1 MAPDST
kern_return_t result; // w0@4
__int64 codes_left; // x25@6
mach_exception_data_type_t code_value; // t1@7
int pid; // [xsp+34h] [xbp-44Ch]@1
char codes_str[1024]; // [xsp+38h] [xbp-448h]@7
__stack_guard = *__stack_chk_guard_ptr;
pid = -1;
kr = pid_for_task(task, &pid);
if ( kr )
{
_os_assumes_log(kr);
_os_avoid_tail_call();
}
if ( current_audit_token.val[5] ) // (b) If the message was sent by
{ // a process with a nonzero PID
result = KERN_FAILURE; // (any non-kernel process),
} // the message is rejected.
else
{
if ( codeCnt )
{
codes_left = codeCnt;
do
{
code_value = *code;
++code;
__snprintf_chk(codes_str, 0x400uLL, 0, 0x400uLL, "0x%llx", code_value);
--codes_left;
}
while ( codes_left );
}
launchd_log_2(
0LL,
3LL,
"Host-level exception raised: pid = %d, thread = 0x%x, "
"exception type = 0x%x, codes = { %s }",
pid,
thread,
exception,
codes_str);
kr = deallocate_port(thread); // (c) The "thread" port sent in
if ( kr ) // the message is deallocated.
{
_os_assumes_log(kr);
_os_avoid_tail_call();
}
kr = deallocate_port(task); // (d) The "task" port sent in the
if ( kr ) // message is deallocated.
{
_os_assumes_log(kr);
_os_avoid_tail_call();
}
if ( exception == EXC_CRASH ) // (e) If the exception type is
result = KERN_FAILURE; // EXC_CRASH, then KERN_FAILURE
else // is returned. MIG will
result = 0; // deallocate the ports again.
}
*__stack_chk_guard_ptr;
return result;
}
यह कोड वास्तव में क्या करता है:
1. यह फ़ंक्शन `mach_exception_raise` अपवाद संदेशों के लिए Mach सेवा दिनचर्या है: यह सीधे Mach सिस्टम द्वारा तब लागू किया जाता है जब launchd `mach_exception_raise` Mach अपवाद संदेश को संसाधित करता है। सेवा दिनचर्या के तर्क Mach संदेश से पार्स किए जाते हैं, और इसलिए संदेश भेजने वाले द्वारा नियंत्रित होते हैं।
2. (b) पर, launchd जाँचता है कि Mach अपवाद संदेश केर्नल द्वारा भेजा गया था या नहीं। प्रेषक के ऑडिट टोकन में फ़ील्ड 5 में भेजने वाली प्रक्रिया का PID होता है, जो केवल केर्नल के लिए शून्य होगा। यदि संदेश केर्नल द्वारा नहीं भेजा गया, तो इसे अस्वीकार कर दिया जाता है।
3. संदेश से थ्रेड और टास्क पोर्ट को (c) और (d) पर स्पष्ट रूप से डीलोकेट किया जाता है।
4. (e) पर, launchd जाँचता है कि अपवाद प्रकार `EXC_CRASH` है या नहीं, और यदि ऐसा है तो `KERN_FAILURE` लौटाता है। इसका उद्देश्य यह सुनिश्चित करना है कि `EXC_CRASH` संदेशों को न संभाला जाए, संभवतः ताकि ReportCrash को कॉर्प्स हैंडलर के रूप में लागू किया जा सके। हालांकि, इस बिंदु पर `KERN_FAILURE` लौटाने से बाद में अपवाद संदेश को साफ करते समय टास्क और थ्रेड पोर्ट फिर से डीलोकेट हो जाएंगे। इसका मतलब है कि ये दो पोर्ट ओवर-डीलोकेट हो जाएंगे।
इस भेद्यता के उपयोगी होने के लिए, हम launchd के एक Mach सेवा के लिए भेजने के अधिकार को मुक्त करना चाहेंगे, ताकि हम फिर उस सेवा का रूप धारण कर सकें और सिस्टम के बाकी हिस्सों से संवाद कर सकें। इसका मतलब है कि हमें अपवाद संदेश में टास्क और थ्रेड पोर्ट को वास्तव में उस Mach सेवा पोर्ट के लिए भेजने के अधिकार के रूप में चाहिए जिसे हम launchd में मुक्त करना चाहते हैं। फिर, एक बार जब हम launchd को दुर्भावनापूर्ण अपवाद संदेश भेजकर सेवा पोर्ट को मुक्त कर देते हैं, तो हम उसी पोर्ट नाम को पुनः उपयोग करने का प्रयास करेंगे, लेकिन इस बार एक ऐसे Mach पोर्ट के लिए जिसके लिए हमें प्राप्त करने का अधिकार है। इस तरह, जब कोई क्लाइंट launchd से सेवा के लिए Mach पोर्ट पर भेजने का अधिकार मांगता है, तो launchd उसके बजाय हमारे पोर्ट पर भेजने का अधिकार देगा, जिससे हम क्लाइंट के सामने उस सेवा का रूप धारण कर सकते हैं। उसके बाद, सिस्टम विशेषाधिकार प्राप्त करने के कई अलग-अलग तरीके हैं।
### भेद्यता को ट्रिगर करना