
# CVE-2021-4034 (PwnKit) के लिए रूट एक्सप्लॉइट यह pkexec के आउट-ऑफ-बाउंड राइट का दुरुपयोग करके Linux सिस्टम पर विशेषाधिकारों को रूट तक बढ़ाने वाला एक्सप्लॉइट है।
PwnKit कमजोरी के लिए रूट एक्सप्लॉइट। मूल रिपोर्ट देखें यहाँ।
इस एक्सप्लॉइट का उपयोग लक्ष्य प्रणाली के मालिकों की स्पष्ट अनुमति के साथ करें।
libc के अलावा कोई निर्भरता नहीं चाहिए। बस make चलाएँ।
विकल्पों के बिना चलाने से एक्सप्लॉइट निष्पादित होगा:
[linux@linux ~]$ ./exploit
-----------------------------------------------------------------------------
__\ / __ __ _ __ _ __ | \ / _ ___
/ V |_ --- _)/ \ _)/| ---|_|/ \__)|_| | V |_) _/|_|
\__ |__ /__\_//__ | |\_/__) | | | \/__| |
-----------------------------------------------------------------------------
sh-5.1# whoami
root
sh-5.1#
आप pkexec का पथ और "from" कैरेक्टर सेट दोनों को अनुकूलित कर सकते हैं:
[linux@linux ~]$ ./exploit -h
...
./exploit [-c] [-h] [-f from_charset] [-p /path/to/pkexec]
-----------------------------------------------------------------------------
-c सिर्फ teardown - एक्सप्लॉइट न करें
-p <path> pkexec का पथ (डिफ़ॉल्ट: "/usr/bin/pkexec")
-f <from_charset> कस्टम "from" कैरेक्टर सेट (डिफ़ॉल्ट: "UTF-8")
-h यह संदेश प्रदर्शित करें
GIO_USE_VFS का मामला क्या है?!मैंने सोशल मीडिया पर कुछ लोगों को पूछते देखा कि कुछ एक्सप्लॉइट क्यों विफल हो जाते हैं यदि
GIO_USE_VFS= परिभाषित नहीं है? वे पुराने संस्करणों के साथ क्यों काम करते हैं?
polkit में कमिट daf3d5c2d15466a267221fcb099c59c870098e03 अपराधी है।
यहाँ diff का प्रासंगिक भाग है:
--- a/src/programs/pkexec.c
+++ b/src/programs/pkexec.c
@@ -503,6 +503,9 @@ main (int argc, char *argv[])
opt_user = NULL;
local_agent_handle = NULL;
+ /* GIO से दूरस्थ फ़ाइल एक्सेस अक्षम करें। */
+ setenv ("GIO_USE_VFS", "local", 1);
+
/* सही आह्वान की जाँच करें */
if (geteuid () != 0)
{
इस कमिट से पहले के संस्करण GIO_USE_VFS चर को परिभाषित करने की आवश्यकता के बिना शोषण योग्य हैं। इसके बाद के संस्करण - तब तक शोषण योग्य नहीं हैं जब तक यह चर परिभाषित न हो।
कमिट का उद्देश्य वास्तव में एक भटकाव है। यह वह नहीं है जो चर
का अर्थ है, यह इसकी उपस्थिति प्रोग्राम के वातावरण को कैसे प्रभावित करती है। सच्चाई के लिए हमें libc को देखना होगा।
libc में एक प्रक्रिया का वातावरण char *s की एक सरणी द्वारा दर्शाया जाता है,
जिसे इस वैश्विक चर द्वारा इंगित किया जाता है:
char **environ;
environ हीप पर रहता है और कभी-कभी स्थानांतरित होता है। आप शायद
पहले से ही जानते हैं कि यह कहाँ जा रहा है। setenv.c से यह कोड स्निपेट देखें:
#if !_LIBC
# define __environ environ
# ifndef HAVE_ENVIRON_DECL
extern char **environ;
# endif
#endif
int
__add_to_environ (const char *name, const char *value, const char *combined,
int replace)
{
char **ep;
// ... छोड़ रहे हैं
ep = __environ;
size = 0;
if (ep != NULL)
{
for (; *ep != NULL; ++ep)
if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
break;
else
++size;
}
if (ep == NULL || __builtin_expect (*ep == NULL, 1))
{
char **new_environ;
/* हमने यह स्थान आवंटित किया; हम इसे बढ़ा सकते हैं। */
new_environ = (char **) realloc (last_environ,
(size + 2) * sizeof (char *));
// ... छोड़ रहे हैं
last_environ = __environ = new_environ;
}
__add_to_environ() को setenv(3) और putenv(3) दोनों द्वारा बुलाया जाता है ताकि
वे जो वादा करते हैं उसे पूरा करें - एक पर्यावरण चर सेट करें। यदि प्रश्न में पर्यावरण चर
परिभाषित नहीं है, तो environ को एक नई प्रविष्टि (नए पर्यावरण key=value जोड़े के लिए एक पॉइंटर) को समायोजित करने के लिए पुनः आवंटित करना होगा। यदि यह
परिभाषित है, तो environ सरणी का आकार नहीं बदला है और इस प्रकार
पुनः आवंटन का कोई कारण नहीं है। संक्षिप्तता के लिए मैंने कोड का वह हिस्सा छोड़ दिया है - मैं
आपको इसे देखने के लिए प्रोत्साहित करता हूँ।
अब एक्सप्लॉइट पर वापस आते हैं। यदि आप यहाँ तक पहुँच गए हैं, तो आप शायद
पहले से ही इस एक्सप्लॉइट के पीछे की पद्धति जानते हैं (यदि नहीं तो कृपया
मूल रिपोर्ट देखें)।
हम pkexec को एक खाली प्रोग्राम तर्क (argv) पास करके एक पर्यावरण चर में घुसने की कोशिश कर रहे हैं। जब argc वास्तव में खाली होता है (एक प्रोग्राम नाम भी नहीं),
तो पर्यावरण चर, जो आसन्न होते हैं, तर्कों से टकराते हैं।
हम इस व्यवहार का दुरुपयोग करके pkexec को लक्षित निष्पादन योग्य का एक कैनोनिकल पथ
पर्यावरण में लिखने के लिए मजबूर करते हैं। हालाँकि, कोड के इस भाग तक पहुँचने से पहले यह होता है:
setenv ("GIO_USE_VFS", "local", 1);
यदि यह चर पर्यावरण में मौजूद नहीं है तो environ को
पुनः आवंटित किया जाएगा, इस प्रकार argv से कभी टकराएगा नहीं। परिणामस्वरूप, सीमा से बाहर
लेखन प्रोग्राम के पर्यावरण को प्रभावित नहीं करेगा, जिससे
एक्सप्लॉइट विफल हो जाएगा।