
مجموعة أدوات كشف ومختبر قابل لإعادة الإنتاج لـ CVE-2026-87902، وهو اجتياز مسار WordPress غير المصادق عليه. يتضمن فاحصًا عن بُعد، ومحلل IoC، وقواعد Sigma، ومنصة اختبار Docker.
أدوات الكشف ومنصة اختبار قابلة لإعادة الإنتاج من أجل GHSA-7hp8-65ch-5whp / CVE-2026-87902 — اجتياز مسار غير مُصادَق عليه في تحليل قوالب الصفحات يؤدي إلى تنفيذ كود عن بُعد شرطي (WordPress، CWE-98، CVSS 4.0: 9.2).
check/ | أداة تحكم عن بُعد، سلبية، دون الوصول إلى الخادم |
detect/ | محلل IoC + قواعد Sigma |
offensive/ | مُولِّد آثار، للتحقق من الكشف على سجلات حقيقية |
docker-compose.yml + provision/ | منصة اختبار، ثلاث تهيئات |
tests/validate.py | بوابة الجودة — تتحكم في أي نشر |
docs/ANALYSIS.md | الثغرة، التصحيح، تحليل قابلية الوصول المقيسة |
make up # monte le banc make ioc # corpus d'attaque -> journaux -> détection
make scan # contrôle le banc make test # porte de qualité
ثلاث نسخ من WordPress على 127.0.0.1، تعزل كل عامل من عوامل الحكم.
8092 هي الأكثر إفادة: نفس النواة المصابة كـ 8091، لكن الشرط المسبق للقالب
غائب. هذا ما يُظهر أن الفرز المبني على الإصدار وحده يبالغ في تقدير التعرض.
القالب هو المتغير الوحيد بين 8091 و8092، والتصحيح هو الوحيد بين 8091 و8093:
الثلاثة تتضمن نفس نوع المحتوى المخصص (provision/mu-plugins/00-lab-cpt.php)
ونفس مسبار حالة الطلب (10-lab-debug.php، ترويسات X-Lab-* التي تكشف is_page()،
قيمة pagename كما يراها المُحمِّل والقالب المُضمَّن في النهاية).
make up # démarre et provisionne — idempotent, relançable
make status # version de chaque instance
make down # arrêt make clean : supprime aussi les volumes
صورة Docker الرسمية تجعل /var/log/apache2/access.log يشير إلى
/dev/stdout: السجلات تخرج على مخرجات الحاوية، لا في ملف.
docker compose logs --no-log-prefix vuln-pre # accès + erreurs
docker compose logs --no-log-prefix vuln-pre > access.log # pour analyse
docker compose logs -f --no-log-prefix vuln-pre # en direct
make logs # les trois instances
على خادم تقليدي: /var/log/apache2/access.log، /var/log/nginx/access.log،
أو /home/*/logs/ عند معظم المستضيفين المشتركين. يجب أن يتضمن التنسيق
سلسلة الاستعلام — %r أو تنسيق combined يتضمنانها، أما LogFormat المبني على
%U فيفقدها، وبدونها لا يمكن أي كشف.
check/wp-ghsa-7hp8-check.pyمن الإنترنت، دون الوصول إلى الخادم. لا حمولة، لا اجتياز، لا
كتابة. لكل مضيف: كشف WordPress، الإصدار مُقاطَع من خمسة مصادر
(meta generator، تغذية RSS، wp-links-opml.php، readme.html، ?ver= لموارد
النواة)، القالب النشط، واستطلاع دليل page-*.
python3 check/wp-ghsa-7hp8-check.py --hosts-file hosts.txt --csv out.csv --json out.json
«مُصاب» تعني أن الكود المصاب موجود، لا أن المهاجم قادر على
تنفيذ كود. انظر docs/ANALYSIS.md.
--transport browser (افتراضي) يقود Google Chrome المثبَّت؛ الطلبات الفرعية
تنطلق من fetch() يُنفَّذ داخل الصفحة وترث حزمة TLS الخاصة بها، وترتيب
ترويسات HTTP/2 وملفات تعريف الارتباط، مما يتجنب التصفية بواسطة CDN قبل قراءة
الرابط. --transport direct يستخدم المكتبة القياسية فقط.
--scheme http|https يتجنب التراجع https → http، الذي يترك وإلا سطر 400
مع ClientHello TLS خام في سجل الهدف.
كل طلب مُوقَّت بالميلي ثانية في سجل JSONL: معرّف الجلسة، رقم الطلب، المرحلة،
الرابط، الحالة، الحجم، المدة، IP الخروج، العلامة.
العلامة SECAUDIT/<nonce> تُرسل في ترويسة X-Security-Audit و كلاحقة
User-Agent — مُضافة، لا مُستبدَلة أبدًا، لتبقى مرئية في access log
قياسي دون كسر بصمة المتصفح. قابلة للتخصيص عبر --marker.
لا أوراكل عن بُعد. الخيار
--probe-inclusionيُجري مقارنة تفاضلية على هدف خامل (wp-includes/version.php، مُحمَّل مسبقًا عند bootstrap:require_onceسيجعله no-op كاملًا). على تثبيت قياسي يُرجعNOT_REACHABLEحتى على نواة مصابة، مع استجابات متطابقة حتى البايت بين نسخة مُصحَّحة وغير مُصحَّحة. هذه ليست حدًا للأداة: WordPress يرد 404 قبل استشارة تسلسل القوالب. إثبات رقمي فيdocs/ANALYSIS.md، القسم 3.
تعبير نمطي حرفي من نوع pagename=.*%2e%2e%2f يمكن التحايل عليه بتغيير حالة
الأحرف (%2E)، أو بترميز إضافي (%252e)، أو بمزج الحرفي والمُرمَّز
(templates/..%2f../). أي قائمة أنماط غير مكتملة بحكم بنيتها.
لذلك ننطلق من الكود، لا من كتابة المهاجم:
pagename يخضع لفك ترميزين على الأكثر قبل الوصول إلى القرص — فك ترميز
PHP على سلسلة الاستعلام، ثم urldecode() الصريح في get_page_template().file_exists()
على مكوّن ... على Linux، الدليل الأب يُكتب بالضبط على البايتين
0x2E 0x2E؛ لا يوجد تمثيل آخر على مستوى نظام الملفات.إذن: فك الترميز حتى النقطة الثابتة والاختبار عند كل مستوى. هذا مجموعة شاملة صارمة لما يفعله WordPress — إضافة طبقة ترميز تنقل فقط المطابقة من مستوى، نمر به أيضًا.
python3 detect/wp-ghsa-7hp8-ioc.py access.log
docker compose logs --no-log-prefix vuln-pre | python3 detect/wp-ghsa-7hp8-ioc.py -
قواعد Sigma في detect/sigma-wp-ghsa-7hp8.yml.
بما أن Sigma لا يعرف فك الترميز التكراري، فهي تُعدِّد المستويات 0 إلى 3: هذا
تقريب مُفترَض، للفرز الأولي. أعد تمرير المطابقات في المحلل للبتّ.
WP::parse_request() يقرأ $_POST قبل $_GET. لذا يمكن أن يصل
pagename في جسم الطلب، غائبًا عن أي access log. التغطية ضرورية على
مستوى WAF أو ModSecurity، على الجسم.لا قاعدة على access log تغطي النقطة الأولى. هذا حد في الدعم، لا في القاعدة — لكن يجب معرفته قبل الإعلان عن تغطية كاملة.
offensive/generate-traces.py يعيد تشغيل 12 كتابة مختلفة لنفس الحمولة
(حرفية، ترميز مفرد/مزدوج/ثلاثي، حالة عليا وسفلى، مزجات،
ترميز UTF-8 مفرط، نقطة-مسافة) بالإضافة إلى 7 طلبات مشروعة تشبهها
(slug بنقاط، wp-includes في slug، رابط دائم بتاريخ، نسبة مئوية مُرمَّزة).
لا يحصل على شيء: لا يوجد exploit عن بُعد لهذا المتجه على تثبيت قياسي. يُنتج آثارًا — هذا كل غرضه.
make ioc # génère le corpus, récupère les journaux réels, passe l'analyseur
المتوقع، والمُتحقَّق منه بواسطة make test على سجلات Apache حقيقية:
12 حمولة مكتشفة من 12 (11 CRITICAL، الترميز المفرط في MEDIUM لأنه
غير قابل للاستغلال على Linux)، 0 تنبيه على 7 طلبات مشروعة، و
كشف فعّال عند ثلاثة مستويات فك ترميز مختلفة.
الهدف محدود بمنصة الاختبار المحلية؛ أي هدف آخر يتطلب --i-have-authorization.
register_argc_argv = Off في php.ini الخاص بـ SAPI الويب؛ إلغاء تثبيت PEAR إذا
كان غير مستخدم — هذا هو محور التضمين → التنفيذ المذكور في الإشعار.open_basedir محدود بجذر الموقع: يحصر أي تضمين محلي.make test هو شرط النشر: مصفوفة الفروع الـ 25 للإشعار
(بما في ذلك مزالق المقارنة — 6.8.9 < 6.8.10 رقميًا، الإصدارات المسبقة،
الفروع خارج المصفوفة)، أداة التحكم مقابل النسخ الثلاث، وقاعدة IoC مُتحقَّق منها
على سجلات حقيقية. تأكيد NOT_REACHABLE للمسبار مُثبَّت فيه عن قصد:
إذا انكسر، فهذا يعني أن السلوك تغيّر ويجب إعادة التحليل.
يُستخدم فقط على أصول تتحمل مسؤوليتها، أو بموجب تفويض كتابي.
منصة الاختبار تستمع فقط على 127.0.0.1؛ يجب ألا تُعرَّض النسخ المصابة أبدًا.
المسبار 10-lab-debug.php يكشف مسارات الخادم: وهو مخصص
لمنصة الاختبار فقط.
| المنفذ | النسخة | النواة | القالب النشط | الحكم المتوقع |
|---|
| 8091 | vuln-pre | 6.8.1 — غير مُصحَّح | Twenty Twelve، مع page-templates/ | AFFECTED_PRECONDITION_MET |
| 8092 | vuln-nopre | 6.8.1 — غير مُصحَّح | Twenty Twenty-Four، بدون page-* | AFFECTED_CORE_ONLY |
| 8093 | patched | 6.8.10 — مُصحَّح | Twenty Twelve، مع page-templates/ | NOT_AFFECTED |
| الحكم | المعنى |
|---|
AFFECTED_PRECONDITION_MET | نواة مصابة و دليل page-* على القالب النشط. ذو أولوية. |
AFFECTED_THEME_UNKNOWN | نواة مصابة، القالب غير محدد. |
AFFECTED_CORE_ONLY | نواة مصابة، الشرط المسبق للقالب غائب. يجب التصحيح رغم ذلك. |
VERSION_UNKNOWN | تم كشف WordPress، الإصدار مخفي. |
NOT_AFFECTED | الإصدار ≥ التصحيح لفرعه. |
| القاعدة | الخطورة | المُشغِّل |
|---|
GHSA-7hp8-traversal-pagename | CRITICAL | مكوّن .. في pagename، عند أي مستوى فك ترميز |
GHSA-7hp8-traversal-param | HIGH | نفس البدائية في معامل آخر (القوالب والإضافات تستدعي أيضًا locate_template()) |
GHSA-7hp8-traversal-path | HIGH | مكوّن .. في مسار الرابط (nginx يمرر %2f، Apache لا يفعل افتراضيًا) |
GHSA-7hp8-overlong-encoding | MEDIUM | ترميز UTF-8 مفرط (%c0%ae). غير فعّال على Linux، لكنه غير مشروع أبدًا |
GHSA-7hp8-theme-page-dir-probe | LOW | استطلاع دليل page-* للقالب — الاستطلاع |