
डेबियन OpenSSL में पूर्वानुमान योग्य PRNG (CVE-2008-0166)
मूल URL: http://metasploit.com/users/hdm/tools/debian-openssl/ (मिरर)
एक्सप्लॉइट:
अनुशंसित टूल: Crowbar (SSH कुंजियों को ब्रूट फोर्स करने में सक्षम)
परीक्षण विधि: ssh-vulnkey और dowkd.pl
CVE (CVE-2008-0166):
13 मई, 2008 को डेबियन परियोजना ने घोषणा की कि लुसियानो बेलो को उनके द्वारा वितरित किए जा रहे OpenSSL पैकेज में एक दिलचस्प भेद्यता मिली। यह बग md_rand.c से निम्नलिखित कोड पंक्ति को हटाने के कारण हुआ था:
MD_Update(&m,buf,j);
[ .. ]
MD_Update(&m,buf,j); /* purify complains */
ये पंक्तियाँ हटा दी गईं क्योंकि उनके कारण Valgrind और Purify टूल OpenSSL से जुड़े किसी भी कोड में अप्रारंभिक डेटा के उपयोग के बारे में चेतावनी उत्पन्न करते थे। आप OpenSSL टीम को ऐसी एक रिपोर्ट यहाँ देख सकते हैं। इस कोड को हटाने का दुष्प्रभाव OpenSSL PRNG की सीडिंग प्रक्रिया को क्षतिग्रस्त करना था। प्रारंभिक सीड के लिए यादृच्छिक डेटा मिलाने के बजाय, एकमात्र "यादृच्छिक" मान जो उपयोग किया गया था, वह वर्तमान प्रक्रिया ID थी। Linux प्लेटफ़ॉर्म पर, डिफ़ॉल्ट अधिकतम प्रक्रिया ID 32,768 है, जिसके परिणामस्वरूप सभी PRNG संचालनों के लिए बहुत कम संख्या में सीड मान उपयोग किए गए।
सितंबर 2006 और 13 मई, 2008 के बीच डेबियन-आधारित सिस्टम (Ubuntu, Kubuntu, आदि) पर उत्पन्न सभी SSL और SSH कुंजियाँ प्रभावित हो सकती हैं। SSL कुंजियों के मामले में, सभी उत्पन्न प्रमाणपत्रों को फिर से बनाना होगा और हस्ताक्षर करने के लिए प्रमाणपत्र प्राधिकरण को भेजना होगा। डेबियन-आधारित सिस्टम पर उत्पन्न कोई भी प्रमाणपत्र प्राधिकरण कुंजी पुनः उत्पन्न और निरस्त करनी होगी। सभी सिस्टम प्रशासक जो उपयोगकर्ताओं को SSH और सार्वजनिक कुंजी प्रमाणीकरण के साथ अपने सर्वर तक पहुँचने की अनुमति देते हैं, उन्हें यह देखने के लिए उन कुंजियों का ऑडिट करना होगा कि क्या उनमें से कोई भी कमजोर सिस्टम पर बनाई गई थी। कोई भी टूल जो अपने स्थानांतरित डेटा को सुरक्षित करने के लिए OpenSSL के PRNG पर निर्भर था, ऑफ़लाइन हमले के प्रति संवेदनशील हो सकता है। कोई भी SSH सर्वर जो दोषपूर्ण सिस्टम द्वारा उत्पन्न होस्ट कुंजी का उपयोग करता है, ट्रैफ़िक डिक्रिप्शन के अधीन है और मैन-इन-द-मिडिल हमला उपयोगकर्ताओं को दिखाई नहीं देगा। यह दोष इसलिए गंभीर है क्योंकि जिन सिस्टमों में डेबियन सॉफ़्टवेयर का उपयोग नहीं होता, उन्हें भी ऑडिट करने की आवश्यकता है, यदि डेबियन सिस्टम पर बनाई गई कोई कुंजी उपयोग में हो। डेबियन और Ubuntu परियोजनाओं ने कमजोर कुंजियों की पहचान करने के लिए टूल का एक सेट जारी किया है। आप इन्हें नीचे संदर्भ अनुभाग में सूचीबद्ध पा सकते हैं।
डेबियन और Ubuntu द्वारा प्रकाशित ब्लैकलिस्ट दर्शाती हैं कि कुंजी स्थान कितना छोटा है। जब एक नई OpenSSH कुंजी बनाई जाती है, तो किसी दिए गए आर्किटेक्चर, कुंजी आकार और कुंजी प्रकार के लिए केवल 32,767 संभावित परिणाम होते हैं। इसका कारण यह है कि PRNG द्वारा उपयोग किया जाने वाला एकमात्र "यादृच्छिक" डेटा प्रक्रिया की ID है। इन ब्लैकलिस्ट से मेल खाने वाली वास्तविक कुंजियाँ उत्पन्न करने के लिए, हमें लक्ष्य प्लेटफ़ॉर्म के लिए सही बाइनरी वाला एक सिस्टम और विशिष्ट प्रक्रिया ID के साथ कुंजियाँ उत्पन्न करने का एक तरीका चाहिए। प्रक्रिया ID समस्या को हल करने के लिए, मैंने एक साझा लाइब्रेरी लिखी जिसे प्रीलोड किया जा सकता है और जो getpid() लिबc कॉल के लिए उपयोगकर्ता-निर्दिष्ट मान लौटाती है।
अगला कदम एक chroot वातावरण बनाना था जिसमें कमजोर सिस्टम से वास्तविक बाइनरी और लाइब्रेरीज़ शामिल हों। मैंने स्थानीय नेटवर्क पर एक Ubuntu सिस्टम से स्नैपशॉट लिया। आप पूरा chroot वातावरण यहाँ पा सकते हैं। विशिष्ट प्रकार, बिट संख्या और प्रक्रिया ID के साथ एक OpenSSH कुंजी उत्पन्न करने के लिए, मैंने एक शेल स्क्रिप्ट लिखी जिसे chroot वातावरण के भीतर से निष्पादित किया जा सकता है। आप इस शेल स्क्रिप्ट को यहाँ पा सकते हैं। यह स्क्रिप्ट निकाले गए Ubuntu फ़ाइल सिस्टम की रूट निर्देशिका में रखी जाती है। एक कुंजी उत्पन्न करने के लिए, इस स्क्रिप्ट को निम्नलिखित कमांड लाइन के साथ कॉल किया जाता है:
# chroot ubunturoot /dokeygen.sh 1 -t dsa -b 1024 -f /tmp/dsa_1024_1
यह getpid() का मान हमेशा "1" लौटाने के साथ एक नई OpenSSH 1024-बिट DSA कुंजी उत्पन्न करेगा। अब हमारे पास हमारी पहली पूर्व-उत्पन्न SSH कुंजी है। यदि हम इस प्रक्रिया को 32,767 तक के सभी PID के लिए जारी रखते हैं और फिर इसे 2048-बिट RSA कुंजियों के लिए दोहराते हैं, तो हमने बगी OpenSSL लाइब्रेरी चलाने वाले x86 सिस्टम के लिए मान्य कुंजी श्रेणियों को कवर कर लिया है। इस कुंजी सेट के साथ, हम किसी भी उपयोगकर्ता खाते से समझौता कर सकते हैं जिसमें authorized_keys फ़ाइल में सूचीबद्ध एक कमजोर कुंजी है। यह कुंजी सेट पहले से कैप्चर किए गए SSH सत्र को डिक्रिप्ट करने के लिए भी उपयोगी है, यदि SSH सर्वर कमजोर होस्ट कुंजी का उपयोग कर रहा था। 1024-बिट DSA और 2048-बिट RSA कुंजियों (x86) के पूर्व-उत्पन्न कुंजी सेटों के लिंक नीचे डाउनलोड अनुभाग में दिए गए हैं।
इन कुंजियों के बारे में दिलचस्प बात यह है कि वे प्रक्रिया ID से कैसे जुड़ी हैं। चूंकि अधिकांश डेबियन-आधारित सिस्टम अनुक्रमिक प्रक्रिया ID मानों (सिस्टम बूट से बढ़ते हुए और आवश्यकता पड़ने पर वापस लपेटते हुए) का उपयोग करते हैं, किसी दिए गए कुंजी की प्रक्रिया ID यह भी संकेत दे सकती है कि सिस्टम बूट से कितनी जल्दी वह कुंजी उत्पन्न हुई थी। यदि हम इसके विपरीत देखते हैं, तो हम यह निर्धारित कर सकते हैं कि अपने लक्ष्य के आधार पर ब्रूट फोर्स के दौरान किन कुंजियों का उपयोग करना है। बूट समय पर उत्पन्न कुंजी (जैसे SSH होस्ट कुंजी) का अनुमान लगाने की कोशिश करते समय, 200 से कम PID मान वाली कुंजियाँ ब्रूट फोर्स के लिए सबसे अच्छा विकल्प होंगी। उपयोगकर्ता-जनित कुंजी पर हमला करते समय, हम मान सकते हैं कि अधिकांश मान्य उपयोगकर्ता कुंजियाँ 500 से अधिक और 10,000 से कम प्रक्रिया ID के साथ बनाई गई थीं। यह अनुकूलन SSH प्रोटोकॉल पर दूरस्थ उपयोगकर्ता खाते पर ब्रूट फोर्स हमले को काफी तेज कर सकता है।
निकट भविष्य में, इस साइट पर एक ब्रूट फोर्स टूल जोड़ा जाएगा जिसका उपयोग किसी भी SSH खाते तक त्वरित पहुँच प्राप्त करने के लिए किया जा सकता है जो कमजोर कुंजी का उपयोग करके सार्वजनिक कुंजी प्रमाणीकरण की अनुमति देता है। नीचे दी गई डेटा फ़ाइलों में कुंजियाँ निम्नलिखित नामकरण परंपरा का उपयोग करती हैं:
/ एल्गोरिथम / बिट्स / फिंगरप्रिंट-प्रोसेसआईडी
और
/ एल्गोरिथम / बिट्स / फिंगरप्रिंट-प्रोसेसआईडी.pub
किसी भी सार्वजनिक कुंजी के लिए निजी कुंजी फ़ाइल प्राप्त करने के लिए, आपको कुंजी फिंगरप्रिंट जानना होगा। यह फिंगरप्रिंट प्राप्त करने का सबसे आसान तरीका निम्नलिखित कमांड के माध्यम से है:
$ ssh-keygen -l -f targetkey.pub
2048 c6:7b:14:fa:ae:b6:89:e6:67:17:ee:04:17:b0:ec:4e targetkey.pub
यदि हम संपादक में सार्वजनिक कुंजी को देखते हैं, तो हम यह भी अनुमान लगा सकते हैं कि कुंजी प्रकार RSA है। इस सार्वजनिक कुंजी के लिए निजी कुंजी का पता लगाने के लिए, हमें डेटा फ़ाइलों को निकालना होगा, और निम्नलिखित नाम वाली फ़ाइल देखनी होगी:
rsa/2048/**c67b14faaeb689e66717ee0417b0ec4e-26670**
उपरोक्त उदाहरण में, फिंगरप्रिंट को हेक्साडेसिमल में कोलन हटाकर दर्शाया गया है, और प्रक्रिया ID को "26670" के रूप में इंगित किया गया है। यदि हम किसी कमजोर सिस्टम पर प्रमाणीकरण करना चाहते हैं जो प्रमाणीकरण के लिए इस सार्वजनिक कुंजी का उपयोग करता है, तो हम निम्नलिखित कमांड चलाएंगे:
$ ssh -i rsa/2048/c67b14faaeb689e66717ee0417b0ec4e-26670 root@targetmachine
प्रश्न: इन कुंजियों को उत्पन्न करने में कितना समय लगा?
उत्तर: मैंने 2.33Ghz पर क्लॉक किए गए 31 Xeon कोर का उपयोग किया। x86 के लिए 1024-बिट DSA और 2048-बिट RSA कुंजियाँ उत्पन्न करने में दो घंटे लगे। 4096-बिट RSA कुंजियाँ उत्पन्न करने में लगभग 6 घंटे लगे। 8192-बिट RSA कुंजी निर्माण अपनी वर्तमान दर पर लगभग 100 घंटे लेगा और पूरा होने से पहले संभवतः रोक दिया जाएगा।
प्रश्न: क्या आप कुंजी-निर्माण को कई प्रोसेसरों पर वितरित करने के लिए अपना कोड साझा करेंगे?
उत्तर: नहीं। कोड इस विशिष्ट क्लस्टर के लिए हार्डकोडेड है और इसे साफ करने लायक बनाने के लिए बहुत खराब लिखा गया है।
प्रश्न: इन कुंजियों का उपयोग करके SSH उपयोगकर्ता खाते को क्रैक करने में कितना समय लगता है?
उत्तर: यह नेटवर्क की गति और SSH सर्वर के कॉन्फ़िगरेशन पर निर्भर करता है। DSA-1024 और RSA-2048 दोनों की सभी 32,767 कुंजियों को कुछ घंटों के भीतर आज़माना संभव होना चाहिए, लेकिन लक्ष्य सर्वर पर एंटी-ब्रूट-फोर्स स्क्रिप्ट से सावधान रहें।
प्रश्न: मैं 16384-बिट RSA कुंजियों का उपयोग करता हूं, क्या ये तोड़ी जा सकती हैं?
उत्तर: हां, यह केवल समय और प्रोसेसिंग पावर की बात है। 8192-बिट RSA कीसेट को सभी 32,767 कुंजियाँ उत्पन्न करने में लगभग 3100 घंटे का CPU समय लगेगा (मेरे द्वारा अभी उपयोग किए जा रहे 31 कोर पर 100 घंटे)। मुझे लगता है कि 16384-बिट RSA कीसेट को लगभग 100,000 घंटे के CPU समय के करीब लगेगा। ध्यान रखने वाली एक बात यह है कि अधिकांश कुंजियाँ प्रक्रिया ID सीड पर आधारित एक बहुत छोटी सीमा के भीतर होती हैं, और अधिकांश उपयोगकर्ता कुंजियों को कवर करने के लिए पूरे सेट को उत्पन्न करने की आवश्यकता नहीं होगी (अधिकांश कुंजियाँ पहले 3,000 प्रक्रिया ID के भीतर होती हैं)।
कॉपीराइट © 2008 H D Moore