Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
POC-CVE-2023-32233 — बैच अनुरोधों को प्रोसेस करते समय Netfilter nf_tables में Use-After-Free CVE-2023-32233 | Kitploit
उपकरण/GitHubGitHub/oferchen/poc-cve-2023-32233
विशेषाधिकार वृद्धिमेमोरी फोरेंसिकभेद्यता विश्लेषणशोषणपेनिट्रेशन टेस्टिंगपेलोड डेवलपमेंटबाइनरी शोषण
GitHuboferchen/poc-cve-2023-32233

POC-CVE-2023-32233

बैच अनुरोधों को प्रोसेस करते समय Netfilter nf_tables में Use-After-Free CVE-2023-32233

रिपॉजिटरी देखें
53623 साल पहलेKitploit द्वारा समीक्षित

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

नेटफ़िल्टर nf_tables में बैच अनुरोधों को संसाधित करते समय Use-After-Free

डेमो

Demo_CVE-2023-32233

भेद्यता विवरण

प्रभावित कोड आधिकारिक लिनक्स कर्नेल से उत्पन्न होता है https://kernel.org/ और नेटफ़िल्टर nf_tables घटक का हिस्सा है (net/netfilter/nf_tables_api.c).

Netfilter nf_tables अपने कॉन्फ़िगरेशन को एक परमाणु संक्रिया के रूप में अपडेट करने की अनुमति देता है। इस सुविधा का उपयोग करते समय, उपयोगकर्ता-मोड क्लाइंट बैच अनुरोध भेजते हैं जिसमें बुनियादी संक्रियाओं की एक सूची होती है। Netfilter nf_tables फिर बैच के सभी संक्रियाओं को एक एकल लेन-देन के रूप में संसाधित करता है। बैच को संसाधित करते समय, Netfilter nf_tables कॉन्फ़िगरेशन स्थिति अपडेट की जाँच करता है ताकि यह सुनिश्चित हो सके कि प्रत्येक क्रमिक बुनियादी संक्रिया मान्य है और यह बैच के भीतर पिछली सभी संक्रियाओं से स्थिति अपडेट को भी ध्यान में रखता है। हालांकि, वर्तमान में लागू की गई जाँच अपर्याप्त है।

हमारे विशिष्ट परिदृश्य में, हम एक Netfilter nf_tables कॉन्फ़िगरेशन से शुरू करते हैं जिसमें एक अनाम nft_set पर lookup अभिव्यक्ति वाला nft_rule है, और जहाँ अनाम nft_set में कुछ तत्व हैं। अगला, हम निम्नलिखित दो बुनियादी संक्रियाओं वाला एक बैच अनुरोध भेजते हैं:

  1. NFT_MSG_DELRULE संक्रिया nft_rule को हटाने के लिए।
    ध्यान दें कि यह अप्रत्यक्ष रूप से lookup अभिव्यक्ति और अनाम nft_set को भी हटा देता है।
  2. NFT_MSG_DELSETELEM संक्रिया हटाए गए अनाम nft_set के किसी भी तत्व को हटाने के लिए।

Netfilter nf_tables का वर्तमान संस्करण उपरोक्त बैच अनुरोध को स्वीकार करता है। यह तब nf_tables_commit_release() को कॉल करता है जो जारी किए गए संसाधनों को nf_tables_destroy_list में जोड़ता है। nf_tables_destroy_list को फिर nf_tables_trans_destroy_work() द्वारा संसाधित किया जाता है जो पहले NFT_MSG_DELRULE संक्रिया से संबंधित संसाधनों को डीलोकेट करता है:

root@kitploit:~
nft_commit_release()
    nf_tables_rule_destroy()
        nf_tables_expr_destroy()
            expr->ops->destroy() that points to nft_lookup_destroy()
                nf_tables_destroy_set()
                    nft_set_destroy()
                        kvfree() that deallocates memory used by `nft_set`

NFT_MSG_DELSETELEM संक्रिया को संसाधित करने से पहले, जहाँ डीलोकेटेड nft_set का संदर्भ निम्नलिखित कॉलों के दौरान nft_trans_elem_set() के माध्यम से एक्सेस किया जाता है:

root@kitploit:~
nft_commit_release()
    nf_tables_set_elem_destroy()
        nft_set_elem_ext()

उपरोक्त nft_set_elem_ext() के अंदर, nft_set_ext का स्थान निर्धारित करने के लिए डीलोकेटेड nft_set की मेमोरी स्थान एक्सेस की जाती है:

root@kitploit:~
static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
                                                   void *elem)
{
        return elem + set->ops->elemsize;
}

आगे की संक्रियाओं के लिए। इसलिए जब भी set->ops->elemsize का मान दूषित होता है, तो कुछ अप्रत्याशित मेमोरी स्थान को नष्ट किए जाने वाले nft_expr की सूची के रूप में व्याख्यायित किया जा सकता है:

root@kitploit:~
static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
                                       const struct nft_set *set, void *elem)
{
        struct nft_set_ext *ext = nft_set_elem_ext(set, elem);

        if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS))
                nft_set_elem_expr_destroy(ctx, nft_set_ext_expr(ext));

शोषण तकनीक

उपरोक्त भेद्यता का शोषण करने के लिए nf_tables_trans_destroy_work() के साथ एक रेस जीतना आवश्यक है जो लिनक्स कर्नेल के बैकग्राउंड वर्कर थ्रेड से निष्पादित होता है। यह मौजूदा शमनों पर विचार करने से पहले ही व्यावहारिक शोषण को जटिल बनाता है, जैसे कर्नेल स्लैब आवंटक का सख्तीकरण, कर्नेल एड्रेस स्पेस लेआउट रैंडमाइज़ेशन (KASLR) और विशेष रूप से कंट्रोल-फ़्लो इंटीग्रिटी। हालांकि, संलग्न PoC साबित करता है कि व्यवहार में उचित रूप से विश्वसनीय शोषण प्राप्त करना अभी भी संभव है।

भेद्यता का शोषण करने के लिए हमें nft_set से मेमोरी की सामग्री को संशोधित करने की आवश्यकता है, जब इसे nf_tables_rule_destroy() के अंतर्गत डीलोकेट किया जाता है, लेकिन इससे पहले कि इसका उपयोग nf_tables_set_elem_destroy() के अंतर्गत किया जाए। nf_tables_rule_destroy() और nf_tables_set_elem_destroy() दोनों को nf_tables_trans_destroy_work() के एक ही आह्वान के भीतर बुलाया जाता है, जो लिनक्स कर्नेल के बैकग्राउंड वर्कर थ्रेड से निष्पादित होता है। इसके अलावा, डीलोकेटेड मेमोरी चंक आमतौर पर केवल उसी CPU कोर से पुन: उपयोग के लिए उपलब्ध होता है।

जब nf_tables_trans_destroy_work() के साथ रेसिंग करते हैं, तो हम बैकग्राउंड वर्कर थ्रेड के लिए nf_tables_rule_destroy() और nf_tables_set_elem_destroy() को कॉल करने के बीच एक नियंत्रित विलंब जोड़कर अपनी संभावनाओं में सुधार करते हैं। उसके लिए हम बड़ी संख्या में तत्वों वाले एक अन्य nft_set को नष्ट करने के लिए एक अतिरिक्त संक्रिया सम्मिलित करते हैं। इसके अलावा, हम अन्य सभी CPU कोर को व्यस्त रखते हैं, ताकि बैकग्राउंड वर्कर थ्रेड के एक विशिष्ट CPU कोर पर शेड्यूल होने की संभावना हो, ताकि हम उसी CPU कोर से एक नई संरचना आवंटित करने का प्रयास कर सकें, ठीक उसके बाद जब वह nf_tables_rule_destroy() के अंतर्गत nft_set को डीलोकेट करता है। हमारा लक्ष्य एक अलग प्रकार का नया nft_set आवंटित करना है ताकि nf_tables_rule_destroy() के अंतर्गत डीलोकेट किए गए nft_set के मेमोरी स्थान का पुन: उपयोग किया जा सके।

नए nft_set प्रकार को set->ops->elemsize के लिए एक अलग मान का उपयोग करने के लिए चुना जाता है। इसलिए जब बैकग्राउंड वर्कर थ्रेड अंततः NFT_MSG_DELSETELEM संक्रिया को संसाधित करने के लिए nf_tables_set_elem_destroy() को कॉल करता है, तो यह अपने elem तर्क की गलत व्याख्या करता है, जिससे दूषित nft_set_ext *ext सही स्थान से कुछ बाइट आगे होता है। इसका मतलब है कि मूल nft_set_ext के कुछ उपयोगकर्ता-नियंत्रित डेटा फ़ील्ड को अब शीर्षलेख के रूप में व्याख्यायित किया जाता है, जिसके परिणामस्वरूप टाइप कन्फ़्यूज़न होता है।

इस टाइप कन्फ़्यूज़न का दुरुपयोग करने का एक तरीका दूषित nft_set_ext शीर्षलेखों को ऐसे ऑफ़सेट मानों के साथ तैयार करना है कि nf_tables_set_elem_destroy() किसी भी आसन्न मेमोरी ब्लॉक की सामग्री को नष्ट करने के लिए nft_expr की सूची के रूप में व्याख्यायित करे, निम्नलिखित कॉलों के माध्यम से:

root@kitploit:~
nft_set_elem_expr_destroy()
    __nft_set_elem_expr_destroy()
        nf_tables_expr_destroy()
            expr->ops->destroy()

शोषण के इस बिंदु पर, हमारे पास अभी तक कर्नेल मेमोरी लेआउट का विवरण नहीं है। इसलिए निरपेक्ष पॉइंटर पतों को तैयार करना संभव नहीं है। हालांकि, दूषित nft_set_ext शीर्षलेख तैयार करते समय हम अभी भी सीमा से बाहर के ऑफ़सेट का उपयोग कर सकते हैं, ताकि expr->ops->destroy() को आसन्न मेमोरी चंकों में कुछ मान्य nft_expr पर कॉल किया जाए।

इसके लिए हम नियंत्रित NFTA_LOG_PREFIX के साथ nft_log अभिव्यक्तियाँ स्प्रे करते हैं। वह nft_log->prefix तब nft_log_destroy() द्वारा डीलोकेट किया जाता है जब expr->ops->destroy() को कॉल किया जाता है:

root@kitploit:~
static void nft_log_destroy(const struct nft_ctx *ctx,
                            const struct nft_expr *expr)
{
        struct nft_log *priv = nft_expr_priv(expr);
        struct nf_loginfo *li = &priv->loginfo;

        if (priv->prefix != nft_log_null_prefix)
                kfree(priv->prefix);

ध्यान दें कि हम अभी भी स्प्रे किए गए nft_log अभिव्यक्ति के अन्य संदर्भ के माध्यम से इस मेमोरी को एक्सेस कर सकते हैं और फिर से डीलोकेट भी कर सकते हैं।

इसके अतिरिक्त, हम nft_log->prefix के आकार को भी नियंत्रित कर सकते हैं, ताकि इसे किसी भी स्लैब kmalloc-{8, ..., 192} से आवंटित किया जा सके। अंत में, संदर्भित मेमोरी को कर्नेल द्वारा वर्णों की एक स्ट्रिंग के रूप में व्याख्यायित किया जाता है, इसलिए जब हम इस पर विभिन्न ऑब्जेक्ट को ओवरले करते हैं तो भ्रष्टाचार के बारे में चिंता करने की आवश्यकता नहीं है। यह अनिवार्य रूप से गेम ओवर है।

एक असुविधा यह है कि कोई भी NULL वर्ण nft_log->prefix को समाप्त कर देता है, इसलिए हम मेमोरी सामग्री लीक करते समय NULL बाइट्स से आगे नहीं पढ़ सकते हैं। इसका समाधान अगले चरण में किया जाता है, जहाँ हम nft_log->prefix मेमोरी चंक का पुन: उपयोग करने और nft_log अभिव्यक्ति को नष्ट करने के लिए nft_object->udata आवंटित करते हैं। यह nft_object->udata मेमोरी को डीलोकेट करता है, लेकिन अब हम NULL बाइट्स पर किसी प्रतिबंध के बिना मेमोरी सामग्री को लीक करने के लिए nft_object->udata डैंगलिंग पॉइंटर का उपयोग कर सकते हैं।

आगामी चरणों के लिए उपयुक्त संरचनाओं की तलाश में, हमने nft_dynset_new() से आवंटित nft_expr पर निर्णय लिया। ये nft_log->prefix और nft_object->udata के समान स्लैब में रहते हैं। और साथ ही, हमारे पास आवंटन आकार पर उचित नियंत्रण है, ताकि बाद में यदि आवश्यक हो तो हम आसानी से विभिन्न आकार के स्लैब के बीच स्विच कर सकें।

इन संरचनाओं का उपयोग करने के लिए, हम nft_dynset अभिव्यक्ति के साथ पैकेट फ़िल्टर बनाते हैं। और जब हम लूपबैक इंटरफ़ेस पर कोई पैकेट भेजते हैं, तो nft_dynset अभिव्यक्ति संबंधित nft_set के लिए नए तत्व बनाने के लिए nft_dynset_new() को कॉल करती है। बनाए गए तत्व निम्न प्रकार की स्थितिजन्य अभिव्यक्तियाँ हैं:

  • nft_counter कर्नेल मेमोरी में nf_tables.ko का स्थान प्राप्त करने के लिए।
    संरचना में nf_tables.ko कर्नेल मॉड्यूल में nft_counter_ops का एक पॉइंटर शामिल है। हम nft_object->udata पढ़कर इस पॉइंटर को लीक करते हैं।

  • nft_quota मनमानी मेमोरी पढ़ने और लिखने के लिए।
    हम nft_quota->consumed पॉइंटर को संशोधित करने के लिए बार-बार nft_object->udata को डीलोकेट और पुनः आवंटित कर सकते हैं। अगला, हम NFT_MSG_GETSETELEM संक्रिया करते हैं जो संदर्भित मेमोरी की सामग्री को पढ़ने के लिए nft_quota_do_dump() को कॉल करता है और परिणाम में NFTA_QUOTA_CONSUMED विशेषता के रूप में परिणाम पास करता है। लिखने के लिए, हम केवल लूपबैक इंटरफ़ेस पर पैकेट भेजते हैं, जहाँ nft_quota_do_eval() कॉल करता है:

    root@kitploit:~
      static inline bool nft_overquota(struct nft_quota *priv,
                                       const struct sk_buff *skb)
      {
              return atomic64_add_return(skb->len, priv->consumed) >=
    

nft_quota->consumed को संशोधित करने के लिए।

हम कर्नेल कोर का आधार पता प्राप्त करने के लिए उपरोक्त मनमानी मेमोरी रीड का उपयोग करते हैं। और फिर हम "/sbin/modprobe" पथनाम के "sbin" उपस्ट्रिंग को संशोधित करते हैं, ताकि इसे "/tmp" से बदल दिया जाए। परिणामी पथनाम "//tmp/modprobe" का उपयोग तब कर्नेल द्वारा रूट विशेषाधिकारों के साथ एक प्रक्रिया शुरू करने के लिए किया जाता है, जहाँ हम फ़ाइल सामग्री को नियंत्रित करते हैं।

ध्यान दें कि हमने कंट्रोल-फ़्लो इंटीग्रिटी को बायपास करने का कोई जानबूझकर प्रयास नहीं किया। हालांकि, शोषण के प्रत्येक चरण के लिए, हमने सचेत रूप से सबसे लचीले और सबसे मजबूत प्रिमिटिव चुने। पता चला, कि हमारे चयन ने किसी भी ऐसे प्रिमिटिव से बचा लिया जो संभावित रूप से कंट्रोल-फ़्लो इंटीग्रिटी द्वारा अवरुद्ध किया जा सकता था। अब हम यह पुष्टि करने के लिए परीक्षण के साथ उत्सुक हैं कि परिणामी शोषण वास्तव में कंट्रोल-फ़्लो इंटीग्रिटी शमन वाले सिस्टम के विरुद्ध काम करता है।

टूल डाउनलोड करें