flawopen.com/Incidents/rust-unsafe-smallvec-overflow-january-2021
CVE-2021-25900: Rust smallvec heap बफ़र ओवरफ़्लो
SmallVec::insert_many ने size_hint की निचली सीमा पर भरोसा किया; iterator अधिक आइटम देता तो heap buffer से बाहर लिखता। 0.6.14 और 1.6.1 में सुधार हुआ।
एक गोदाम इसलिए सुरक्षित माना जाता है क्योंकि हर शेल्फ़ पर कुछ रखने से पहले एक रोबोट उसे जाँचता है। कुछ कामों के लिए रोबोट बंद कर दिया जाता है और एक व्यक्ति सावधानी का वादा करके हाथ से काम करता है। ऐसे एक व्यक्ति ने ड्राइवर से पूछा: "लगभग कितने डिब्बे ला रहे हो?", उतनी बड़ी शेल्फ़ बनाई और रखना शुरू कर दिया। अनुमान बस अंदाज़ा था, गारंटी नहीं, और जब वादे से ज़्यादा डिब्बे आए तो ढेर शेल्फ़ के किनारे से बाहर चला गया।
इस पेज के मुख्य शब्द
SmallVec- Rust का एक संग्रह जो कुछ ही तत्वों को अपने भीतर रखता है और बढ़ने पर हीप बफ़र पर चला जाता है। इसकी तेज़ी उस unsafe कोड से आती है जो इस बफ़र को हाथ से संभालता है।
size_hint- Iterator का एक मेथड जो बचे हुए आइटमों की अनुमानित निचली और ऊपरी सीमा बताता है। यह केवल संकेत है: safe कोड कोई भी मान लौटा सकता है, ग़लत भी।
unsafe Rust- unsafe ब्लॉक का कोड ऐसे काम कर सकता है जिन्हें कंपाइलर नहीं जाँच सकता, जैसे रॉ पॉइंटर से लिखना; लेखक को हर संभव safe कॉलर के लिए मेमोरी सुरक्षा बनाए रखनी होती है।
साउंडनेस- कोई safe API साउंड है अगर कोई भी safe कोड, कितना भी असामान्य हो, उसके ज़रिए अपरिभाषित व्यवहार न करा सके। insert_many साउंड नहीं था, क्योंकि एक वैध size_hint मेमोरी बिगाड़ सकता था।
फ्रेमवर्क मैपिंग
घटना का समयक्रम (Timeline)
Yechan Bae और Georgia Tech के SSLab का Rust समूह इस बग की सूचना देते हैं; RustSec, RUSTSEC-2021-0003 प्रकाशित करता है और smallvec 0.6.14 व 1.6.1 में सुधार आता है।
CVE-2021-25900 आवंटित होती है; cargo audit डिपेंडेंसी ट्री में प्रभावित संस्करणों को चिह्नित करने लगता है।
हमले का चरण-दर-चरण प्रवाह
इटरेटर अपनी लंबाई कम बताता है
insert_many को ऐसे इटरेटर के साथ बुलाया जाता है जिसके size_hint की निचली सीमा वास्तव में दिए जाने वाले आइटमों से कम है। safe कोड को ऐसा करने की अनुमति है।
संकेत के आधार पर जगह रखी जाती है
insert_many केवल निचली सीमा जितनी जगह रखता है और मौजूदा तत्वों को उतना ही खिसकाता है।
फिर भी हर आइटम लिखा जाता है
unsafe ब्लॉक के भीतर लूप हर आइटम को रॉ पॉइंटर से लिखता है, इसलिए अतिरिक्त आइटम आवंटित जगह के अंत के बाहर पहुँच जाते हैं।
हीप बिगड़ जाता है
ओवरफ़्लो पड़ोसी हीप मेमोरी को ओवरराइट कर देता है। जो प्रोग्राम अविश्वसनीय इनपुट से प्रभावित इटरेटर insert_many को देते हैं, वे जोखिम में हैं।
सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन
// एक *hint* के आधार पर allocate करें...
let (lower, _) = iter.size_hint();
self.reserve(lower);
unsafe {
let ptr = self.as_mut_ptr().add(index);
for (i, item) in iter.enumerate() {
// ...लेकिन वास्तव में आने वाले
// सभी items लिखें।
ptr::write(ptr.add(i), item);
}
}// हर item के लिए capacity फिर से जाँचें।
// safe code के किसी value को
// unsafe द्वारा उपयोग की जाने वाली सीमा तय न करने दें।
for (i, item) in iter.enumerate() {
self.reserve(1);
unsafe {
let ptr = self.as_mut_ptr()
.add(index + i);
ptr::write(ptr, item);
}
}
// वास्तविक सुधार ने
// unsafe surface को भी काफी घटाया।इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट
- ✓unsafe कोड द्वारा इस्तेमाल होने वाले बफ़र का आकार कभी safe trait मेथड, जैसे size_hint, trait object पर len या तुलनाकर्ता, से तय न करें; हर लेखन से पहले क्षमता दोबारा जाँचें।
- ✓हर unsafe ब्लॉक पर // SAFETY: टिप्पणी लिखें कि वह किस अपरिवर्तनीय शर्त पर निर्भर है, और उन समीक्षाओं को अस्वीकार करें जिनमें वह शर्त अविश्वसनीय safe कोड पर टिकी हो।
- ✓CI में Miri को ऐसे परीक्षणों पर चलाएँ जो शत्रुतापूर्ण इम्प्लीमेंटेशन इस्तेमाल करें, जैसे झूठा size_hint देने वाला इटरेटर, पैनिक करने वाला Drop और पूर्ण क्रम न मानने वाला तुलनाकर्ता।
- ✓unsafe ब्लॉक जितने छोटे हो सकें रखें; smallvec के सुधार ने भी insert_many में unsafe कोड घटाया ताकि उसे सत्यापित किया जा सके।
- ✓CI में cargo audit (या cargo deny) चलाएँ ताकि RustSec चेतावनी वाली डिपेंडेंसी, जैसे 0.6.14 या 1.6.1 से पहले का smallvec, बिल्ड को विफल करें।
स्रोत
- RustSec — RUSTSEC-2021-0003: SmallVec::insert_many में बफ़र ओवरफ़्लो
- servo/rust-smallvec — issue 252
- CVE-2021-25900 — CVE रिकॉर्ड
- MITRE CWE-787
- Heartbleed: एक छूटी सीमा-जाँच, आधा इंटरनेट
- Baron Samedit: एक बैकस्लैश में छिपा दस साल का root
- Citrix Bleed: एक रिटर्न वैल्यू को ग़लत पढ़ने से MFA कैसे बेअसर हुआ