
क्रूशियल MX500 SSD फर्मवेयर अपडेट तंत्र में तीन कमजोरियों के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट्स, जो बफर ओवरफ्लो और ATA कमांड के माध्यम से संभावित कोड निष्पादन को सक्षम बनाते हैं।
प्रश्नगत उपकरण कोई भी MX500-श्रृंखला SSD है। ये SSD Sillicon-Motion SM2259 नियंत्रक (पुराने बैचों में पुराना नियंत्रक, Sillicon-Motion SM2258, था, लेकिन इस दस्तावेज़ का मुख्य फोकस नए पर है) द्वारा नियंत्रित होते हैं। SM2259 एक 4-चैनल SATA 6Gb/s माइक्रो-कंट्रोलर है जो ARC आर्किटेक्चर पर आधारित 32-बिट लिटिल-एंडियन CPU का उपयोग करता है।
इस दस्तावेज़ की तिथि पर लागू नवीनतम फ़र्मवेयर, जो M3CR046 है, का अवलोकन करने पर, कुछ समस्याएँ पहचानी गईं और स्थिर तथा गतिशील दोनों रूप से पुष्टि की गईं।
सभी समस्याएँ नियंत्रक के फ़र्मवेयर अद्यतन तंत्र में पाई गईं, जो माइक्रो-कंट्रोलर हैंडलर ATA PIO DOWNLOAD-MICROCODE (0x92) कमांड से संबंधित है, विशेष रूप से उस तर्क में जो ऑफ़सेट विधि का उपयोग करके फ़र्मवेयर डाउनलोड करता है, जो उपकमांड 0x03 और 0x0E से संबंधित है।
इस दस्तावेज़ में शामिल सभी बग Crucial MX500 500GB SSD (CT500MX500SSD1), SM2259H-AC नियंत्रक पर M3CR046 FW के साथ NY112 फ्लैश चिप्स और x86_64 CPU वाले PC पर सत्यापित किए गए।
FW कोड को आधार पते 0x80020000 पर मैप किया गया है, और कमजोर ATA हैंडलर पते 0x80024A9C पर स्थित है। आपकी सुविधा के लिए फ़ंक्शन का एक डीकंपाइल संस्करण resources/download_microcode_handler.c के अंतर्गत पाया जा सकता है।
जो लोग तकनीकी विवरणों से निपटना नहीं चाहते और निचली पंक्ति को समझना चाहते हैं, कृपया नीचे FAQ अनुभाग देखें।
चूंकि M3CR046 में कई फ़र्मवेयर इमेज हैं जिनमें से उपयुक्त फ़र्मवेयर अद्यतन तंत्र द्वारा चुना जाता है (शायद वास्तविक फ्लैश चिप्स या कुछ अन्य हार्डवेयर विशेषताओं पर निर्भर करता है), यह दस्तावेज़ पहले फ़र्मवेयर वेरिएंट की बारीकियों को कवर करेगा (क्योंकि यह हमारे विशिष्ट ड्राइव पर समर्थित फ़र्मवेयर है, और इस प्रकार हम केवल उस फ़र्मवेयर वेरिएंट का परीक्षण कर सकते हैं)। हालांकि, इस दस्तावेज़ में प्रस्तुत बग सभी फ़र्मवेयर वेरिएंट पर लागू होते प्रतीत होते हैं, लेकिन उन्हें पुन: प्रस्तुत करते समय वास्तविक बारीकियों में कुछ अंतर हो सकते हैं।
यह समस्या उन मामलों को संदर्भित करती है जहां भेजा गया पहला खंड 0x200 सेक्टर से बड़ा होता है। यदि हम ATA कमांड हैंडलर के अंदर देखें, विशेष रूप से उस तर्क पर जो तब निष्पादित होता है जब खंड का आकार सेक्टर आकार से बड़ा होता है और जब खंड पहला भेजा गया हो:

यह अगले ऑफ़सेट (जो हमारे मामले में, चूंकि हमने अब तक केवल एक खंड भेजा है, खंड की लंबाई सेक्टरों में है) और lower_bound_fw_offset नामक चर के आधार पर कुछ चर सेट करता है, जो ब्लॉक ऑफ़सेट है (अर्थात, सेक्टरों की ग्रैन्युलैरिटी में ऑफ़सेट) जिसके भीतर हमारी फ़र्मवेयर इमेज इनपुट डाउनलोड इमेज में पाई जाने की उम्मीद है। यह प्रति फ़र्मवेयर वेरिएंट एक हार्डकोडेड मान है, जो हमारे मामले में (पहला वेरिएंट), 0 के बराबर है।
इस स्थिति में, some_index के लिए घटाव परिणाम की गणना करते समय अंडरफ़्लो होता है, जिससे some_index का मान 0xFFFF जितना अधिक हो जाता है। यह अप्रत्याशित व्यवहार है, क्योंकि डाउनलोड बफर में डेटा ले जाने वाले तर्क के आधार पर:

हम देखते हैं कि जिस स्रोत पते से डेटा कॉपी किया जाता है वह some_index के अप्रत्याशित मान को देखते हुए मान्य नहीं हो सकता है।
जब पहले खंड के 0x200 सेक्टर से बड़े आकार के साथ फ़र्मवेयर अद्यतन अनुरोध भेजकर गतिशील रूप से परीक्षण किया जाता है, तो नियंत्रक हैंग हो जाता है और मूल अनुरोध का कोई उत्तर भी नहीं भेजता है। यह सुसंगत और आसानी से प्रतिलिपि करने योग्य है।
संभवतः ऐसा गणना किए गए स्रोत पते के अमान्य संदर्भ के कारण होता है, जो फिर एक अपवाद को ट्रिगर करता है जिससे नियंत्रक हैंग हो जाता है। यह सिद्ध नहीं हुआ है, बल्कि एक अनुमान है जो हैंग की व्याख्या कर सकता है।
इनपुट डाउनलोड इमेज (M3CR046 के लिए) का आकार 0x242400 बाइट्स है, और इस इमेज के अंदर 3 आंतरिक फ़र्मवेयर इमेज हैं जिनमें से केवल एक को फ़र्मवेयर अद्यतन प्रक्रिया के बाद फ्लैश में लिखा जाता है, प्रत्येक ऐसी इमेज का आकार 0xC0C00 बाइट्स (या 0x606 सेक्टर) है।
इसका मतलब है कि जब फ़र्मवेयर अद्यतन तंत्र इनपुट डाउनलोड इमेज से सही फ़र्मवेयर प्रतिलिपि निकालता है, तो उसे सत्यापित करना होता है कि इसका आकार 0xC0C00 बाइट्स से अधिक न हो।
नियंत्रक वास्तव में ऐसा करने का प्रयास करता है, लेकिन कुछ सीमांत स्थितियां अप्रत्याशित व्यवहार का कारण बन सकती हैं। आइए निम्नलिखित स्निपेट देखें (जो पिछले बग के साथ कुछ कोड साझा करता है):

यदि वर्तमान खंड 0x200 सेक्टर से बड़ा है और यह अनुक्रम में पहला खंड नहीं है, तो एक बार में 0x200 सेक्टर (0x40000 बाइट्स) कॉपी किए जाएंगे। फिर, एक जांच है जिसका उद्देश्य कॉपी करने के लिए बाइट्स की संख्या से अतिरिक्त बाइट्स को छोटा करना है, यदि फ़र्मवेयर इमेज का कुल आकार higher_bound_fw_offset (जो हमारे मामले में 0x606 सेक्टर है, क्योंकि फ़र्मवेयर का आकार बिल्कुल यही होना चाहिए) से अधिक हो जाता है।
यह तर्क समग्र रूप से समझ में आता है, लेकिन इसमें एक खामी है – यदि भेजा गया अंतिम खंड अगले ऑफ़सेट को बहुत अधिक कर देता है, जैसे कि अतिरिक्त बाइट्स की संख्या 0x200 सेक्टर (या 0x40000 बाइट्स) से अधिक हो जाती है, तो curr_bytes_to_copy को एक “ऋणात्मक” मान मिलता है, जो लगभग ~4GB (~0xFFFFFFFF) तक अंडरफ़्लो हो जाता है। जैसा कि हमने पहले देखा, इस चर का उपयोग डाउनलोड बफर में स्थानांतरित किए जाने वाले बाइट्स की संख्या निर्धारित करने के लिए किया जाता है।
यदि हम r_maybe_some_efficient_data_transfer के अंदर देखते हैं, तो हम निम्नलिखित कोड का टुकड़ा देखते हैं:

जिसका अर्थ है कि कॉपी आकार को 32MB (मूल ~4GB कॉपी आकार से) में छोटा कर दिया जाता है, लेकिन फिर भी यह एक बड़ी संख्या है जो 0x40000000 पर शुरू होने वाली मेमोरी रेंज का आकार 32MB से कम होने पर अपरिभाषित व्यवहार का कारण बन सकती है।
जब 0x600 के ऑफ़सेट पर पहुंचने के लिए ATA खंड भेजकर, और फिर अंडरफ़्लो को ट्रिगर करने के लिए 0x207 सेक्टर का एक बड़ा खंड भेजकर गतिशील रूप से परीक्षण किया जाता है, तो नियंत्रक फिर से हैंग हो जाता है, संभवतः कॉपी के दौरान अमान्य मेमोरी एक्सेस के कारण।
यह बग पिछले वाले की तुलना में अधिक दिलचस्प है, क्योंकि भले ही हमारे पास नियंत्रित ओवरराइट नहीं है (बल्कि, एक बड़ा ओवरराइट जो संभवतः एक अपवाद को ट्रिगर करता है जो नियंत्रक को हैंग कर देता है), यदि डेटा को डाउनलोड बफर में ले जाने वाला फ़ंक्शन वास्तव में क्रैश होने से पहले इतना डेटा स्थानांतरित करने में सफल हो जाता है (मुख्य मेमोरी में डाउनलोड बफर के ठीक बाद स्थित मेमोरी रेंज को ओवरराइट करते हुए), तो शायद अपवाद हैंडलर का व्यवहार ओवरराइट किए गए डेटा के आधार पर बदल सकता है। ऐसा संभवतः हो सकता है, यदि, उदाहरण के लिए, अपवाद हैंडलर ओवरराइट किए गए क्षेत्र से एक पॉइंटर पढ़ता है और फिर उस पर कूदता है (यह विशिष्ट मामला विशेष रूप से संभावित नहीं है, लेकिन कुछ और शोध के साथ, इस तरह की कोई चीज़ खोजी जा सकती है)।
जैसा कि बताया गया है, डाउनलोड इमेज का आकार 0x242400 (या 0x1212 सेक्टर) है। फ़र्मवेयर सत्यापित करता है कि स्थानांतरित इमेज का कुल आकार इस आकार से अधिक न हो, यह सुनिश्चित करके कि अगला ऑफ़सेट 0x1212 सेक्टर से अधिक न हो। यह जांच समझ में आती है, लेकिन अगले ऑफ़सेट की गणना त्रुटिपूर्ण है:

यदि वर्तमान ऑफ़सेट 0x600 सेक्टर है, और संसाधित होने वाला अगला ATA कमांड पर्याप्त बड़े आकार का है (मान लीजिए 0xFC00 सेक्टर, जो ATA मानक द्वारा अनुमत है), तो अगला ऑफ़सेट रैप अराउंड हो जाता है, जिससे उपरोक्त जांच ठीक से काम नहीं करती है:

या दूसरे शब्दों में, सामान्य मामले में, फ़र्मवेयर अद्यतन तंत्र अपनी स्थिति मशीन को रीसेट करेगा और एक त्रुटि लौटाएगा, लेकिन यदि हम बहुत बड़ा खंड भेजते हैं, तो हम इसे संसाधित करना जारी रखेंगे। निम्नलिखित कोड स्निपेट दिखाता है कि स्थानांतरण कैसे किया जाता है:

हम इस बिंदु पर याद करते हैं कि यदि स्थानांतरित करने के लिए सेक्टरों की संख्या 0x200 सेक्टर से अधिक है और वर्तमान खंड पहला नहीं है, तो एक बार में 0x200 सेक्टर डाउनलोड बफर में कॉपी किए जाते हैं। यह बहुत दिलचस्प है, क्योंकि इसका मतलब है कि हम डाउनलोड बफर से परे लगभग 0x200 सेक्टर (या 0x40000 बाइट्स) कॉपी कर सकते हैं, मुख्य मेमोरी में डेटा को ओवरराइट कर सकते हैं। उदाहरण के लिए, यदि वर्तमान ऑफ़सेट 0x605 सेक्टर है और हम 0xF9FB सेक्टर का खंड आकार प्रदान करते हैं, तो रैप अराउंड के कारण __next_offset का मान 0 हो जाता है। जिस स्रोत सूचकांक से कॉपी शुरू होती है वह 0 है, और curr_bytes_to_copy को 0x40000 का मान मिलता है। चूंकि हम वर्तमान में ऑफ़सेट 0x605 सेक्टर पर हैं, तो g_blocks_copied को 0x605 का मान मिलता है। चूंकि वर्तमान ऑफ़सेट वास्तव में मान्य है (और अगला भी), तो डाउनलोड बफर में कॉपी ऑपरेशन ट्रिगर होता है, जिससे डाउनलोड बफर के अंत से थोड़ा कम बाइट्स का बड़े पैमाने पर ओवरराइट होता है।
यह एक मजबूत प्रारंभिक स्थिति है जो अधिक नियंत्रित नियंत्रक बफर ओवरफ़्लो की अनुमति देती है (जो पिछले मामलों की तरह नियंत्रक को तुरंत क्रैश नहीं करती है), और पिछले बग की तुलना में बहुत अधिक निश्चितता के साथ कोड निष्पादन की ओर ले जा सकती है (लेकिन फिर भी, यह निर्धारित करने के लिए कि शोषण की विशेषताएं क्या हैं, मुख्य मेमोरी में डाउनलोड बफर के बाद वास्तव में क्या रखा गया है, इसके बारे में और शोध करने की आवश्यकता है)।
ये सभी बग Ubuntu 22.04 64-बिट मशीन पर मानक Linux SCSI ड्राइवर का उपयोग करके SG_IO इंटरफ़ेस पर सत्यापित किए गए थे। यह ध्यान दिया जाना चाहिए कि इस विशिष्ट ड्राइवर के साथ बग #3 को पुन: प्रस्तुत करने के लिए, ह्यूज पेज सक्षम होना चाहिए और बड़े अनुरोध के लिए एक एकल 1GB पेज आवंटित किया जाना चाहिए। इसका कारण यह है कि ऐसा प्रतीत होता है कि इस ड्राइवर को संपूर्ण ATA अनुरोध को सन्निकट भौतिक मेमोरी ब्लॉक में होना आवश्यक है। चूंकि अनुरोध का आकार लगभग ~30MB है, 2MB पेज पर्याप्त नहीं हैं, और इस प्रकार 1GB पेज हमारे परीक्षण प्रणाली पर उपलब्ध अगला (और अंतिम) आकार है।
हालांकि, यह भी ध्यान दिया जाना चाहिए कि इसका मतलब यह नहीं है कि इसे ट्रिगर करने के लिए यह एक आवश्यक कदम है, क्योंकि शायद अन्य समाधान भी हैं जो बड़े ATA अनुरोध भेजने की अनुमति देते हैं, जिन्हें हमने अभी तक कवर नहीं किया है। ह्यूज-पेज सक्षम करना इस बग की पुष्टि करने का सबसे तेज़ तरीका था। इसके अलावा, इन सभी बगों को ट्रिगर करने के लिए आवश्यक एकमात्र पूर्वापेक्षा ATA पैकेट भेजने के लिए आवश्यक अनुमतियाँ हैं (आमतौर पर, नियंत्रक के साथ संचार करने वाले PC तक रूट एक्सेस)।
उपरोक्त सभी बगों को पुन: प्रस्तुत करने वाला स्रोत कोड इस रिपॉजिटरी के भाग के रूप में प्रदान किया गया है। बग #1 और बग #2 के लिए, अपेक्षित व्यवहार ड्राइव का अगले पावर चक्र तक हैंग होना है। बग #3 के लिए, प्रदान किया गया स्रोत कोड आवश्यक रूप से नियंत्रक को क्रैश नहीं करता है, लेकिन यह डाउनलोड बफर से परे एक बड़ा ओवरराइट करता है।
जैसा कि बताया गया है, चूंकि बग Ubuntu 22.04 64-बिट मशीन पर सत्यापित किए गए थे, संकलन प्रक्रिया समान मशीन पर की जानी चाहिए। अन्य वितरणों या ऑपरेटिंग सिस्टमों के लिए कोई गारंटी नहीं है।
निर्माण करने के लिए, परियोजना की मूल निर्देशिका में निम्नलिखित चलाएँ:
cmake -B build && make
निर्माण प्रक्रिया 3 बाइनरी बनाती है, ये सभी build निर्देशिका में उपलब्ध होंगे, जिनके नाम CVE_MX500_BUG_1, CVE_MX500_BUG_2 और CVE_MX500_BUG_3 होंगे, जो क्रमशः बग #1, बग #2 और बग #3 को ट्रिगर करने वाली स्रोत फ़ाइलों से संबंधित हैं।
प्रत्येक बाइनरी MX500 SSD का डिवाइस पथ प्राप्त करने की अपेक्षा करता है, और इसे रूट विशेषाधिकारों के साथ चलाया जाना चाहिए। उदाहरण के लिए:
sudo ./build/CVE_MX500_BUG1 /dev/sda
यह संभावित हमलावर के अंतिम लक्ष्य पर निर्भर करता है। यदि वे केवल आपके ड्राइव के स्टोरेज तक पूर्ण पढ़ने/लिखने की पहुँच चाहते हैं, तो आपके PC के अंदर होना पहले से ही पर्याप्त है। हालांकि, यदि वह हमलावर इसे कुछ कदम आगे ले जाना चाहता है? यदि किसी ड्राइव का FW डिजिटल रूप से हस्ताक्षरित है, तो बग #3 एक हमलावर को फ़र्मवेयर के हस्ताक्षर सत्यापन को बायपास करने में सक्षम बना सकता है, जिससे हमलावर ड्राइव के फ़र्मवेयर में एक दुर्भावनापूर्ण पेलोड डाल सकता है। एक बार अंदर जाने के बाद, ऐसा पेलोड बहुत अच्छी तरह से छिपा होता है, ड्राइव फ़ॉर्मेट से बच जाता है और नियंत्रक फ़र्मवेयर अपडेट से भी बच सकता है। ऐसा पेलोड वास्तव में क्या कर सकता है, यह इस दस्तावेज़ के दायरे से परे है, इसलिए इस पर चर्चा नहीं की जाएगी।
यह संभावना है कि उत्तर बहुत बड़ा नहीं होगा। वास्तव में इस तरह के हमले को अंजाम देने के लिए आवश्यक R&D की मात्रा बहुत अधिक है, और यह (बहुत संभावना है) बहुत गंभीर खतरे वाले अभिनेताओं के लिए ही संभव होगा। जब तक आप सरकारों द्वारा वांछित नहीं हैं, इसका आपको किसी भी तरह से प्रभावित करना अत्यंत असंभावित है।
विक्रेता ने महीनों के दौरान इन मुद्दों के बारे में कई ईमेलों का जवाब नहीं दिया। CVE को वास्तव में प्रकाशित करने के लिए, CNA को एक सार्वजनिक लिंक प्रदान किया जाना चाहिए। दुख की बात है कि उन्हें जानकारी निजी तौर पर भेजना इस तरह से काम नहीं करता है।
इस दस्तावेज़ में उल्लिखित बग मूल रूप से मई 2024 में खोजे गए थे। तब से माइक्रोन से कई बार संपर्क किया गया (उनके आधिकारिक सुरक्षा ईमेल के माध्यम से), और उनकी ओर से कोई प्रतिक्रिया नहीं मिली। जुलाई 2024 में MITRE को सूचित किया गया, और अगस्त 2024 में एक CVE निर्दिष्ट किया गया। अगस्त 2024 के अंत में, यह रिपॉजिटरी सार्वजनिक कर दी गई (CVE द्वारा MITRE द्वारा अनुमोदित होने के कुछ दिनों बाद)।
चूंकि M3CR046 से पुराने M3CR04X फ़र्मवेयर अब डाउनलोड के लिए उपलब्ध नहीं हैं, यह स्पष्ट नहीं है कि वे प्रभावित हैं या नहीं, लेकिन यदि मुझे अनुमान लगाना हो, तो मैं हाँ कहूंगा। इससे भी पुराने संस्करणों के बारे में, उदाहरण के लिए, M3CR033, तो स्थैतिक विश्लेषण के आधार पर, ऐसा प्रतीत होता है कि वहाँ समान बग मौजूद हैं।
प्रश्नगत नियंत्रक, SM2259, अन्य विक्रेताओं के SSDs में भी एम्बेडेड है। यह संभव है कि विक्रेता फ़र्मवेयर कोड के कुछ हिस्से को संशोधित करते हैं, लेकिन मैं यह भी कहूंगा कि यह निश्चित रूप से संभावित है कि ये बग (या उनके समान) अन्य विक्रेताओं के SSDs में भी मौजूद हों।
यह CVE MITRE द्वारा प्रकाशित किया गया है। इसका विश्लेषण NVD द्वारा 6.7 (मध्यम) के CVSS 3.0 स्कोर के साथ भी किया गया है।
यदि आपने विवरण में अशुद्धियाँ या गलतियाँ पाई हैं या आपको इन बगों को पुन: प्रस्तुत करने में परेशानी हो रही है, तो कृपया मुझसे log1kxd at gmail.com पर संपर्क करें।
0x40000