{"id":237,"date":"2026-02-11T16:38:24","date_gmt":"2026-02-11T15:38:24","guid":{"rendered":"https:\/\/helloblog.io\/pt\/falha-critica-wpvivid-backup-upload-arbitrario-ficheiros-cve-2026-1357\/"},"modified":"2026-02-11T16:38:24","modified_gmt":"2026-02-11T15:38:24","slug":"falha-critica-wpvivid-backup-upload-arbitrario-ficheiros-cve-2026-1357","status":"publish","type":"post","link":"https:\/\/helloblog.io\/pt\/falha-critica-wpvivid-backup-upload-arbitrario-ficheiros-cve-2026-1357\/","title":{"rendered":"Falha cr\u00edtica no WPvivid Backup exp\u00f5e at\u00e9 800 mil sites: upload arbitr\u00e1rio de ficheiros sem autentica\u00e7\u00e3o (CVE-2026-1357)"},"content":{"rendered":"\n<p>Foi divulgado um problema de seguran\u00e7a grave no plugin <strong>WPvivid Backup &#038; Migration<\/strong> (tamb\u00e9m identificado como <em>Migration, Backup, Staging<\/em>), com mais de <strong>800.000 instala\u00e7\u00f5es ativas<\/strong>. A falha (classificada como <strong>Critical<\/strong>, <strong>CVSS 9.8<\/strong>) permite <strong>upload arbitr\u00e1rio de ficheiros sem autentica\u00e7\u00e3o<\/strong> e pode escalar para <strong>Remote Code Execution (RCE)<\/strong> &#8211; na pr\u00e1tica, um caminho t\u00edpico para tomada completa do site.<\/p>\n\n\n\n<p>O ponto-chave (e que muda muito a avalia\u00e7\u00e3o de risco no terreno): segundo a an\u00e1lise publicada, o impacto cr\u00edtico aplica-se sobretudo a sites que <strong>t\u00eam uma chave gerada nas defini\u00e7\u00f5es do plugin<\/strong> para permitir que <strong>outro site envie um backup para esse site<\/strong>. Essa funcionalidade vem <strong>desativada por omiss\u00e3o<\/strong>, e a expira\u00e7\u00e3o da chave pode ser definida no m\u00e1ximo para <strong>24 horas<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1504\" height=\"784\" src=\"https:\/\/helloblog.io\/app\/uploads\/sites\/9\/2026\/02\/FeaturedImage_Wordfence_303.01.png\" alt=\"Imagem de destaque do alerta sobre a vulnerabilidade no plugin WPvivid Backup\" class=\"wp-image-236\" srcset=\"https:\/\/helloblog.io\/app\/uploads\/sites\/9\/2026\/02\/FeaturedImage_Wordfence_303.01.png 1504w, https:\/\/helloblog.io\/app\/uploads\/sites\/9\/2026\/02\/FeaturedImage_Wordfence_303.01-300x156.png 300w, https:\/\/helloblog.io\/app\/uploads\/sites\/9\/2026\/02\/FeaturedImage_Wordfence_303.01-1024x534.png 1024w, https:\/\/helloblog.io\/app\/uploads\/sites\/9\/2026\/02\/FeaturedImage_Wordfence_303.01-768x400.png 768w, https:\/\/helloblog.io\/app\/uploads\/sites\/9\/2026\/02\/FeaturedImage_Wordfence_303.01-400x209.png 400w\" sizes=\"auto, (max-width: 1504px) 100vw, 1504px\" \/><figcaption class=\"wp-element-caption\">. \u2014 <em>Forr\u00e1s: Wordfence<\/em><\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">O que foi afetado (resumo r\u00e1pido e pr\u00e1tico)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>CVE:<\/strong> CVE-2026-1357<\/li>\n\n\n<li><strong>Severidade:<\/strong> 9.8 (Critical)<\/li>\n\n\n<li><strong>Plugin:<\/strong> Migration, Backup, Staging &#8211; WPvivid Backup &#038; Migration<\/li>\n\n\n<li><strong>Slug no WordPress.org:<\/strong> wpvivid-backuprestore<\/li>\n\n\n<li><strong>Vers\u00f5es vulner\u00e1veis:<\/strong> <= 0.9.123<\/li>\n\n\n<li><strong>Vers\u00e3o corrigida:<\/strong> 0.9.124<\/li>\n\n\n<li><strong>Tipo de falha:<\/strong> Unauthenticated Arbitrary File Upload (upload arbitr\u00e1rio de ficheiros sem login)<\/li>\n\n\n<li><strong>Poss\u00edvel impacto:<\/strong> Remote Code Execution (RCE) e comprometimento total do site, tipicamente via webshells<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Porque \u00e9 que isto pode dar RCE (e takeover do site)<\/h2>\n\n\n\n<p>Vulnerabilidades de <em>arbitrary file upload<\/em> s\u00e3o das mais perigosas em WordPress porque, se o atacante conseguir colocar um ficheiro <strong>execut\u00e1vel pelo servidor<\/strong> (por exemplo, um <code>.php<\/code>) numa pasta acess\u00edvel via web, basta depois chamar esse ficheiro por URL para executar c\u00f3digo no servidor. Isso abre portas a webshells, cria\u00e7\u00e3o de utilizadores admin, inje\u00e7\u00e3o de malware, pivoting para outros sites no mesmo servidor, etc.<\/p>\n\n\n\n<p>Neste caso, o vetor est\u00e1 associado ao mecanismo do WPvivid para <strong>receber backups enviados por outro site<\/strong>, usando uma <strong>chave gerada temporariamente<\/strong>. O endpoint\/a\u00e7\u00e3o explorada \u00e9 referida como <code>wpvivid_action=send_to_site<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Condi\u00e7\u00e3o importante: quando \u00e9 que o teu site fica realmente exposto?<\/h2>\n\n\n\n<p>A publica\u00e7\u00e3o ressalva repetidamente um detalhe operacional: a explora\u00e7\u00e3o cr\u00edtica depende de o site ter <strong>uma chave gerada nas defini\u00e7\u00f5es<\/strong> para permitir a rece\u00e7\u00e3o de backups enviados de outro site. Como essa op\u00e7\u00e3o vem <strong>desligada por defeito<\/strong>, nem todos os sites com o plugin instalado est\u00e3o automaticamente num estado \u201caberto\u201d &#8211; mas qualquer site que tenha usado essa funcionalidade (mesmo que de forma pontual) merece aten\u00e7\u00e3o imediata.<\/p>\n\n\n\n<p>Al\u00e9m disso, a chave tem <strong>validade curta<\/strong> (expira\u00e7\u00e3o configur\u00e1vel at\u00e9 um m\u00e1ximo de <strong>24 horas<\/strong>). Ainda assim, uma janela de 24 horas pode ser suficiente para explora\u00e7\u00e3o, especialmente em cen\u00e1rios de ataque automatizado.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">An\u00e1lise t\u00e9cnica (o que correu mal no c\u00f3digo)<\/h2>\n\n\n\n<p>A investiga\u00e7\u00e3o aponta para uma combina\u00e7\u00e3o de problemas: <strong>tratamento incorreto de erro na desencripta\u00e7\u00e3o RSA<\/strong> e <strong>aus\u00eancia de sanitiza\u00e7\u00e3o de caminho (path sanitization)<\/strong> ao escrever ficheiros no disco.<\/p>\n\n\n\n<p>O fluxo descrito passa pela fun\u00e7\u00e3o <code>send_to_site()<\/code> na classe <code>WPvivid_Send_to_site<\/code>, que processa o conte\u00fado recebido (<code>$_POST['wpvivid_content']<\/code>) e tenta desencriptar a mensagem com base numa chave configurada no plugin (guardada em <code>wpvivid_api_token<\/code>). Se a op\u00e7\u00e3o n\u00e3o existir, ou se estiver expirada, o plugin termina (<code>die()<\/code>). Quando existe e est\u00e1 v\u00e1lida, o plugin cria um objeto <code>WPvivid_crypt<\/code> e chama <code>decrypt_message()<\/code>.<\/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 send_to_site()\n{\n    include_once WPVIVID_PLUGIN_DIR . '\/includes\/class-wpvivid-crypt.php';\n\n    \/\/ ... logging omitido ...\n\n    if (isset($_POST['wpvivid_content'])) {\n        $default = array();\n        $option  = get_option('wpvivid_api_token', $default);\n\n        if (empty($option)) {\n            die();\n        }\n\n        if ($option['expires'] != 0 &amp;&amp; $option['expires'] &lt; time()) {\n            die();\n        }\n\n        $crypt = new WPvivid_crypt(base64_decode($option['private_key']));\n        $body  = base64_decode($_POST['wpvivid_content']);\n        $data  = $crypt-&gt;decrypt_message($body);\n\n        \/\/ ... segue para escrita do ficheiro ...\n    }\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\"> send_to_site<\/span><span style=\"color:#E1E4E8\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">    include_once<\/span><span style=\"color:#79B8FF\"> WPVIVID_PLUGIN_DIR<\/span><span style=\"color:#F97583\"> .<\/span><span style=\"color:#9ECBFF\"> '\/includes\/class-wpvivid-crypt.php'<\/span><span style=\"color:#E1E4E8\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">    \/\/ ... logging omitido ...<\/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:#79B8FF\">isset<\/span><span style=\"color:#E1E4E8\">($_POST[<\/span><span style=\"color:#9ECBFF\">'wpvivid_content'<\/span><span style=\"color:#E1E4E8\">])) {<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">        $default <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> array<\/span><span style=\"color:#E1E4E8\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">        $option  <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#B392F0\"> get_option<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#9ECBFF\">'wpvivid_api_token'<\/span><span style=\"color:#E1E4E8\">, $default);<\/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:#79B8FF\">empty<\/span><span style=\"color:#E1E4E8\">($option)) {<\/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>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#F97583\">        if<\/span><span style=\"color:#E1E4E8\"> ($option[<\/span><span style=\"color:#9ECBFF\">'expires'<\/span><span style=\"color:#E1E4E8\">] <\/span><span style=\"color:#F97583\">!=<\/span><span style=\"color:#79B8FF\"> 0<\/span><span style=\"color:#F97583\"> &#x26;&#x26;<\/span><span style=\"color:#E1E4E8\"> $option[<\/span><span style=\"color:#9ECBFF\">'expires'<\/span><span style=\"color:#E1E4E8\">] <\/span><span style=\"color:#F97583\">&#x3C;<\/span><span style=\"color:#79B8FF\"> time<\/span><span style=\"color:#E1E4E8\">()) {<\/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>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">        $crypt <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#F97583\"> new<\/span><span style=\"color:#79B8FF\"> WPvivid_crypt<\/span><span style=\"color:#E1E4E8\">(<\/span><span style=\"color:#79B8FF\">base64_decode<\/span><span style=\"color:#E1E4E8\">($option[<\/span><span style=\"color:#9ECBFF\">'private_key'<\/span><span style=\"color:#E1E4E8\">]));<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">        $body  <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#79B8FF\"> base64_decode<\/span><span style=\"color:#E1E4E8\">($_POST[<\/span><span style=\"color:#9ECBFF\">'wpvivid_content'<\/span><span style=\"color:#E1E4E8\">]);<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">        $data  <\/span><span style=\"color:#F97583\">=<\/span><span style=\"color:#E1E4E8\"> $crypt<\/span><span style=\"color:#F97583\">-><\/span><span style=\"color:#B392F0\">decrypt_message<\/span><span style=\"color:#E1E4E8\">($body);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color:#6A737D\">        \/\/ ... segue para escrita do ficheiro ...<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color:#E1E4E8\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>O problema central aparece no <code>decrypt_message()<\/code>: o plugin usa RSA para desencriptar uma chave de sess\u00e3o (<code>$key<\/code>). Quando a desencripta\u00e7\u00e3o falha (por exemplo, devido a valores inv\u00e1lidos), o resultado pode ser <code>false<\/code>. Segundo a an\u00e1lise, o plugin <strong>n\u00e3o interrompia a execu\u00e7\u00e3o<\/strong> nesse cen\u00e1rio e acabava por inicializar a cifra AES\/Rijndael com esse <code>false<\/code>.<\/p>\n\n\n\n<p>Aqui entra um detalhe perigoso: a biblioteca (phpseclib) pode tratar <code>false<\/code> como uma string de <strong>bytes nulos<\/strong> (null bytes), resultando numa chave previs\u00edvel. Com isso, um atacante consegue <strong>fabricar um payload encriptado<\/strong> com uma chave previs\u00edvel (baseada em null bytes), contornando a expectativa de segredo da chave.<\/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\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\n    $rsa = new Crypt_RSA();\n    $rsa-&gt;loadKey($this-&gt;public_key);\n    $key = $rsa-&gt;decrypt($key);\n\n    $rij = new Crypt_Rijndael();\n    $rij-&gt;setKey($key); \/\/ se $key for false, pode virar uma chave previs\u00edvel\n\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>\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>\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:#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 style=\"color:#6A737D\">\/\/ se $key for false, pode virar uma chave previs\u00edvel<\/span><\/span>\n<span class=\"line\"><\/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<p>Em paralelo, a publica\u00e7\u00e3o destaca que o plugin aceitava nomes de ficheiro provenientes do payload desencriptado <strong>sem sanitiza\u00e7\u00e3o adequada<\/strong>, o que pode permitir <strong>directory traversal<\/strong> (por exemplo, usar <code>..\/<\/code> para escapar da diretoria \u201cprotegida\u201d de backups). Resultado: o atacante consegue escrever ficheiros fora do local esperado &#8211; incluindo em diretorias acess\u00edveis publicamente.<\/p>\n\n\n\n<p>Somando (1) chave previs\u00edvel quando a desencripta\u00e7\u00e3o RSA falha, (2) aus\u00eancia de valida\u00e7\u00e3o de tipo\/extens\u00e3o e (3) aus\u00eancia de sanitiza\u00e7\u00e3o de caminhos, o cen\u00e1rio fica perfeito para <strong>subir um ficheiro PHP malicioso<\/strong> e executar c\u00f3digo remotamente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Como o patch resolveu (e o que mudou)<\/h2>\n\n\n\n<p>A corre\u00e7\u00e3o publicada na vers\u00e3o <strong>0.9.124<\/strong> faz duas coisas essenciais:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>No <code>decrypt_message()<\/code>, passou a existir valida\u00e7\u00e3o expl\u00edcita para abortar quando <code>$key<\/code> \u00e9 <code>false<\/code> ou est\u00e1 vazia (evitando cair no caso da \u201cchave de bytes nulos\u201d).<\/li>\n\n\n<li>No <code>send_to_site()<\/code>, foi adicionada valida\u00e7\u00e3o de extens\u00e3o para garantir que <strong>apenas tipos de ficheiro de backup<\/strong> s\u00e3o aceites.<\/li>\n\n<\/ul>\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    \/\/ ... parsing omitido ...\n\n    $rsa = new Crypt_RSA();\n    $rsa-&gt;loadKey($this-&gt;public_key);\n    $key = $rsa-&gt;decrypt($key);\n\n    if ($key === false || empty($key)) {\n        return false;\n    }\n\n    $rij = new Crypt_Rijndael();\n    $rij-&gt;setKey($key);\n\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:#6A737D\">    \/\/ ... parsing omitido ...<\/span><\/span>\n<span class=\"line\"><\/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:#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:#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>\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<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    $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\">    $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\">Mitiga\u00e7\u00e3o: o que deves fazer agora<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li><strong>Atualiza o WPvivid Backup para a vers\u00e3o 0.9.124<\/strong> (ou superior, se j\u00e1 existir). Esta \u00e9 a vers\u00e3o indicada como corrigida no momento da publica\u00e7\u00e3o do alerta.<\/li>\n\n\n<li>Rev\u00ea as defini\u00e7\u00f5es do plugin e confirma se a funcionalidade de <strong>receber backups de outro site<\/strong> est\u00e1 ativa e se existe uma <strong>chave gerada<\/strong>. Se n\u00e3o precisas, mant\u00e9m desativado e evita gerar chaves desnecessariamente.<\/li>\n\n\n<li>Se usaste essa funcionalidade recentemente, assume que estiveste dentro de uma janela de exposi\u00e7\u00e3o e faz uma verifica\u00e7\u00e3o extra (ficheiros estranhos em <code>wp-content\/uploads\/<\/code>, diret\u00f3rios de cache, e outros locais publicamente acess\u00edveis).<\/li>\n\n\n<li>Garante que tens um WAF (Web Application Firewall). No caso espec\u00edfico do Wordfence, foi disponibilizada uma regra de firewall para bloquear tentativas de explora\u00e7\u00e3o associadas a esta falha (detalhes abaixo).<\/li>\n\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Prote\u00e7\u00e3o via Wordfence: datas de disponibiliza\u00e7\u00e3o<\/h2>\n\n\n\n<p>De acordo com o comunicado, a equipa do Wordfence disponibilizou uma regra de firewall para bloquear explora\u00e7\u00e3o desta vulnerabilidade em momentos diferentes consoante o plano:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Utilizadores <strong>Wordfence Premium<\/strong>, <strong>Wordfence Care<\/strong> e <strong>Wordfence Response<\/strong> receberam a regra a <strong>22 de janeiro de 2026<\/strong>.<\/li>\n\n\n<li>Utilizadores do <strong>Wordfence Free<\/strong> recebem a mesma prote\u00e7\u00e3o <strong>30 dias depois<\/strong>, a <strong>21 de fevereiro de 2026<\/strong>.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Cronologia de divulga\u00e7\u00e3o (disclosure timeline)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>January 12, 2026<\/strong> &#8211; Submiss\u00e3o da vulnerabilidade (Arbitrary File Upload) no WPvivid Backup via Wordfence Bug Bounty Program.<\/li>\n\n\n<li><strong>January 22, 2026<\/strong> &#8211; Valida\u00e7\u00e3o do reporte e confirma\u00e7\u00e3o do proof-of-concept; contacto inicial ao vendor com convite para usar o <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; Regra de firewall entregue a Wordfence Premium\/Care\/Response.<\/li>\n\n\n<li><strong>January 23, 2026<\/strong> &#8211; Resposta do vendor e op\u00e7\u00e3o por conduzir a divulga\u00e7\u00e3o via email.<\/li>\n\n\n<li><strong>January 23, 2026<\/strong> &#8211; Envio dos detalhes completos ao vendor; confirma\u00e7\u00e3o e in\u00edcio do trabalho na corre\u00e7\u00e3o.<\/li>\n\n\n<li><strong>January 28, 2026<\/strong> &#8211; Lan\u00e7amento da vers\u00e3o corrigida do plugin: <strong>0.9.124<\/strong>.<\/li>\n\n\n<li><strong>February 21, 2026<\/strong> &#8211; Prote\u00e7\u00e3o equivalente chega ao Wordfence Free.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Nota sobre o reporte e Bug Bounty<\/h2>\n\n\n\n<p>A falha foi descoberta e reportada de forma respons\u00e1vel por <strong>Lucas Montes (NiRoX)<\/strong> atrav\u00e9s do <strong>Wordfence Bug Bounty Program<\/strong>. O relat\u00f3rio entrou no programa <strong>cinco dias<\/strong> ap\u00f3s a vulnerabilidade ter sido introduzida (segundo o comunicado), e o investigador recebeu uma bounty de <strong>US$ 2.145,00<\/strong>.<\/p>\n\n\n\n<p>O Wordfence tamb\u00e9m refor\u00e7a que o seu Bug Bounty Program cobre plugins e temas WordPress sem custos para os vendors, com recompensas que podem chegar a <strong>US$ 31.200 por vulnerabilidade<\/strong>, dependendo do escopo e severidade.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclus\u00e3o<\/h2>\n\n\n\n<p>Estamos perante uma vulnerabilidade <strong>cr\u00edtica<\/strong> (CVE-2026-1357) no <strong>WPvivid Backup &#038; Migration<\/strong> que pode permitir <strong>upload arbitr\u00e1rio de ficheiros sem autentica\u00e7\u00e3o<\/strong> e evoluir para <strong>execu\u00e7\u00e3o remota de c\u00f3digo<\/strong>. O risco \u00e9 especialmente relevante quando o site est\u00e1 configurado para <strong>receber backups de outro site<\/strong> atrav\u00e9s de uma <strong>chave gerada<\/strong> (fun\u00e7\u00e3o desativada por omiss\u00e3o, com expira\u00e7\u00e3o at\u00e9 24 horas).<\/p>\n\n\n\n<p>A corre\u00e7\u00e3o est\u00e1 dispon\u00edvel na vers\u00e3o <strong>0.9.124<\/strong> e deve ser aplicada o quanto antes, complementada por boas pr\u00e1ticas de hardening e uma camada de firewall aplicacional quando poss\u00edvel.<\/p>\n\n\n<div class=\"references-section\">\n                <h2>Refer\u00eancias \/ Fontes<\/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\">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\/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>Uma vulnerabilidade cr\u00edtica no WPvivid Backup permite a atacantes n\u00e3o autenticados fazer upload de ficheiros (incluindo PHP) e chegar a execu\u00e7\u00e3o remota de c\u00f3digo &#8211; mas h\u00e1 uma condi\u00e7\u00e3o importante: a funcionalidade s\u00f3 fica realmente exposta quando existe uma chave gerada nas defini\u00e7\u00f5es.<\/p>\n","protected":false},"author":29,"featured_media":235,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[12,11,13,15,10],"class_list":["post-237","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-seguranca","tag-plugins","tag-seguranca","tag-vulnerabilidade","tag-wordfence","tag-wordpress"],"_links":{"self":[{"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/posts\/237","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/comments?post=237"}],"version-history":[{"count":0,"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/posts\/237\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/media\/235"}],"wp:attachment":[{"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/media?parent=237"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/categories?post=237"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helloblog.io\/pt\/wp-json\/wp\/v2\/tags?post=237"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}