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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
cve-2023-41564-research — تحليل مفصل وإثبات مفهوم لـ CVE-2023-41564، وهي ثغرة XSS مخزنة في Cockpit CMS <=2.6.3، مع السبب الجذري على مستوى الكود وإرشادات التخفيف. | Kitploit
أدوات/GitHubGitHub/sota70/cve-2023-41564-research
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبأمن الويباختبار الاختراقالتعلم والتعليم
GitHubsota70/cve-2023-41564-research

cve-2023-41564-research

تحليل مفصل وإثبات مفهوم لـ CVE-2023-41564، وهي ثغرة XSS مخزنة في Cockpit CMS <=2.6.3، مع السبب الجذري على مستوى الكود وإرشادات التخفيف.

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

الأكثر شعبية

عرض الكل →

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

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

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

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

ملخص ثغرة CVE-2023-41564

CVE-2023-415641 هي ثغرة XSS مخزّنة (Stored XSS) موجودة في نظام إدارة المحتوى (CMS) المسمى Cockpit (بالإصدار <= v2.6.3).
وتتمثل هذه الثغرة في أنه عند رفع ملف HTML بامتداد .shtml أثناء رفع الملفات، يتم تنفيذ JavaScript فور فتح الملف المرفوع.

1: https://nvd.nist.gov/vuln/detail/CVE-2023-41564

آلية تنفيذ الهجوم

في البداية، سأشرح أسلوب الهجوم استنادًا إلى كود الإثبات PoC2 الذي نشره الشخص الذي يُرجَّح أنه مبلّغ الثغرة.
أولاً، سجّل الدخول إلى الموقع باستخدام حساب يمتلك صلاحية رفع الملفات.
cms login cms assets ثم ارفع ملف shtml مثل الملف الموضح أدناه.

root@kitploit:~

انسخ عنوان URL للملف المرفوع (Asset). cms link عند الوصول إلى الرابط المنسوخ، يتم تنفيذ السكربت المكتوب في كود HTML الموضح أعلاه. cms xss
2: https://github.com/LongHair00/Mitre_opensource_report/blob/main/CockpitCMS-StoredXSS.md

تفاصيل حدوث الثغرة

من هنا سأشرح نتائج التحقيق الأعمق الذي أجريته حول الثغرة.
تبدأ عملية رفع الأصول (Assets) من طلب POST يُرسل إلى المسار /assets/upload.
تم تعريف معالجة طلب الرفع في السطر 513 من الملف modules/Assets/bootstrap.php.
فيما يلي الكود:

root@kitploit:~
// assets api
$this->module('assets')->extend([

    // 省略
    'upload' => function(string|array $param = 'files', array $meta = [], bool $isUpload = true) {

        $files = [];

        if (is_string($param) && isset($this->app->request->files[$param])) {
            $files = $this->app->request->files[$param];
        } elseif (is_array($param) && isset($param['name'], $param['error'], $param['tmp_name'])) {
            $files = $param;
        }

        $finfo      = finfo_open(FILEINFO_MIME_TYPE);
        $uploaded  = [];
        $failed    = [];
        $_files     = [];
        $assets    = [];

        $allowed   = $this->app->retrieve('assets/allowed_uploads', '*');
        $allowed   = $allowed == '*' ? true : str_replace([' ', ','], ['', '|'], preg_quote(is_array($allowed) ? implode(',', $allowed) : $allowed));
        $max_size  = $this->app->retrieve('assets/max_upload_size', 0);

        $forbiddenExtension = ['bat', 'exe', 'sh', 'php', 'phar', 'phtml', 'phps', 'htm', 'html', 'xhtml', 'htaccess'];
        $forbiddenMime = [
            'application/x-httpd-php', 'application/x-php', 'text/x-php',
            'text/html', 'application/xhtml+xml'
        ];

        if (isset($files['name']) && is_array($files['name'])) {

            $cnt = count($files['name']);

            for ($i = 0; $i < $cnt; $i++) {

                $_file  = $this->app->path('#tmp:').'/'.$files['name'][$i];
                $_mime = $finfo->file($files['tmp_name'][$i]);
                $_isAllowed = $allowed === true ? true : preg_match("/\.({$allowed})$/i", $_file);
                $_sizeAllowed = $max_size ? filesize($files['tmp_name'][$i]) < $max_size : true;

                $extension = strtolower(pathinfo(parse_url($_file, PHP_URL_PATH), PATHINFO_EXTENSION));

                if (!$extension) {
                    $_isAllowed = false;
                }

                // prevent uploading php / html files
                if ($_isAllowed && (
                    in_array($extension, $forbiddenExtension) ||
                    in_array(strtolower($_mime), $forbiddenMime)
                )) {
                    $_isAllowed = false;
                }

                if (!$files['error'][$i] && $_isAllowed && $_sizeAllowed && ($isUpload ? move_uploaded_file($files['tmp_name'][$i], $_file) : rename($files['tmp_name'][$i], $_file))) {

                    $_files[]   = $_file;
                    $uploaded[] = $files['name'][$i];

                    if (\preg_match('/\.(svg|xml)$/i', $_file)) {
                        file_put_contents($_file, \SVGSanitizer::clean(\file_get_contents($_file)));
                    }

                } else {
                    $failed[] = $files['name'][$i];
                }
            }
        }

        if (count($_files)) {

            $assets = $this->add($_files, $meta, isset($meta['_id']));

            foreach ($_files as $file) {
                unlink($file);
            }
        }

        return ['uploaded' => $uploaded, 'failed' => $failed, 'assets' => $assets];
    },
    // 省略
]);

يتم تخزين دالة upload في متغير عضو في صنف App يحتفظ بدوال وحدة Assets، ويُسمى هذا المتغير registry['modules']['assets'].
لذلك، عند استدعاء دالة upload، يتم ذلك باستخدام الصيغة: $this->module('assets')->upload('file', $file);
يتم استدعاء دالة upload المسجلة هنا بواسطة صنف Assets4.

root@kitploit:~
public function upload() {
    this->helper('session')->close();
    this->hasValidCsrfToken(true);
    if (!this->isAllowed('assets/upload')) {
        return $this->stop(['error' => 'Upload not allowed'], 401);
    }
    $meta = ['folder' => $this->param('folder', '')];
    return $this->module('assets')->upload('files', $meta);
}

يمكنك ملاحظة أن دالة upload المسجلة في registry['modules']['assets'] هي التي يتم استدعاؤها.
لنلقِ نظرة الآن على دالة upload المكتوبة في bootstrap.php.
يتم هنا تعريف قائمة الامتدادات المحظورة في المتغير $forbiddenExtension.
ولكن، امتداد shtml غير مدرج في القائمة.
لذلك، تُعد هذه نقطة الخلل التي تجعل رفع ملفات shtml ممكنًا.

3: https://github.com/Cockpit-HQ/Cockpit/blob/2.6.3/modules/Assets/bootstrap.php#L51
4: https://github.com/Cockpit-HQ/Cockpit/blob/2.6.3/modules/Assets/Controller/Assets.php#L140

الإجراء الوقائي

بما أن سبب الثغرة هو أن امتداد shtml غير محظور، يمكن معالجتها بإضافة shtml إلى قائمة forbiddenExtension.

root@kitploit:~
$forbiddenExtension = ['bat', 'exe', 'sh', 'php', 'phar', 'phtml', 'phps', 'htm', 'html', 'xhtml', 'htaccess', 'shtml'];
تنزيل الأداة