गतिशील भाषा इंटरप्रेटरों के लिए एक (कवरेज-निर्देशित) फजर, जो एक कस्टम मध्यवर्ती भाषा ("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 देखें। इसके बाद, उच्च-स्तरीय फजिंग लॉजिक के लिए देखें। वहाँ से किसी भी दिलचस्प हिस्से में गोता लगाएँ।
यदि आप इस परियोजना की मदद से पाई गई किसी भेद्यता के लिए [email protected] पर एक संक्षिप्त नोट (संभवतः CVE नंबर सहित) भेज सकते हैं या एक पुल अनुरोध खोल सकते हैं तो बहुत सराहना की जाएगी ताकि इसे बग शोकेस अनुभाग में शामिल किया जा सके। इसके अलावा आप निश्चित रूप से किसी भी बग बाउंटी, CVE क्रेडिट आदि का दावा कर सकते हैं :)
अवधारणा
जब मुख्य इंटरप्रेटर बग, जैसे कि JIT कंपाइलर में, के लिए फजिंग की जाती है, तो उत्पन्न प्रोग्रामों की सिमैंटिक शुद्धता एक चिंता का विषय बन जाती है। यह अधिकांश अन्य परिदृश्यों के विपरीत है, उदाहरण के लिए रनटाइम API की फजिंग, जहाँ सिमैंटिक शुद्धता को जनरेटेड कोड को try-catch कंस्ट्रक्ट में लपेटकर आसानी से दरकिनार किया जा सकता है। स्वीकार्य दर पर सिमैंटिकली सही नमूने प्राप्त करने के लिए अलग-अलग संभावनाएँ हैं, उनमें से एक उत्परिवर्तन दृष्टिकोण है जिसमें कोष में सभी नमूने भी सिमैंटिकली मान्य होते हैं। उस स्थिति में, प्रत्येक उत्परिवर्तन में एक मान्य नमूने को अमान्य में बदलने की संभावना कम होती है।
एक उत्परिवर्तन-आधारित जावास्क्रिप्ट फजर को लागू करने के लिए, जावास्क्रिप्ट कोड पर उत्परिवर्तन को परिभाषित करना होता है। किसी प्रोग्राम के AST या अन्य सिंटैक्टिक तत्वों को उत्परिवर्तित करने के बजाय, एक कस्टम मध्यवर्ती भाषा (IL) को परिभाषित किया जाता है जिस पर प्रोग्राम के नियंत्रण और डेटा प्रवाह में उत्परिवर्तन अधिक सीधे किए जा सकते हैं। इस IL का बाद में निष्पादन के लिए जावास्क्रिप्ट में अनुवाद किया जाता है। मध्यवर्ती भाषा मोटे तौर पर इस प्रकार दिखती है:
एक 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 को उन आवंटनों के लिए संकेत नहीं डालने चाहिए जो अब मान्य नहीं हैं
CVE-2020-3901: FTL JIT कोड में GetterSetter टाइप कन्फ्यूज़न (हमेशा सुरक्षित नहीं LICM के कारण)
CVE-2021-30851: समवर्ती HashTable लुकअप के दौरान लॉक का अभाव
CVE-2021-30818: DFG OSR Exit पर आर्गुमेंट्स के पुनर्निर्माण के दौरान टाइप कन्फ्यूज़न
CVE-2022-46696: JIT-संकलित कोड में अपवाद जाँच की कमी के कारण असर्शन विफलता
CVE-2022-46699: IC में विशेष प्रॉपर्टी के गलत कैशिंग के कारण असर्शन विफलता
CVE-2022-46700: Intl.Locale.prototype.hourCycles खाली JSValue को स्क्रिप्ट में लीक करता है
CVE-2025-43214: स्टैक पर पुनरावृत्ति के दौरान JSToWasmEntry में मेमोरी भ्रष्टाचार
CVE-2025-43213: NewRegExpUntyped ऑपरेशन की अमान्य टाइपिंग
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 में विशेष आर्गुमेंट के लिए टाइप कन्फ्यूज़न