flawopen.com/Teardowns/cve-2024-21626-runc-container-breakout-leaky-vessels
CVE-2024-21626: runc ने Leaky Vessels को कैसे ठीक किया
CVE-2024-21626 में runc का आंतरिक फ़ाइल डिस्क्रिप्टर लीक और chdir के बाद सीमा-जाँच की कमी साथ आई। लॉन्च पथ के अनुसार कंटेनर होस्ट नेमस्पेस की कार्य-निर्देशिका से शुरू हो सकता था या संबंधित exec पथ से होस्ट फ़ाइलों तक पहुँच सकता था।[1], [2], [3]
runc कंटेनर के लिए एक अलग कमरा तैयार करता है। लीक हुआ आंतरिक हैंडल चुनी गई कार्य-निर्देशिका को उस कमरे के बाहर पहुँचा सकता था; अंतिम सीमा-जाँच और आंतरिक हैंडल बंद करना इस रास्ते को रोकता है।[1], [2]
इस पेज के मुख्य शब्द
runc- कंटेनर बनाने और शुरू करने वाला OCI runtime।[1]
आंतरिक फ़ाइल डिस्क्रिप्टर- खुली फ़ाइल या निर्देशिका का OS हैंडल। यदि child प्रक्रिया शुरू होने पर डिस्क्रिप्टर खुला रहे, तो पहुँच प्रक्रिया-सीमा के पार बनी रह सकती है।[1], [3]
cwd- प्रक्रिया की कार्य-निर्देशिका। माउंट नेमस्पेस रूट के बाहर होने पर Linux Getwd से ENOENT मिल सकता है।[1], [2]
कंटेनर से बच निकलना- वह रास्ता जिससे कंटेनर प्रक्रिया अपनी अलगाव सीमा के बाहर होस्ट संसाधन तक पहुँचे।[1]
फ्रेमवर्क मैपिंग
- इस गाइड में बताई गई कमजोरी के लिए CWE संदर्भ: CWE-403
मूल कारण विश्लेषण (Root Cause)
runc 1.1.12 से पहले आंतरिक फ़ाइल डिस्क्रिप्टर runc init में लीक हो सकते थे। वे runc init के आंतरिक डिस्क्रिप्टर थे; कंटेनर प्रक्रिया को सीधे विरासत में नहीं मिले थे। हमले 1 और 2 में कॉन्फ़िगर या चुनी गई कार्य-निर्देशिका होस्ट माउंट नेमस्पेस के हैंडल से हल हो सकती थी; chdir के बाद runc यह नहीं जाँचता था कि अंतिम cwd कंटेनर की रूट के भीतर है। अलग रूपों में execve पथ-हैंडलिंग से होस्ट बाइनरी ओवरराइट की जा सकती थी। संस्करण 1.1.12 ने चार परतें जोड़ीं: Linux Getwd/ENOENT व्यवहार से cwd जाँचना, execve से ठीक पहले आंतरिक डिस्क्रिप्टर बंद करना, ज्ञात लीक ठीक करना, और runc init शुरू करने से पहले गैर-stdio डिस्क्रिप्टर को close-on-exec करना।[1], [2], [3], [4]
CVE-2024-21626: हमले के रूप और runc 1.1.12 की संबंधित सुरक्षा
| एडवाइजरी में हमला | ज़रूरी शर्तें और सीमा | संबंधित सुधार या अस्थायी उपाय |
|---|---|---|
हमला 1 — runc run से दुर्भावनापूर्ण इमेज | विशेषाधिकार प्राप्त उपयोगकर्ता को अविश्वसनीय इमेज चलाने के लिए धोखा देना आवश्यक है। कॉन्फ़िगर की गई कार्य-निर्देशिका कंटेनर माउंट नेमस्पेस के बाहर हल हो सकती है। | chdir के बाद unix.Getwd() जाँच cwd के नेमस्पेस रूट से बाहर होने पर विफल होती है। अस्थायी उपाय के रूप में अविश्वसनीय इमेज के लिए केवल / cwd की अनुमति दें। |
हमला 2 — कंटेनर प्रक्रिया के साथ runc exec | कंटेनर में चल रही प्रक्रिया को अनुमान लगाना होगा कि व्यवस्थापक runc exec --cwd में / से अलग कौन-सा cwd चुनेगा, और exec से पहले संबंधित पथ तैयार करना होगा। | chdir के बाद वही cwd जाँच कंटेनर से बाहर निष्पादन रोकती है। पैच तक --cwd को / तक सीमित रखें। |
| हमला 3a — इमेज लॉन्च से होस्ट बाइनरी ओवरराइट | यह हमला 1 का रूप है और इसमें विशेषाधिकार प्राप्त उपयोगकर्ता द्वारा दुर्भावनापूर्ण इमेज चलाने की शर्त बनी रहती है; यह execve सीमा पार करके होस्ट बाइनरी तक पहुँचता है। | execve से ठीक पहले runc के आंतरिक डिस्क्रिप्टर बंद करें, ज्ञात लीक ठीक करें और O_CLOEXEC लगाएँ। runc 1.1.12 या विक्रेता-समर्थित सुधारित संस्करण में अपग्रेड करें। |
हमला 3b — runc exec से होस्ट बाइनरी ओवरराइट | यह हमला 2 का रूप है और ऐसे चल रहे कंटेनर के दुर्भावनापूर्ण process से शुरू होता है जिसे हमलावर प्रभावित कर सकता है; फिर भी, विशेषाधिकार प्राप्त administrator को उस कंटेनर पर सामान्य runc exec चलाना पड़ता है। एडवाइजरी के अनुसार, इमेज वाले रास्ते की तुलना में इसमें user interaction कम चाहिए। | exec से पहले बंद करना और close-on-exec सुरक्षा इस अलग रास्ते को रोकती है। मेंटेनर कोई व्यावहारिक workaround नहीं बताते; अपग्रेड करें। |
हमले का चरण-दर-चरण प्रवाह
प्रभाव और शर्तें
एडवाइजरी चार रूपों में होस्ट फ़ाइल-सिस्टम तक पहुँच और होस्ट नियंत्रण बताती है। इमेज वाले हमले में विशेषाधिकार प्राप्त उपयोगकर्ता को अविश्वसनीय इमेज चलानी पड़ती है। हमले 3b में भी administrator को ऐसे कंटेनर पर सामान्य runc exec चलाना पड़ता है जिसे हमलावर प्रभावित कर सकता है।[1]
सोर्स कोड: कमज़ोर बनाम सुरक्षित कार्यान्वयन
// सुधार से पहले के व्यवहार का सरल रूप; यह runc का शब्दशः स्रोत कोड नहीं है
if err := os.Chdir(config.Cwd); err != nil {
return err
}
// कमी: अंतिम cwd नेमस्पेस रूट के भीतर है या नहीं, इसकी जाँच
// runc 1.1.12 की सीमा-जाँच (upstream अंश)
if wd, err := unix.Getwd(); errors.Is(err, unix.ENOENT) {
return errors.New("cwd कंटेनर माउंट नेमस्पेस रूट के बाहर है")
} else if err != nil {
return fmt.Errorf("cwd सुरक्षा सत्यापित नहीं हो सकी: %w", err)
} else if !filepath.IsAbs(wd) {
return fmt.Errorf("cwd निरपेक्ष पथ नहीं है: %q", wd)
}
इंजीनियरिंग और सिस्टम सुरक्षा चेकलिस्ट
- ✓runc को 1.1.12 या विक्रेता-समर्थित नए संस्करण में अपडेट करें और प्रत्येक नोड इमेज का वास्तविक runtime संस्करण जाँचें।[1], [4]
- ✓अविश्वसनीय कंटेनर इमेज को कोड चलाने का अनुरोध मानें; Docker, Kubernetes और build pipeline में उन्हें शुरू करने के अधिकार सीमित करें।[1]
- ✓Runtime लागू करते समय chdir के बाद प्लेटफ़ॉर्म की namespace-root जाँच से cwd सत्यापित करें और त्रुटि पर सुरक्षित रूप से रुकें।[1], [2]
- ✓आंतरिक डिस्क्रिप्टर पर O_CLOEXEC लगाएँ और runtime के आवश्यक डिस्क्रिप्टर ध्यान में रखते हुए exec से पहले अंतिम सुरक्षित बिंदु पर गैर-stdio डिस्क्रिप्टर बंद करें।[1], [3]
- ✓user namespace को runc patch का विकल्प न मानें; उपलब्ध होने पर उसे अतिरिक्त अलगाव परत की तरह उपयोग करें।[1]