Skip to content
KitploitKITPLOIT
أدواتالمدونة
Log in
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2022-41218 — تفاصيل الثغرة الأمنية لـ CVE-2022-41218 | Kitploit
أدوات/GitHubGitHub/tobey123/cve-2022-41218
تحليل الثغرات الأمنيةالاستغلالاستغلال الملفات الثنائية
GitHubtobey123/cve-2022-41218

CVE-2022-41218

تفاصيل الثغرة الأمنية لـ CVE-2022-41218

عرض المستودع
4منذ 4 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

مقدمة

هذه الثغرة هي ثغرة حالة سباق (race condition) تحدث في drivers/media/dvb-core/dmxdev.c. لذلك، قد تحدث حالة سباق في برنامج تشغيل جهاز USB الذي يستخدم هذا dmxdev.

يمكن استخدام هذه الثغرة لتفعيل 3 عمليات UAF.

الثغرة

1. كتابة UAF في vmalloc

أولاً، ترتيب الاستغلال هو كما يلي (قمت بالتصحيح باستخدام drivers/media/usb/ttusb-dec/ttusb_dec.c):``` cpu0 cpu1 cpu 2 1. dvb_dvr_open() 2. ttusb_dec_disconnect() ttusb_dec_exit_dvb() dvb_dmxdev_release() wait_event(dmxdev->dvr_dvbdev->wait_queue, …) 3. dvb_demux_open() dvb_demux_ioctl() dvb_usercopy() copy_from_user() <- userfaultfd stuck 4. dvb_dvr_release() 5. vfree(dmxdev->filter) 6. copy_from_user() <- userfaultfd release dvb_demux_do_ioctl() struct dmxdev *dmxdev = dmxdevfilter->dev; <- UAF!!

التدفق التفصيلي للاستغلال يكون كما يلي:

1. افتح العقدة dvr0 من بين عُقد الأجهزة. يؤدي هذا إلى استدعاء الدالة dvb_dvr_open() لتنفيذ `dvbdev->users++`.
في هذه الحالة، عند تنفيذ ttusb_dec_disconnect() عن طريق إزالة جهاز usb، يتم تعليق التنفيذ عند شرط `wait_event(dmxdev->dvr_dvbdev->wait_queue, …)`.

2. قم بإزالة جهاز USB فعليًا.
في هذه الحالة، وأثناء تنفيذ الدالة ttusb_dec_disconnect()، فإنها تنتظر عند `wait_event(dmxdev->dvr_dvbdev->wait_queue, …)`.

3. استدعِ open() على العقدة demux0 بحيث يتم استدعاء الدالة dvb_demux_open().
تنفذ هذه الدالة أيضًا `dvbdev->users++` بشكل مشابه للدالة dvb_dvr_open() في الخطوة 1.
ومع ذلك، يحدث هذا العد غير الصحيح للمراجع لأن الدالة dvb_dmxdev_release() التي تنتظر حاليًا قد تجاوزت بالفعل التحقق من `dvbdev->users`:```
void dvb_dmxdev_release(struct dmxdev *dmxdev)
{
        dmxdev->exit = 1;
        if (dmxdev->dvbdev->users > 1) {    // This check is bypassed. improper reference counting.
                wait_event(dmxdev->dvbdev->wait_queue,
                                dmxdev->dvbdev->users == 1);
        }
        if (dmxdev->dvr_dvbdev->users > 1) {
                wait_event(dmxdev->dvr_dvbdev->wait_queue,    // Currently wait()ing here.
                                dmxdev->dvr_dvbdev->users == 1);
        }

        dvb_unregister_device(dmxdev->dvbdev);
        dvb_unregister_device(dmxdev->dvr_dvbdev);

        vfree(dmxdev->filter);
        dmxdev->filter = NULL;
        dmxdev->demux->close(dmxdev->demux);
}

ثم يستدعي ioctl() على demux0. عند الاستدعاء، تُرسل الوسيطة الثالثة عنوان مساحة المستخدم الذي تم تعيينه بواسطة userfaultfd (أو FUSE fs). الآن أثناء تشغيل ioctl، سيتوقف عند copy_from_user() الخاصة بـ dvb_usercopy():``` int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg, int (*func)(struct file *file, unsigned int cmd, void *arg)) { char sbuf[128]; void *mbuf = NULL; void *parg = NULL; int err = -EINVAL;

    /*  Copy arguments into temp kernel buffer  */
    switch (_IOC_DIR(cmd)) {
    case _IOC_NONE:
            /*
             * For this command, the pointer is actually an integer
             * argument.
             */
            parg = (void *) arg;
            break;
    case _IOC_READ: /* some v4l ioctls are marked wrong ... */
    case _IOC_WRITE:
    case (_IOC_WRITE | _IOC_READ):
            if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
                    parg = sbuf;
            } else {
                    /* too big to allocate from stack */
                    mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
                    if (NULL == mbuf)
                            return -ENOMEM;
                    parg = mbuf;
            }

            err = -EFAULT;
            if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))   // here
                    goto out;
            break;
    }
4. قم باستدعاء `close()` على واصف الملف (fd) في الخيط الذي قام بفتح عقدة dvr0.
ثم يتم استدعاء `dvb_dvr_release()`، ويتم تنفيذ `dvbdev->users--` و `wake_up(&dvbdev->wait_queue)` لتنبيه دالة `dvb_dmxdev_release()`، وهي تدفق .disconnect.

5. في تدفق .disconnect، دالة `dvb_dmxdev_release()` تنفذ `vfree(dmxdev->filter)`.

6. حرّر userfaultfd من خيط ioctl الخاص بـ demux0 الذي قام بضبط userfaultfd.
سيؤدي هذا إلى حدوث UAF عند قراءة عنوان `dmxdev->filter` الذي تم تحريره للتو من .disconnect.
يمكن الآن استخدام UAF في جميع حالات `dvb_demux_do_ioctl()`، وحتى LPE ممكن عند ربطه مع eBPF.
تنزيل الأداة