{"id":222,"date":"2026-02-11T16:38:59","date_gmt":"2026-02-11T15:38:59","guid":{"rendered":"https:\/\/helloblog.io\/it\/cve-2026-1357-wpvivid-backup-upload-file-arbitrari-rce-chiave-send-to-site\/"},"modified":"2026-02-11T16:38:59","modified_gmt":"2026-02-11T15:38:59","slug":"cve-2026-1357-wpvivid-backup-upload-file-arbitrari-rce-chiave-send-to-site","status":"publish","type":"post","link":"https:\/\/helloblog.io\/it\/cve-2026-1357-wpvivid-backup-upload-file-arbitrari-rce-chiave-send-to-site\/","title":{"rendered":"CVE-2026-1357 in WPvivid Backup: upload di file arbitrari e rischio RCE (ma solo se usi la chiave \u201csend to site\u201d)"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Cosa sta succedendo: vulnerabilit\u00e0 critica in WPvivid Backup<\/h2>\n\n\n\n<p>Wordfence ha pubblicato un advisory su una vulnerabilit\u00e0 di tipo <strong>Unauthenticated Arbitrary File Upload<\/strong> nel plugin WordPress <strong>WPvivid Backup &#038; Migration<\/strong> (slug: <code>wpvivid-backuprestore<\/code>), che conta oltre <strong>800.000 installazioni attive<\/strong>. In pratica, in certe condizioni un attaccante <strong>non autenticato<\/strong> pu\u00f2 caricare file a piacere sul sito e ottenere <strong>Remote Code Execution (RCE)<\/strong>, cio\u00e8 eseguire codice sul server: lo scenario classico che porta a webshell e compromissione completa del sito.<\/p>\n\n\n\n<div class=\"wp-block-group callout callout-warning is-style-warning is-layout-flow wp-block-group-is-layout-flow\" style=\"border-width:1px;border-radius:8px;padding-top:1rem;padding-right:1.5rem;padding-bottom:1rem;padding-left:1.5rem\">\n\n<h4 class=\"wp-block-heading callout-title\">Dettaglio importante sull\u2019impatto reale<\/h4>\n\n\n<p>L\u2019advisory sottolinea che l\u2019impatto \u201ccritico\u201d riguarda in particolare chi ha <strong>generato una chiave<\/strong> nelle impostazioni del plugin per permettere a un altro sito di <strong>inviare un backup<\/strong> verso quel sito (funzionalit\u00e0 \u201creceive a backup from another site\u201d). Questa opzione \u00e8 <strong>disabilitata di default<\/strong> e la <strong>scadenza della chiave<\/strong> pu\u00f2 essere impostata al massimo a <strong>24 ore<\/strong>.<\/p>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Riepilogo vulnerability (Wordfence Intelligence)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Titolo: <strong>Migration, Backup, Staging <= 0.9.123 - Unauthenticated Arbitrary File Upload<\/strong><\/li>\n\n\n<li>CVE: <strong>CVE-2026-1357<\/strong><\/li>\n\n\n<li>Severit\u00e0: <strong>CVSS 9.8 (Critical)<\/strong><\/li>\n\n\n<li>Versioni impattate: <strong><= 0.9.123<\/strong><\/li>\n\n\n<li>Versione con fix: <strong>0.9.124<\/strong><\/li>\n\n\n<li>Parametro citato nell\u2019exploit chain: <strong><code>wpvivid_action=send_to_site<\/code><\/strong><\/li>\n\n\n<li>Ricercatore: <strong>Lucas Montes (NiRoX)<\/strong><\/li>\n\n\n<li>Bounty: <strong>$2,145.00<\/strong><\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Perch\u00e9 \u00e8 pericolosa: upload arbitrario + directory traversal + PHP eseguibile<\/h2>\n\n\n\n<p>Nelle versioni vulnerabili, la catena descritta da Wordfence combina pi\u00f9 fattori: gestione errata di un passaggio di decrittazione (RSA\/AES) e assenza di sanitizzazione del path del file scritto su disco. Il risultato \u00e8 che un attaccante pu\u00f2 arrivare a caricare un file (anche <strong>PHP<\/strong>) in una directory pubblicamente raggiungibile e poi richiamarlo via HTTP per ottenere RCE.<\/p>\n\n\n\n<p>Il punto d\u2019ingresso si trova nella funzione <code>send_to_site()<\/code> della classe <code>WPvivid_Send_to_site<\/code>, che gestisce la ricezione di un backup da un altro sito quando \u00e8 presente la chiave generata nelle impostazioni. Il flusso include <code>class-wpvivid-crypt.php<\/code>, inizializza logging e poi legge <code>$_POST['wpvivid_content']<\/code> (base64) per decrittare un payload e procedere con la gestione del file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Il cuore del problema: la chiave \u201cfalse\u201d che diventa prevedibile<\/h3>\n\n\n\n<p>Secondo l\u2019analisi tecnica, il plugin usa la chiave generata nelle impostazioni per decrittare via RSA un valore <code>$key<\/code>. Se la decrittazione fallisce, <code>$key<\/code> diventa <code>false<\/code>. Qui entra il bug: l\u2019esecuzione <strong>non viene interrotta<\/strong> e quel <code>false<\/code> viene passato all\u2019inizializzazione del cifrario AES\/Rijndael (tramite phpseclib). La libreria tratta quel <code>false<\/code> come una stringa di <strong>byte nulli<\/strong>, rendendo la \u201cchiave\u201d di cifratura di fatto <strong>prevedibile<\/strong>. Un attaccante pu\u00f2 quindi costruire dati cifrati usando questa chiave a byte nulli.<\/p>\n\n\n\n<p>A questo si somma un secondo aspetto: i nomi file contenuti nel payload decrittato vengono accettati <strong>senza sanitizzazione del percorso<\/strong>. Questo abilita <strong>directory traversal<\/strong>, cio\u00e8 la possibilit\u00e0 di \u201cuscire\u201d dalla directory protetta dei backup e finire a scrivere file altrove (ad esempio in percorsi web-accessible). Non essendoci (nelle versioni vulnerabili) controlli su estensione\/tipo file, diventa possibile caricare un file PHP malevolo e poi eseguirlo.<\/p>\n\n\n\n<div class=\"wp-block-group callout callout-danger is-style-danger is-layout-flow wp-block-group-is-layout-flow\" style=\"border-width:1px;border-radius:8px;padding-top:1rem;padding-right:1.5rem;padding-bottom:1rem;padding-left:1.5rem\">\n\n<h4 class=\"wp-block-heading callout-title\">Impatto tipico<\/h4>\n\n\n<p>Come in molte vulnerabilit\u00e0 di <strong>arbitrary file upload<\/strong>, l\u2019esito pratico pu\u00f2 essere la compromissione completa tramite webshell e tecniche correlate (persistenza, esfiltrazione, pivoting su account\/admin, ecc.).<\/p>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Dettagli tecnici: i punti chiave citati da Wordfence<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Funzione coinvolta nella ricezione: <code>send_to_site()<\/code> in <code>WPvivid_Send_to_site<\/code>.<\/li>\n\n\n<li>Contenuto ricevuto via POST: <code>wpvivid_content<\/code> (base64) che viene decrittato lato server.<\/li>\n\n\n<li>Decrittazione con RSA che pu\u00f2 fallire: quando <code>openssl_private_decrypt()<\/code> (menzionato nel riepilogo) non riesce, il valore pu\u00f2 diventare <code>false<\/code> e non viene gestito correttamente.<\/li>\n\n\n<li>Inizializzazione cifrario AES\/Rijndael (phpseclib) con chiave <code>false<\/code>: interpretata come sequenza di byte nulli (chiave prevedibile).<\/li>\n\n\n<li>Assenza di path sanitization per i nomi file nel payload: possibilit\u00e0 di directory traversal e scrittura fuori dalla directory backup.<\/li>\n\n\n<li>Possibilit\u00e0 di caricare file PHP in directory pubbliche e arrivare a RCE.<\/li>\n\n\n<li>Parametro menzionato per l\u2019azione: <code>wpvivid_action=send_to_site<\/code>.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">La patch in WPvivid 0.9.124: cosa \u00e8 stato corretto<\/h2>\n\n\n\n<p>Il team di WPvivid ha rilasciato una correzione nella versione <strong>0.9.124<\/strong>. Dall\u2019advisory emergono due interventi principali: (1) un controllo esplicito sul valore della chiave dopo la decrittazione RSA e (2) un controllo sulle estensioni dei file consentiti in upload nella logica di ricezione.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1) Check su <code>$key<\/code> in <code>decrypt_message()<\/code><\/h3>\n\n\n\n<p>Il fix aggiunge un controllo: se la chiave risultante \u00e8 <code>false<\/code> o vuota, la funzione termina restituendo <code>false<\/code> invece di proseguire e inizializzare il cifrario con una chiave prevedibile.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#e1e4e8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>public function decrypt_message($message)\n{\n    $len = substr($message, 0, 3);\n    $len = hexdec($len);\n    $key = substr($message, 3, $len);\n\n    $cipherlen = substr($message, ($len + 3), 16);\n    $cipherlen = hexdec($cipherlen);\n\n    $data = substr($message, ($len + 19), $cipherlen);\n    $rsa = new Crypt_RSA();\n    $rsa-&gt;loadKey($this-&gt;public_key);\n    $key = $rsa-&gt;decrypt($key);\n\n    \/\/ Patch: interrompe se la chiave non \u00e8 valida\n    if ($key === false || empty($key))\n    {\n        return false;\n    }\n\n    $rij = new Crypt_Rijndael();\n    $rij-&gt;setKey($key);\n    return $rij-&gt;decrypt($data);\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#F97583\">public<\/span><span style=\"color:#F97583\"> function<\/span><span style=\"color:#B392F0\"> decrypt_message<\/span><span style=\"color:#E1E4E8\">($message)<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $len <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, <\/span><span style=\"color:#79B8FF\">0<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#79B8FF\">3<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $len <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> hexdec<\/span><span style=\"color:#E1E4E8\">($len);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $key <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, <\/span><span style=\"color:#79B8FF\">3<\/span><span style=\"color:#E1E4E8\">, $len);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $cipherlen <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, ($len <\/span><span style=\"color:#F97583\">+<\/span><span style=\"color:#79B8FF\"> 3<\/span><span style=\"color:#E1E4E8\">), <\/span><span style=\"color:#79B8FF\">16<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $cipherlen <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> hexdec<\/span><span style=\"color:#E1E4E8\">($cipherlen);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $data <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> substr<\/span><span style=\"color:#E1E4E8\">($message, ($len <\/span><span style=\"color:#F97583\">+<\/span><span style=\"color:#79B8FF\"> 19<\/span><span style=\"color:#E1E4E8\">), $cipherlen);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $rsa <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#F97583\"> new<\/span><span style=\"color:#79B8FF\"> Crypt_RSA<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $rsa<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">loadKey<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#79B8FF\">$this<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#E1E4E8\">public_key);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $key <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#E1E4E8\"> $rsa<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">decrypt<\/span><span style=\"color:#E1E4E8\">($key);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">    \/\/ Patch: interrompe se la chiave non \u00e8 valida<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">    if<\/span><span style=\"color:#E1E4E8\"> ($key <\/span><span style=\"color:#F97583\">===<\/span><span style=\"color:#79B8FF\"> false<\/span><span style=\"color:#F97583\"> ||<\/span><span style=\"color:#79B8FF\"> empty<\/span><span style=\"color:#E1E4E8\">($key))<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">        return<\/span><span style=\"color:#79B8FF\"> false<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $rij <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#F97583\"> new<\/span><span style=\"color:#79B8FF\"> Crypt_Rijndael<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $rij<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">setKey<\/span><span style=\"color:#E1E4E8\">($key);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">    return<\/span><span style=\"color:#E1E4E8\"> $rij<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">decrypt<\/span><span style=\"color:#E1E4E8\">($data);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">2) Whitelist delle estensioni accettate in <code>send_to_site()<\/code><\/h3>\n\n\n\n<p>In aggiunta, la patch introduce un controllo sulle estensioni per assicurare che vengano caricati solo file di backup. Il codice mostrato da Wordfence usa <code>basename()<\/code> e una <code>preg_replace()<\/code> per ripulire il nome, poi verifica l\u2019estensione contro una lista consentita.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#e1e4e8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>$safe_name = basename($params['name']);\n$safe_name = preg_replace('\/[^a-zA-Z0-9._-]\/', '', $safe_name);\n\n$allowed_extensions = array('zip', 'gz', 'tar', 'sql');\n$file_ext = strtolower(pathinfo($safe_name, PATHINFO_EXTENSION));\n\nif (!in_array($file_ext, $allowed_extensions, true))\n{\n    $ret['result'] = WPVIVID_FAILED;\n    $ret['error'] = 'Invalid file type - only backup files allowed.';\n    echo wp_json_encode($ret);\n    die();\n}\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#E1E4E8\">$safe_name <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> basename<\/span><span style=\"color:#E1E4E8\">($params[<\/span><span style=\"color:#9ECBFF\">'name'<\/span><span style=\"color:#E1E4E8\">]);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$safe_name <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> preg_replace<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">'\/<\/span><span style=\"color:#DBEDFF\">[^a-zA-Z0-9._-]<\/span><span style=\"color:#9ECBFF\">\/'<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">''<\/span><span style=\"color:#E1E4E8\">, $safe_name);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$allowed_extensions <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> array<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">'zip'<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">'gz'<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">'tar'<\/span><span style=\"color:#E1E4E8\">, <\/span><span style=\"color:#9ECBFF\">'sql'<\/span><span style=\"color:#E1E4E8\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">$file_ext <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> strtolower<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#79B8FF\">pathinfo<\/span><span style=\"color:#E1E4E8\">($safe_name, <\/span><span style=\"color:#79B8FF\">PATHINFO_EXTENSION<\/span><span style=\"color:#E1E4E8\">));<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">if<\/span><span style=\"color:#E1E4E8\"> (<\/span><span style=\"color:#F97583\">!<\/span><span style=\"color:#79B8FF\">in_array<\/span><span style=\"color:#E1E4E8\">($file_ext, $allowed_extensions, <\/span><span style=\"color:#79B8FF\">true<\/span><span style=\"color:#E1E4E8\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $ret[<\/span><span style=\"color:#9ECBFF\">'result'<\/span><span style=\"color:#E1E4E8\">] <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> WPVIVID_FAILED<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    $ret[<\/span><span style=\"color:#9ECBFF\">'error'<\/span><span style=\"color:#E1E4E8\">] <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#9ECBFF\"> 'Invalid file type - only backup files allowed.'<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color:#79B8FF\">    echo<\/span><span style=\"color:#B392F0\"> wp_json_encode<\/span><span style=\"color:#E1E4E8\">($ret);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">    die<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Chi \u00e8 esposto davvero? La condizione della chiave generata<\/h2>\n\n\n\n<p>Il punto operativo da tenere a mente \u00e8 quello evidenziato anche da Wordfence: la vulnerabilit\u00e0 \u201ccolpisce in modo critico\u201d chi ha attivato la funzionalit\u00e0 di ricezione backup generando una chiave nelle impostazioni. \u00c8 una funzione <strong>off di default<\/strong>, e la chiave ha una scadenza configurabile fino a <strong>24 ore<\/strong>. Questo non annulla la gravit\u00e0 tecnica (CVSS 9.8), ma cambia molto la priorit\u00e0 di analisi del rischio per siti che non usano mai quel canale di trasferimento.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Mitigazione: cosa fare subito su siti WordPress in produzione<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li>Verifica la versione installata di WPvivid Backup: se sei su <strong>0.9.123 o precedente<\/strong>, pianifica l\u2019update immediato.<\/li>\n\n\n<li>Aggiorna a <strong>WPvivid Backup 0.9.124<\/strong> (versione indicata come patchata al momento della pubblicazione dell\u2019advisory).<\/li>\n\n\n<li>Controlla le impostazioni del plugin: se in passato hai generato una chiave per ricevere backup da un altro sito, considera di rigenerarla solo quando serve e rispettare la scadenza breve (massimo 24 ore, come indicato).<\/li>\n\n\n<li>Se usi Wordfence: sappi che la protezione via firewall \u00e8 stata distribuita a <strong>Wordfence Premium\/Care\/Response il 22 gennaio 2026<\/strong>; per <strong>Wordfence Free<\/strong> la stessa regola \u00e8 prevista <strong>30 giorni dopo, il 21 febbraio 2026<\/strong> (secondo la comunicazione).<\/li>\n\n\n<li>Dopo l\u2019update, esegui una verifica di integrit\u00e0: controlla directory tipicamente pubbliche (es. <code>wp-content\/uploads\/<\/code> e simili) alla ricerca di file inattesi, e rivedi i log di accesso se hai indicatori di compromissione.<\/li>\n\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Timeline di disclosure (secondo Wordfence)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>January 12, 2026<\/strong> &#8211; Invio della segnalazione della vulnerabilit\u00e0 tramite Wordfence Bug Bounty Program.<\/li>\n\n\n<li><strong>January 22, 2026<\/strong> &#8211; Validazione e conferma del proof-of-concept; primo contatto con il vendor e invito a usare il <a href=\"https:\/\/www.wordfence.com\/threat-intel\/vendor\/vulnerability-management-portal\/\">Wordfence Vulnerability Management Portal<\/a>.<\/li>\n\n\n<li><strong>January 22, 2026<\/strong> &#8211; Rilascio della regola firewall per utenti Wordfence Premium\/Care\/Response.<\/li>\n\n\n<li><strong>January 23, 2026<\/strong> &#8211; Risposta del vendor (preferenza per gestione via email).<\/li>\n\n\n<li><strong>January 23, 2026<\/strong> &#8211; Invio dei dettagli completi; ack e avvio lavoro sul fix.<\/li>\n\n\n<li><strong>January 28, 2026<\/strong> &#8211; Rilascio della versione patchata <strong>0.9.124<\/strong>.<\/li>\n\n\n<li><strong>February 21, 2026<\/strong> &#8211; Protezione equivalente prevista per Wordfence Free.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Nota sul Bug Bounty e sul ricercatore<\/h2>\n\n\n\n<p>La scoperta \u00e8 attribuita a <strong>Lucas Montes (NiRoX)<\/strong>, che ha riportato il problema responsabilmente tramite il <strong>Bug Bounty Program<\/strong> di Wordfence. Wordfence indica che la segnalazione \u00e8 arrivata <strong>cinque giorni dopo<\/strong> l\u2019introduzione della vulnerabilit\u00e0 e che il bounty riconosciuto per questo caso \u00e8 stato di <strong>$2,145.00<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusione<\/h2>\n\n\n\n<p>CVE-2026-1357 \u00e8 un caso da prendere sul serio: una combinazione di gestione errata degli errori in decrittazione e controlli insufficienti sul file in ingresso pu\u00f2 trasformarsi in <strong>upload arbitrario<\/strong> e <strong>RCE<\/strong> senza autenticazione. La buona notizia \u00e8 che esiste una versione corretta (<strong>0.9.124<\/strong>) e che l\u2019impatto pi\u00f9 critico si manifesta soprattutto quando \u00e8 attiva la funzione di ricezione backup tramite chiave temporanea. Se hai WPvivid in produzione, l\u2019azione pi\u00f9 sensata \u00e8 verificare versione e configurazione, aggiornare e controllare eventuali tracce di upload sospetti.<\/p>\n\n\n<div class=\"references-section\">\n                <h2>Riferimenti \/ Fonti<\/h2>\n                <ul class=\"references-list\"><li><a href=\"https:\/\/www.wordfence.com\/blog\/2026\/02\/800000-wordpress-sites-affected-by-arbitrary-file-upload-vulnerability-in-wpvivid-backup-wordpress-plugin\/\" target=\"_blank\" rel=\"noopener noreferrer\">800,000 WordPress Sites Affected by Arbitrary File Upload Vulnerability in WPvivid Backup WordPress Plugin<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/wordpress-plugins\/wpvivid-backuprestore\/migration-backup-staging-09123-unauthenticated-arbitrary-file-upload\" target=\"_blank\" rel=\"noopener noreferrer\">Migration, Backup, Staging &lt;= 0.9.123 &#8212; Unauthenticated Arbitrary File Upload<\/a><\/li><li><a href=\"https:\/\/www.cve.org\/CVERecord?id=CVE-2026-1357\" target=\"_blank\" rel=\"noopener noreferrer\">CVE-2026-1357<\/a><\/li><li><a href=\"https:\/\/wordpress.org\/plugins\/wpvivid-backuprestore\/\" target=\"_blank\" rel=\"noopener noreferrer\">WPvivid Backup &amp; Migration<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/bug-bounty-program\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Bug Bounty Program<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vendor\/vulnerability-management-portal\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Vulnerability Management Portal<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/submit\/\" target=\"_blank\" rel=\"noopener noreferrer\">Submit Vulnerability<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/threat-intel\/vulnerabilities\/researchers\/lucas-montes\" target=\"_blank\" rel=\"noopener noreferrer\">Lucas Montes (NiRoX)<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/products\/wordfence-premium\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Premium<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/products\/wordfence-care\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Care<\/a><\/li><li><a href=\"https:\/\/www.wordfence.com\/products\/wordfence-response\/\" target=\"_blank\" rel=\"noopener noreferrer\">Wordfence Response<\/a><\/li><\/ul>\n            <\/div>","protected":false},"excerpt":{"rendered":"<p>Una vulnerabilit\u00e0 critica in WPvivid Backup (fino alla 0.9.123) pu\u00f2 permettere a un attaccante non autenticato di caricare file arbitrari e arrivare alla Remote Code Execution. L\u2019impatto pi\u00f9 grave per\u00f2 riguarda un caso specifico: quando \u00e8 attiva la chiave temporanea per ricevere backup da un altro sito.<\/p>\n","protected":false},"author":20,"featured_media":221,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[111,12,11,15,10],"class_list":["post-222","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-sicurezza","tag-cve","tag-plugin","tag-sicurezza","tag-wordfence","tag-wordpress"],"_links":{"self":[{"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/posts\/222","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/comments?post=222"}],"version-history":[{"count":0,"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/posts\/222\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/media\/221"}],"wp:attachment":[{"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/media?parent=222"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/categories?post=222"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helloblog.io\/it\/wp-json\/wp\/v2\/tags?post=222"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}