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

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

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

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

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

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
उपकरण/GitHubGitHub/chenaotian/cve-2022-0847
विशेषाधिकार वृद्धिभेद्यता विश्लेषणशोषणलर्निंग और शिक्षाबाइनरी शोषणलैब और अभ्यास
GitHubchenaotian/cve-2022-0847

CVE-2022-0847

CVE-2022-0847 (Dirty Pipe) Linux कर्नेल विशेषाधिकार वृद्धि भेद्यता का प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट और विस्तृत विश्लेषण, जिसमें परीक्षण और डीबगिंग के लिए Docker वातावरण शामिल है।

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

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

सभी देखें →

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

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

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

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

CVE-2022-0847 Dirty Pipe Linux कर्नेल विशेषाधिकार वृद्धि विश्लेषण

[toc]

यह लेख पहली बार Huawei सुरक्षा सार्वजनिक खाते में प्रकाशित हुआ था, यह ब्लॉग संस्करण है (अधिक पूर्ण)

पहला लिंक: https://mp.weixin.qq.com/s/6VhWBOzJ7uu80nzFxe5jpg

भेद्यता परिचय

भेद्यता संख्या: CVE-2022-0847 (उपनाम: गंदा पाइप)

भेद्यता उत्पाद: Linux कर्नेल - splice syscall

प्रभावित संस्करण: Linux 5.8 पैच f6dd975583bd द्वारा शुरू किया गया ~ 5.16.11, 5.15.25, 5.10.102 द्वारा ठीक किया गया

भेद्यता का प्रभाव: किसी भी पठनीय फ़ाइल पर एक पृष्ठ से अधिक नहीं (पर्याप्त) सामग्री लिखना, स्थानीय विशेषाधिकार वृद्धि संभव।

पर्यावरण सेटअप

भेद्यता विश्लेषण Docker: chenaotian/cve-2022-0847 (यदि अभी भी पहुँच योग्य नहीं है तो मैंने इसे अभी तक अपलोड नहीं किया है)

प्रदान करता है:

  • संकलित कमजोर डिबग करने योग्य कर्नेल 5.13
  • qemu, gdb, Linux कर्नेल 5.13 स्रोत कोड
  • exp

प्रारंभ:

root@kitploit:~
cd ~/cve-2022-0847
gcc exp.c -o exp --static && cp exp ./rootfs && cd rootfs
find . | cpio -o --format=newc > ../rootfs.img
cd ../ 
./boot.sh

डिबगिंग:

root@kitploit:~
gdb ./vmlinux
target remote :10086
directory /root/linux-5.13
b do_splice
b copy_page_to_iter_pipe 
b pipe_write
ignore 3 15
...
p *(struct pipe_inode_info *) pipe
p (struct pipe_buffer)pipe->bufs[0]

भेद्यता सिद्धांत

भेद्यता का संक्षिप्त सिद्धांत यह है कि splice फ़ंक्शन को कॉल करके फ़ाइल को "ज़ीरो-कॉपी" रूप में pipe पर भेजा जा सकता है। कोड स्तर पर ज़ीरो-कॉपी का अर्थ है कि फ़ाइल कैश पेज (page cache) को सीधे pipe के buf पेज के रूप में उपयोग किया जाता है। लेकिन यहाँ एक चर प्रारंभ न करने की भेद्यता शुरू की गई है, जिससे फ़ाइल कैश पेज बाद में pipe चैनल में सामान्य pipe कैश पेज के रूप में माना जाता है और "आगे लिखा" जा सकता है और इस प्रकार छेड़छाड़ की जा सकती है। हालाँकि, इस स्थिति में, कर्नेल इस कैश पेज को "गंदा पेज" नहीं मानेगा, और थोड़े समय (अगले रिबूट आदि तक) के लिए डिस्क पर फ्लश नहीं होगा। इस अवधि के दौरान, उस फ़ाइल तक पहुँचने वाले सभी परिदृश्य छेड़छाड़ किए गए फ़ाइल कैश पेज का उपयोग करेंगे, जिससे "थोड़े समय में किसी भी पठनीय फ़ाइल में मनमाना लेखन" का संचालन प्राप्त होता है। इससे स्थानीय विशेषाधिकार वृद्धि पूरी की जा सकती है।

भेद्यता घटना बिंदु

पैच के अनुसार, भेद्यता बिंदु copy_page_to_iter_pipe फ़ंक्शन में स्थित है, जहाँ buf->flags के प्रारंभिकीकरण को जोड़ा गया है, इसलिए यह एक चर प्रारंभ न करने की भेद्यता है।

image-20220308170149137

copy_page_to_iter_pipe का कॉल बिंदु splice सिस्टम कॉल में दिखाई देता है। splice फ़ंक्शन (सिस्टम कॉल) "ज़ीरो-कॉपी" विधि द्वारा फ़ाइल सामग्री को पाइप में स्थानांतरित करता है। पारंपरिक रूप से फ़ाइल सामग्री को सीधे पाइप में डालने की तुलना में यह बेहतर प्रदर्शन करता है। विस्तार से नीचे वर्णित है।

पाइप सिद्धांत और pipe_write

सबसे पहले, भेद्यता उपनाम गंदा पाइप है, आइए पहले पाइप (pipe) को समझें। pipe कर्नेल द्वारा प्रदान किया गया एक संचार पाइप है, जिसे pipe/pipe2 फ़ंक्शन द्वारा बनाया जाता है, जो दो फ़ाइल डिस्क्रिप्टर लौटाता है, एक डेटा भेजने के लिए और दूसरा डेटा प्राप्त करने के लिए, पाइप के दो सिरों के समान, विशिष्ट उपयोग के बारे में अधिक नहीं बोलेंगे।

image-20220309124007780

कर्नेल में कार्यान्वयन के बारे में संक्षेप में, आमतौर पर पाइप कैश स्थान की कुल लंबाई 65536 बाइट्स को पृष्ठों के रूप में प्रबंधित किया जाता है, कुल 16 पृष्ठ (एक पृष्ठ 4096 बाइट्स), पृष्ठ निरंतर नहीं होते हैं, बल्कि एक सरणी के माध्यम से प्रबंधित होते हैं, जो एक रिंग लिंक्ड लिस्ट बनाते हैं। दो लिंक्ड लिस्ट पॉइंटर बनाए रखे जाते हैं, एक लिखने के लिए (pipe->head), और एक पढ़ने के लिए (pipe->tail), यहाँ मुख्य रूप से pipe_write फ़ंक्शन का विश्लेषण किया गया है:

linux-5.13\fs\pipe.c : 400 : pipe_write

root@kitploit:~
static ssize_t
pipe_write(struct kiocb *iocb, struct iov_iter *from)
{
    struct file *filp = iocb->ki_filp;
    struct pipe_inode_info *pipe = filp->private_data;
    unsigned int head;
    ssize_t ret = 0;
    size_t total_len = iov_iter_count(from);
    ssize_t chars;
    bool was_empty = false;
    bool wake_next_writer = false;

    ··· ···
    ··· ···
    head = pipe->head;
    was_empty = pipe_empty(head, pipe->tail);
    chars = total_len & (PAGE_SIZE-1);
    if (chars && !was_empty) { 
        //[1] पाइप कैश खाली नहीं है, तो वर्तमान अंतिम पृष्ठ से "आगे" लिखने का प्रयास करें
        unsigned int mask = pipe->ring_size - 1;
        struct pipe_buffer *buf = &pipe->bufs[(head - 1) & mask];
        int offset = buf->offset + buf->len; 

        if ((buf->flags & PIPE_BUF_FLAG_CAN_MERGE) &&
            offset + chars <= PAGE_SIZE) { 
            /*[2] महत्वपूर्ण, यदि PIPE_BUF_FLAG_CAN_MERGE ध्वज मौजूद है, तो इस पृष्ठ को आगे लिखने की अनुमति है
             * यदि लिखने की लंबाई पृष्ठ सीमा को पार नहीं करती है, तो आगे लिखें, अन्यथा नया पृष्ठ शुरू करें */
            ret = pipe_buf_confirm(pipe, buf);
            ···
            ret = copy_page_from_iter(buf->page, offset, chars, from);
            ···
            }
            buf->len += ret;
            ···
        }
    }

    for (;;) {//[3] यदि पिछले पृष्ठ पर आगे नहीं लिख सकते, तो नया पृष्ठ शुरू करें
        ··· ···
        head = pipe->head;
        if (!pipe_full(head, pipe->tail, pipe->max_usage)) {
            unsigned int mask = pipe->ring_size - 1;
            struct pipe_buffer *buf = &pipe->bufs[head & mask];
            struct page *page = pipe->tmp_page;
            int copied;

            if (!page) {//[4] एक नया पृष्ठ आवंटित करें
                page = alloc_page(GFP_HIGHUSER | __GFP_ACCOUNT);
                if (unlikely(!page)) {
                    ret = ret ? : -ENOMEM;
                    break;
                }
                pipe->tmp_page = page;
            }

            spin_lock_irq(&pipe->rd_wait.lock);

            head = pipe->head;
            ··· ···
            pipe->head = head + 1;
            spin_unlock_irq(&pipe->rd_wait.lock);

            /* इसे बफर सरणी में डालें */
            buf = &pipe->bufs[head & mask];
            buf->page = page;//[5] नए आवंटित पृष्ठ को पृष्ठ सरणी में रखें
            buf->ops = &anon_pipe_buf_ops;
            buf->offset = 0;
            buf->len = 0;
            if (is_packetized(filp))
                buf->flags = PIPE_BUF_FLAG_PACKET;
            else
                buf->flags = PIPE_BUF_FLAG_CAN_MERGE;
                //[6] ध्वज सेट करें, डिफ़ॉल्ट PIPE_BUF_FLAG_CAN_MERGE
            pipe->tmp_page = NULL;

            copied = copy_page_from_iter(page, 0, PAGE_SIZE, from); 
            //[7] कॉपी ऑपरेशन
            ··· ···
            ret += copied;
            buf->offset = 0;
            buf->len = copied;

            ··· ···
        }
        ··· ···
    }
    ··· ···
    return ret;
}
टूल डाउनलोड करें