Fuzzilli
गतिशील भाषा इंटरप्रेटरों के लिए एक (कवरेज-निर्देशित) फजर, जो एक कस्टम मध्यवर्ती भाषा ("FuzzIL") पर आधारित है, जिसे उत्परिवर्तित (mutate) कर जावास्क्रिप्ट में अनुवादित किया जा सकता है।
उपयोग
इस फजर का उपयोग करने के मूल चरण हैं:
- समर्थित जावास्क्रिप्ट इंजनों में से किसी एक का स्रोत कोड डाउनलोड करें। समर्थित जावास्क्रिप्ट इंजनों की सूची के लिए Targets/ निर्देशिका देखें।
- लक्ष्य की निर्देशिका से संबंधित पैच लागू करें। उस निर्देशिका में README.md भी देखें।
- कवरेज इंस्ट्रूमेंटेशन के साथ इंजन को संकलित करें (क्लैंग >= 4.0 की आवश्यकता है) जैसा कि README में वर्णित है।
- फजर को संकलित करें:
swift build [-c release].
- फजर चलाएँ:
swift run [-c release] FuzzilliCli --profile=<profile> [अन्य क्ली विकल्प] /path/to/jsshell. यह भी देखें swift run FuzzilliCli --help।
फजली और समर्थित जावास्क्रिप्ट इंजनों को डॉकर और Google Compute Engine के अंदर बनाना और चलाना भी समर्थित है।
हैकिंग
Fuzzilli लाइब्रेरी के उपयोग का एक उदाहरण देखने और विभिन्न कॉन्फ़िगरेशन विकल्पों के साथ खेलने के लिए main.swift देखें। इसके बाद, उच्च-स्तरीय फजिंग लॉजिक के लिए Fuzzer.swift देखें। वहाँ से किसी भी दिलचस्प हिस्से में गोता लगाएँ।
इस परियोजना में पैच, परिवर्धन, अन्य योगदान आदि का बहुत स्वागत है! हालाँकि, योगदानकर्ताओं के लिए नोट्स जल्दी से देख लें। Fuzzilli मोटे तौर पर Google के Swift के लिए कोड शैली गाइड का अनुसरण करता है।
यदि आप इस परियोजना की मदद से पाई गई किसी भेद्यता के लिए [email protected] पर एक संक्षिप्त नोट (संभवतः CVE नंबर सहित) भेज सकते हैं या एक पुल अनुरोध खोल सकते हैं तो बहुत सराहना की जाएगी ताकि इसे बग शोकेस अनुभाग में शामिल किया जा सके। इसके अलावा आप निश्चित रूप से किसी भी बग बाउंटी, CVE क्रेडिट आदि का दावा कर सकते हैं :)
अवधारणा
जब मुख्य इंटरप्रेटर बग, जैसे कि JIT कंपाइलर में, के लिए फजिंग की जाती है, तो उत्पन्न प्रोग्रामों की सिमैंटिक शुद्धता एक चिंता का विषय बन जाती है। यह अधिकांश अन्य परिदृश्यों के विपरीत है, उदाहरण के लिए रनटाइम API की फजिंग, जहाँ सिमैंटिक शुद्धता को जनरेटेड कोड को try-catch कंस्ट्रक्ट में लपेटकर आसानी से दरकिनार किया जा सकता है। स्वीकार्य दर पर सिमैंटिकली सही नमूने प्राप्त करने के लिए अलग-अलग संभावनाएँ हैं, उनमें से एक उत्परिवर्तन दृष्टिकोण है जिसमें कोष में सभी नमूने भी सिमैंटिकली मान्य होते हैं। उस स्थिति में, प्रत्येक उत्परिवर्तन में एक मान्य नमूने को अमान्य में बदलने की संभावना कम होती है।
एक उत्परिवर्तन-आधारित जावास्क्रिप्ट फजर को लागू करने के लिए, जावास्क्रिप्ट कोड पर उत्परिवर्तन को परिभाषित करना होता है। किसी प्रोग्राम के AST या अन्य सिंटैक्टिक तत्वों को उत्परिवर्तित करने के बजाय, एक कस्टम मध्यवर्ती भाषा (IL) को परिभाषित किया जाता है जिस पर प्रोग्राम के नियंत्रण और डेटा प्रवाह में उत्परिवर्तन अधिक सीधे किए जा सकते हैं। इस IL का बाद में निष्पादन के लिए जावास्क्रिप्ट में अनुवाद किया जाता है। मध्यवर्ती भाषा मोटे तौर पर इस प्रकार दिखती है:
v0 <− LoadInteger '0'
v1 <− LoadInteger '10'
v2 <− LoadInteger '1'
v3 <− LoadInteger '0'
BeginFor v0, '<', v1, '+', v2 −> v4
v6 <− BinaryOperation v3, '+', v4
Reassign v3, v6
EndFor
v7 <− LoadString 'Result: '
v8 <− BinaryOperation v7, '+', v3
v9 <− LoadGlobal 'console'
v10 <− CallMethod v9, 'log', [v8]
जिसे आसानी से निम्नलिखित जावास्क्रिप्ट कोड में अनुवादित किया जा सकता है:
const v0 = 0;
const v1 = 10;
const v2 = 1;
let v3 = 0;
for (let v4 = v0; v4 < v1; v4 = v4 + v2) {
const v6 = v3 + v4;
v3 = v6;
}
const v7 = "Result: ";
const v8 = v7 + v3;
const v9 = console;
const v10 = v9.log(v8);
या मध्यवर्ती अभिव्यक्तियों को इनलाइन करके निम्नलिखित जावास्क्रिप्ट कोड में:
let v3 = 0;
for (let v4 = 0; v4 < 10; v4++) {
v3 = v3 + v4;
}
console.log("Result: " + v3);
FuzzIL में कई गुण हैं:
- एक FuzzIL प्रोग्राम केवल निर्देशों की एक सूची है।
- एक FuzzIL निर्देश एक ऑपरेशन है जिसमें इनपुट और आउटपुट वेरिएबल और संभावित रूप से एक या अधिक पैरामीटर (ऊपर के संकेतन में एकल उद्धरणों में) होते हैं।
- निर्देशों के इनपुट हमेशा वेरिएबल होते हैं, कोई तत्काल मान नहीं होते।
- एक निर्देश का प्रत्येक आउटपुट एक नया वेरिएबल होता है, और मौजूदा वेरिएबल को केवल समर्पित संचालन जैसे
Reassign निर्देश के माध्यम से पुन: असाइन किया जा सकता है।
- प्रत्येक वेरिएबल का उपयोग करने से पहले परिभाषित किया जाता है।
इन प्रोग्रामों पर कई उत्परिवर्तन किए जा सकते हैं:
- InputMutator: प्रोग्राम के डेटाफ्लो को उत्परिवर्तित करने के लिए निर्देशों के इनपुट वेरिएबल को अलग-अलग वेरिएबल से बदलता है।
- CodeGenMutator: कोड उत्पन्न करता है और उसे उत्परिवर्तित प्रोग्राम में कहीं सम्मिलित करता है। कोड या तो कोड जनरेटर चलाकर या कोष से किसी अन्य प्रोग्राम से कुछ निर्देशों की प्रतिलिपि बनाकर (स्प्लिसिंग) उत्पन्न किया जाता है।
- CombineMutator: कोष से एक प्रोग्राम को उत्परिवर्तित प्रोग्राम में एक यादृच्छिक स्थान पर सम्मिलित करता है।
- OperationMutator: संचालन के पैरामीटर को उत्परिवर्तित करता है, उदाहरण के लिए एक पूर्णांक स्थिरांक को एक अलग से बदलना।
- और भी बहुत कुछ...
Fuzzilli कैसे काम करता है इसकी अधिक विस्तृत चर्चा यहाँ पाई जा सकती है।
कार्यान्वयन
फजर Swift में लागू किया गया है, जिसमें कुछ भाग (जैसे कवरेज माप, सॉकेट इंटरैक्शन, आदि) C में लागू किए गए हैं।
आर्किटेक्चर
एक फजर इंस्टेंस (Fuzzer.swift में लागू) निम्नलिखित केंद्रीय घटकों से बना होता है:
- MutationFuzzer: उत्परिवर्तन लागू करके मौजूदा प्रोग्रामों से नए प्रोग्राम तैयार करता है। बाद में उत्पादित नमूनों को निष्पादित करता है और उनका मूल्यांकन करता है।
- ScriptRunner: लक्ष्य भाषा के प्रोग्राम निष्पादित करता है।
- Corpus: दिलचस्प नमूनों को संग्रहीत करता है और उन्हें कोर फजर को प्रदान करता है।
- Environment: रनटाइम वातावरण का ज्ञान रखता है, जैसे उपलब्ध बिल्टिन, प्रॉपर्टी नाम और विधियाँ।
- Minimizer: क्रैश और दिलचस्प प्रोग्राम को छोटा करता है।
- Evaluator: मूल्यांकन करता है कि क्या कोई नमूना किसी मीट्रिक, जैसे कोड कवरेज, के अनुसार दिलचस्प है।
- Lifter: FuzzIL प्रोग्राम को लक्ष्य भाषा (जावास्क्रिप्ट) में अनुवादित करता है।
इसके अलावा, कई मॉड्यूल वैकल्पिक रूप से उपलब्ध हैं:
- Statistics: विभिन्न सांख्यिकीय जानकारी एकत्र करता है।
- NetworkSync: नेटवर्क पर कई इंस्टेंस को सिंक्रोनाइज़ करता है।
- ThreadSync: एक ही प्रक्रिया में कई इंस्टेंस को सिंक्रोनाइज़ करता है।
- Storage: क्रैश होने वाले प्रोग्राम को डिस्क पर संग्रहीत करता है।
फजर इवेंट-चालित है, जिसमें विभिन्न वर्गों के बीच अधिकांश इंटरैक्शन इवेंट के माध्यम से होते हैं। इवेंट उदाहरण के लिए क्रैश या एक दिलचस्प प्रोग्राम मिलने, एक नया प्रोग्राम निष्पादित होने, एक लॉग संदेश उत्पन्न होने आदि के परिणामस्वरूप प्रेषित होते हैं। इवेंट की पूरी सूची के लिए Events.swift देखें। इवेंट तंत्र प्रभावी रूप से फजर के विभिन्न घटकों को अलग करता है और अतिरिक्त मॉड्यूल को लागू करना आसान बनाता है।
एक FuzzIL प्रोग्राम को ProgramBuilder इंस्टेंस का उपयोग करके बनाया जा सकता है। ProgramBuilder नए निर्देश बनाने और जोड़ने, किसी अन्य प्रोग्राम से निर्देश जोड़ने, मौजूदा वेरिएबल प्राप्त करने, वर्तमान स्थिति (जैसे कि यह लूप के अंदर है या नहीं) पर निष्पादन संदर्भ क्वेरी करने, और अधिक के लिए विधियाँ प्रदान करता है।
निष्पादन
Fuzzilli REPRL (read-eval-print-reset-loop) नामक एक कस्टम निष्पादन मोड का उपयोग करता है। इसके लिए, लक्ष्य इंजन को पाइप और/या साझा मेमोरी पर एक स्क्रिप्ट इनपुट स्वीकार करने, उसे निष्पादित करने, फिर अपनी आंतरिक स्थिति को रीसेट करने और अगली स्क्रिप्ट की प्रतीक्षा करने के लिए संशोधित किया जाता है। यह प्रक्रिया निर्माण से ओवरहेड को हटाता है और बड़े पैमाने पर इंजन आरंभीकरण से।
मापनीयता
प्रति लक्ष्य प्रक्रिया में एक Fuzzer इंस्टेंस होता है। यह प्रोग्राम के समकालिक निष्पादन को सक्षम बनाता है और इस प्रकार लगातार उत्परिवर्तन और न्यूनतमकरण जैसे विभिन्न एल्गोरिदम के कार्यान्वयन को सरल बनाता है। इसके अलावा, यह कोष जैसी आंतरिक स्थिति में थ्रेड-सुरक्षित पहुँच को लागू करने की आवश्यकता से बचाता है। प्रत्येक फजर इंस्टेंस का अपना DispatchQueue होता है, जो वैचारिक रूप से एक एकल थ्रेड से मेल खाता है। एक सामान्य नियम के रूप में, एक Fuzzer इंस्टेंस के साथ प्रत्येक इंटरैक्शन उस इंस्टेंस की डिस्पैच क्यू पर होना चाहिए। यह थ्रेड-सुरक्षा की गारंटी देता है क्योंकि क्यू सीरियल है। अधिक विवरण के लिए दस्तावेज़ देखें।
पैमाने के लिए, फजर इंस्टेंस एक ट्री पदानुक्रम बना सकते हैं, जिस स्थिति में वे नए पाए गए दिलचस्प नमूनों और क्रैश को अपने पैरेंट नोड को रिपोर्ट करते हैं। बदले में, एक पैरेंट नोड अपने कोष को अपने चाइल्ड नोड के साथ सिंक्रोनाइज़ करता है। ट्री में नोड के बीच संचार विभिन्न तरीकों से हो सकता है, प्रत्येक को एक मॉड्यूल के रूप में लागू किया गया है:
- इंटर-थ्रेड संचार: अन्य फजर के DispatchQueue पर कार्यों को एनक्यू करके एक ही प्रक्रिया में इंस्टेंस को सिंक्रोनाइज़ करता है।
- इंटर-मशीन संचार: एक सरल TCP-आधारित प्रोटोकॉल पर इंस्टेंस को सिंक्रोनाइज़ करता है।
यह डिज़ाइन फजर को एक मशीन पर कई कोर के साथ-साथ कई अलग-अलग मशीनों पर स्केल करने की अनुमति देता है। चूँकि एक पैरेंट नोड जल्दी से ओवरलोड हो सकता है यदि बहुत सारे इंस्टेंस उसे प्रोग्राम भेजते हैं, तो इंस्टेंस के कई स्तरों को कॉन्फ़िगर करना संभव है, उदाहरण के लिए एक रूट इंस्टेंस, रूट से जुड़े 16 मध्यवर्ती नोड, और मध्यवर्ती नोड से जुड़े 256 "लीव्स"। वितरित फजिंग के बारे में अधिक जानकारी के लिए Cloud/ निर्देशिका देखें।
संसाधन
इस फजर के बारे में आगे के संसाधन:
- ऑफेंसिव कॉन 2019 में Fuzzilli पर दिया गया एक प्रेजेंटेशन।
- वह मास्टर्स थीसिस जिसके लिए प्रारंभिक कार्यान्वयन किया गया था।
- v8 में एक बग खोजने के लिए Fuzzilli का उपयोग करने पर Sensepost द्वारा एक ब्लॉगपोस्ट।
- JerryScript इंजन को Fuzzilli से फज करने पर Doyensec द्वारा एक ब्लॉगपोस्ट।
- Fuzzilli और अन्य फजरों से इसकी तुलना पर NDSS Symposium 2023 से एक पेपर।
बग शोकेस
निम्नलिखित Fuzzilli की मदद से पाए गए कुछ बगों की सूची है। इस सूची में केवल वे बग शामिल होने चाहिए जिनका सुरक्षा प्रभाव हो और जो प्रभावित सॉफ्टवेयर के कम से कम बीटा रिलीज में मौजूद हों। चूँकि Fuzzilli का उपयोग अक्सर विकास के दौरान निरंतर फज टेस्टिंग के लिए किया जाता है, इसलिए इसके द्वारा पाए गए कई मुद्दे इस सूची में शामिल नहीं हैं क्योंकि वे आमतौर पर कमजोर कोड के बीटा रिलीज तक पहुँचने से पहले पाए जाते हैं। हालाँकि, V8 में Fuzzilli द्वारा हाल ही में पाए गए सभी मुद्दों की सूची यहाँ पाई जा सकती है।
Fuzzilli का उपयोग करने वाले और इसके द्वारा पाए गए बगों की रिपोर्ट करने वाले सभी उपयोगकर्ताओं का विशेष धन्यवाद!
WebKit/JavaScriptCore
- Issue 185328: DFG कंपाइलर NumberIsInteger ऑपरेशन के लिए गलत आउटपुट रजिस्टर का उपयोग करता है
- CVE-2018-4299: performProxyCall आंतरिक ऑब्जेक्ट को स्क्रिप्ट में लीक करता है
- CVE-2018-4359: compileMathIC गलत मशीन कोड उत्पन्न करता है
- CVE-2019-8518: FTL JIT में LICM के कारण बाउंड्स चेक से पहले ऐरे एक्सेस को स्थानांतरित करने के कारण OOB एक्सेस
- CVE-2019-8558: डैंगलिंग Watchpoints के कारण CodeBlock UaF
- CVE-2019-8611: AIR ऑप्टिमाइज़ेशन रजिस्टर में असाइनमेंट को गलत तरीके से हटाता है
- CVE-2019-8623: DFG JIT में लूप-इनवेरिएंट कोड मोशन (LICM) स्टैक वेरिएबल को अप्रारंभीकृत छोड़ देता है
- CVE-2019-8622: DFG का doesGC() StringObjects पर HasIndexedProperty ऑपरेशन के व्यवहार के बारे में गलत है
- CVE-2019-8671: DFG: लूप-इनवेरिएंट कोड मोशन (LICM) ऑब्जेक्ट प्रॉपर्टी एक्सेस को असुरक्षित छोड़ देता है
- CVE-2019-8672: ValueProfiles में JSValue यूज़-आफ्टर-फ्री
- CVE-2019-8678: JSC कुछ प्रोटोटाइप संशोधित होने पर haveABadTime() चलाने में विफल रहता है, जिससे टाइप कन्फ्यूज़न होता है
- CVE-2019-8685: JSPropertyNameEnumerator गलत स्ट्रक्चर ID का उपयोग करता है
- CVE-2019-8765: DFG संकलन के दौरान GetterSetter टाइप कन्फ्यूज़न
- CVE-2019-8820: आर्गुमेंट्स ऑब्जेक्ट के पुनर्निर्माण के दौरान बेलआउट पर टाइप कन्फ्यूज़न
- CVE-2019-8844: ObjectAllocationSinkingPhase को उन आवंटनों के लिए संकेत नहीं डालने चाहिए जो अब मान्य नहीं हैं
Gecko/Spidermonkey
- CVE-2018-12386: IonMonkey रजिस्टर आवंटन बग टाइप कन्फ्यूज़न की ओर ले जाता है
- CVE-2019-9791: OSR के माध्यम से प्रवेश करने वाले कंस्ट्रक्टर के लिए IonMonkey का टाइप अनुमान गलत है
- CVE-2019-9792: IonMonkey JS_OPTIMIZED_OUT मैजिक वैल्यू को स्क्रिप्ट में लीक करता है
- CVE-2019-9816: ObjectGroupDispatch ऑपरेशन में अप्रत्याशित ObjectGroup
- CVE-2019-9813: IonMonkey संकलित कोड अनुमानित प्रॉपर्टी प्रकारों को अपडेट करने में विफल रहता है, जिससे टाइप कन्फ्यूज़न होता है
- CVE-2019-11707: IonMonkey Array.prototype.pop के रिटर्न प्रकार का गलत अनुमान लगाता है, जिससे टाइप कन्फ्यूज़न होता है
- CVE-2020-15656: IonMonkey में विशेष आर्गुमेंट के लिए टाइप कन्फ्यूज़न
- CVE-2021-29982: गलत रजिस्टर आवंटन (JIT-Picker द्वारा पाया गया)
- CVE-2021-29984: एक अप्रत्याशित GC के साथ संयोजन में निर्देश पुनःक्रमण मेमोरी भ्रष्टाचार का कारण बन सकता है
- CVE-2022-28285: MLoadTypedArrayElementHole के लिए AliasSet बहुत अनुमेय है
- CVE-2022-31745: वृद्धिशील GC में त्रुटि
- CVE-2022-42928: कुछ BigInt ऑपरेशनों के लिए KeepAlive एनोटेशन की कमी मेमोरी भ्रष्टाचार का कारण बन सकती है
- CVE-2022-45406: जावास्क्रिप्ट Realm का यूज़-आफ्टर-फ्री
- CVE-2023-4577: GC और RegEx के इंटरैक्शन के कारण मेमोरी भ्रष्टाचार
- CVE-2023-5171: संकलन के दौरान GC के परिणामस्वरूप यूज़-आफ्टर-फ्री की स्थिति
Chromium/v8* Issue 939316: Reflect.construct को ऑप्टिमाइज़ करते समय Turbofan एक Map पॉइंटर को सीमा से बाहर पढ़ सकता है
- Issue 944062: JSCallReducer::ReduceArrayIndexOfIncludes Map चेक सम्मिलित करने में विफल रहता है
- CVE-2019-5831: V8 में गलत मैप प्रोसेसिंग
- Issue 944865: V8 में अमान्य मान निरूपण
- CVE-2019-5841: इनलाइनिंग ह्यूरिस्टिक में बग
- CVE-2019-5847: V8 के सील/फ्रोज़न एलिमेंट क्रैश का कारण बनते हैं
- CVE-2019-5853: regexp लंबाई जांच में मेमोरी भ्रष्टाचार
- Issue 992914: मैप माइग्रेशन एलिमेंट काइंड्स का सम्मान नहीं करता, जिससे टाइप कन्फ्यूजन होता है
- CVE-2020-6512: V8 में टाइप कन्फ्यूजन
- CVE-2020-16006: DescriptorArray में अनुचित तरीके से संभाले गए हैश कोलिज़न के कारण मेमोरी भ्रष्टाचार
- CVE-2021-37991: समवर्ती JIT संकलन के दौरान रेस कंडीशन
- Issue 1359937: BigInts का डिसीरियलाइज़ेशन अमान्य -0n मान उत्पन्न कर सकता है
- Issue 1377775: Turbofan में Array.prototype.at को इनलाइन करते समय गलत टाइप जांच
- Issue 2323: putprop में अस्थिर valstack पॉइंटर
- Issue 2320: स्ट्रिंग बिल्टिन में Memcmp पॉइंटर ओवरफ़्लो
- CVE-2020-13991: स्प्रेड आर्गुमेंट्स का गलत रिलीज़
- Issue 3784: गलत प्रॉपर्टी गणना के कारण मेमोरी भ्रष्टाचार
- CVE-2020-13623: Proxy ऑब्जेक्ट्स के लिए प्रॉपर्टी कुंजियों के माध्यम से स्टैक ओवरफ़्लो
- CVE-2020-13649 (1): OOM के मामले में त्रुटि हैंडलिंग के कारण मेमोरी भ्रष्टाचार
- CVE-2020-13649 (2): OOM के मामले में त्रुटि हैंडलिंग के कारण मेमोरी भ्रष्टाचार
- CVE-2020-13622: Proxy ऑब्जेक्ट्स के लिए प्रॉपर्टी कुंजियों के गलत संचालन के कारण मेमोरी भ्रष्टाचार
- CVE-2020-14163: की/वैल्यू पेयर जोड़ते समय गार्बेज कलेक्शन द्वारा ट्रिगर रेस कंडीशन के कारण मेमोरी भ्रष्टाचार
- Issue 3813: SerializeJSONProperty फ़ंक्शन में गलत त्रुटि हैंडलिंग
- Issue 3814: ecma_op_function_has_instance एसर्शन में अप्रत्याशित Proxy ऑब्जेक्ट
- Issue 3836: गलत TypedArray आरंभीकरण के कारण मेमोरी भ्रष्टाचार
- Issue 3837: getOwnPropertyDescriptor में गलत मेमोरी हैंडलिंग के कारण मेमोरी भ्रष्टाचार
- CVE-2020-1912: आलसी रूप से संकलित आंतरिक जनरेटर फ़ंक्शन निष्पादित करते समय मेमोरी भ्रष्टाचार
- CVE-2020-1914: SaveGeneratorLong निर्देश को संभालते समय बाइटकोड भ्रष्टाचार
अस्वीकरण
यह आधिकारिक रूप से समर्थित Google उत्पाद नहीं है।