Saltar para o conteúdo
Falha crítica no WPvivid Backup expõe até 800 mil sites: upload arbitrário de ficheiros sem autenticação (CVE-2026-1357)
Beatriz Tavares
Beatriz Tavares 11 dEurope/Budapest February dEurope/Budapest 2026 · 7 min de leitura

Falha crítica no WPvivid Backup expõe até 800 mil sites: upload arbitrário de ficheiros sem autenticação (CVE-2026-1357)

Foi divulgado um problema de segurança grave no plugin WPvivid Backup & Migration (também identificado como Migration, Backup, Staging), com mais de 800.000 instalações ativas. A falha (classificada como Critical, CVSS 9.8) permite upload arbitrário de ficheiros sem autenticação e pode escalar para Remote Code Execution (RCE) – na prática, um caminho típico para tomada completa do site.

O ponto-chave (e que muda muito a avaliação de risco no terreno): segundo a análise publicada, o impacto crítico aplica-se sobretudo a sites que têm uma chave gerada nas definições do plugin para permitir que outro site envie um backup para esse site. Essa funcionalidade vem desativada por omissão, e a expiração da chave pode ser definida no máximo para 24 horas.

Imagem de destaque do alerta sobre a vulnerabilidade no plugin WPvivid Backup
. — Forrás: Wordfence

O que foi afetado (resumo rápido e prático)

  • CVE: CVE-2026-1357
  • Severidade: 9.8 (Critical)
  • Plugin: Migration, Backup, Staging – WPvivid Backup & Migration
  • Slug no WordPress.org: wpvivid-backuprestore
  • Versões vulneráveis: <= 0.9.123
  • Versão corrigida: 0.9.124
  • Tipo de falha: Unauthenticated Arbitrary File Upload (upload arbitrário de ficheiros sem login)
  • Possível impacto: Remote Code Execution (RCE) e comprometimento total do site, tipicamente via webshells

Porque é que isto pode dar RCE (e takeover do site)

Vulnerabilidades de arbitrary file upload são das mais perigosas em WordPress porque, se o atacante conseguir colocar um ficheiro executável pelo servidor (por exemplo, um .php) numa pasta acessível via web, basta depois chamar esse ficheiro por URL para executar código no servidor. Isso abre portas a webshells, criação de utilizadores admin, injeção de malware, pivoting para outros sites no mesmo servidor, etc.

Neste caso, o vetor está associado ao mecanismo do WPvivid para receber backups enviados por outro site, usando uma chave gerada temporariamente. O endpoint/ação explorada é referida como wpvivid_action=send_to_site.

Condição importante: quando é que o teu site fica realmente exposto?

A publicação ressalva repetidamente um detalhe operacional: a exploração crítica depende de o site ter uma chave gerada nas definições para permitir a receção de backups enviados de outro site. Como essa opção vem desligada por defeito, nem todos os sites com o plugin instalado estão automaticamente num estado “aberto” – mas qualquer site que tenha usado essa funcionalidade (mesmo que de forma pontual) merece atenção imediata.

Além disso, a chave tem validade curta (expiração configurável até um máximo de 24 horas). Ainda assim, uma janela de 24 horas pode ser suficiente para exploração, especialmente em cenários de ataque automatizado.

Análise técnica (o que correu mal no código)

A investigação aponta para uma combinação de problemas: tratamento incorreto de erro na desencriptação RSA e ausência de sanitização de caminho (path sanitization) ao escrever ficheiros no disco.

O fluxo descrito passa pela função send_to_site() na classe WPvivid_Send_to_site, que processa o conteúdo recebido ($_POST['wpvivid_content']) e tenta desencriptar a mensagem com base numa chave configurada no plugin (guardada em wpvivid_api_token). Se a opção não existir, ou se estiver expirada, o plugin termina (die()). Quando existe e está válida, o plugin cria um objeto WPvivid_crypt e chama decrypt_message().

public function send_to_site()
{
    include_once WPVIVID_PLUGIN_DIR . '/includes/class-wpvivid-crypt.php';

    // ... logging omitido ...

    if (isset($_POST['wpvivid_content'])) {
        $default = array();
        $option  = get_option('wpvivid_api_token', $default);

        if (empty($option)) {
            die();
        }

        if ($option['expires'] != 0 && $option['expires'] < time()) {
            die();
        }

        $crypt = new WPvivid_crypt(base64_decode($option['private_key']));
        $body  = base64_decode($_POST['wpvivid_content']);
        $data  = $crypt->decrypt_message($body);

        // ... segue para escrita do ficheiro ...
    }
}

O problema central aparece no decrypt_message(): o plugin usa RSA para desencriptar uma chave de sessão ($key). Quando a desencriptação falha (por exemplo, devido a valores inválidos), o resultado pode ser false. Segundo a análise, o plugin não interrompia a execução nesse cenário e acabava por inicializar a cifra AES/Rijndael com esse false.

Aqui entra um detalhe perigoso: a biblioteca (phpseclib) pode tratar false como uma string de bytes nulos (null bytes), resultando numa chave previsível. Com isso, um atacante consegue fabricar um payload encriptado com uma chave previsível (baseada em null bytes), contornando a expectativa de segredo da chave.

public function decrypt_message($message)
{
    $len = substr($message, 0, 3);
    $len = hexdec($len);

    $key = substr($message, 3, $len);

    $cipherlen = substr($message, ($len + 3), 16);
    $cipherlen = hexdec($cipherlen);

    $data = substr($message, ($len + 19), $cipherlen);

    $rsa = new Crypt_RSA();
    $rsa->loadKey($this->public_key);
    $key = $rsa->decrypt($key);

    $rij = new Crypt_Rijndael();
    $rij->setKey($key); // se $key for false, pode virar uma chave previsível

    return $rij->decrypt($data);
}

Em paralelo, a publicação destaca que o plugin aceitava nomes de ficheiro provenientes do payload desencriptado sem sanitização adequada, o que pode permitir directory traversal (por exemplo, usar ../ para escapar da diretoria “protegida” de backups). Resultado: o atacante consegue escrever ficheiros fora do local esperado – incluindo em diretorias acessíveis publicamente.

Somando (1) chave previsível quando a desencriptação RSA falha, (2) ausência de validação de tipo/extensão e (3) ausência de sanitização de caminhos, o cenário fica perfeito para subir um ficheiro PHP malicioso e executar código remotamente.

Como o patch resolveu (e o que mudou)

A correção publicada na versão 0.9.124 faz duas coisas essenciais:

  • No decrypt_message(), passou a existir validação explícita para abortar quando $key é false ou está vazia (evitando cair no caso da “chave de bytes nulos”).
  • No send_to_site(), foi adicionada validação de extensão para garantir que apenas tipos de ficheiro de backup são aceites.
public function decrypt_message($message)
{
    // ... parsing omitido ...

    $rsa = new Crypt_RSA();
    $rsa->loadKey($this->public_key);
    $key = $rsa->decrypt($key);

    if ($key === false || empty($key)) {
        return false;
    }

    $rij = new Crypt_Rijndael();
    $rij->setKey($key);

    return $rij->decrypt($data);
}
$safe_name = basename($params['name']);
$safe_name = preg_replace('/[^a-zA-Z0-9._-]/', '', $safe_name);

$allowed_extensions = array('zip', 'gz', 'tar', 'sql');
$file_ext = strtolower(pathinfo($safe_name, PATHINFO_EXTENSION));

if (!in_array($file_ext, $allowed_extensions, true)) {
    $ret['result'] = WPVIVID_FAILED;
    $ret['error']  = 'Invalid file type - only backup files allowed.';
    echo wp_json_encode($ret);
    die();
}

Mitigação: o que deves fazer agora

  1. Atualiza o WPvivid Backup para a versão 0.9.124 (ou superior, se já existir). Esta é a versão indicada como corrigida no momento da publicação do alerta.
  2. Revê as definições do plugin e confirma se a funcionalidade de receber backups de outro site está ativa e se existe uma chave gerada. Se não precisas, mantém desativado e evita gerar chaves desnecessariamente.
  3. Se usaste essa funcionalidade recentemente, assume que estiveste dentro de uma janela de exposição e faz uma verificação extra (ficheiros estranhos em wp-content/uploads/, diretórios de cache, e outros locais publicamente acessíveis).
  4. Garante que tens um WAF (Web Application Firewall). No caso específico do Wordfence, foi disponibilizada uma regra de firewall para bloquear tentativas de exploração associadas a esta falha (detalhes abaixo).

Proteção via Wordfence: datas de disponibilização

De acordo com o comunicado, a equipa do Wordfence disponibilizou uma regra de firewall para bloquear exploração desta vulnerabilidade em momentos diferentes consoante o plano:

  • Utilizadores Wordfence Premium, Wordfence Care e Wordfence Response receberam a regra a 22 de janeiro de 2026.
  • Utilizadores do Wordfence Free recebem a mesma proteção 30 dias depois, a 21 de fevereiro de 2026.

Cronologia de divulgação (disclosure timeline)

  • January 12, 2026 – Submissão da vulnerabilidade (Arbitrary File Upload) no WPvivid Backup via Wordfence Bug Bounty Program.
  • January 22, 2026 – Validação do reporte e confirmação do proof-of-concept; contacto inicial ao vendor com convite para usar o Wordfence Vulnerability Management Portal.
  • January 22, 2026 – Regra de firewall entregue a Wordfence Premium/Care/Response.
  • January 23, 2026 – Resposta do vendor e opção por conduzir a divulgação via email.
  • January 23, 2026 – Envio dos detalhes completos ao vendor; confirmação e início do trabalho na correção.
  • January 28, 2026 – Lançamento da versão corrigida do plugin: 0.9.124.
  • February 21, 2026 – Proteção equivalente chega ao Wordfence Free.

Nota sobre o reporte e Bug Bounty

A falha foi descoberta e reportada de forma responsável por Lucas Montes (NiRoX) através do Wordfence Bug Bounty Program. O relatório entrou no programa cinco dias após a vulnerabilidade ter sido introduzida (segundo o comunicado), e o investigador recebeu uma bounty de US$ 2.145,00.

O Wordfence também reforça que o seu Bug Bounty Program cobre plugins e temas WordPress sem custos para os vendors, com recompensas que podem chegar a US$ 31.200 por vulnerabilidade, dependendo do escopo e severidade.

Conclusão

Estamos perante uma vulnerabilidade crítica (CVE-2026-1357) no WPvivid Backup & Migration que pode permitir upload arbitrário de ficheiros sem autenticação e evoluir para execução remota de código. O risco é especialmente relevante quando o site está configurado para receber backups de outro site através de uma chave gerada (função desativada por omissão, com expiração até 24 horas).

A correção está disponível na versão 0.9.124 e deve ser aplicada o quanto antes, complementada por boas práticas de hardening e uma camada de firewall aplicacional quando possível.

Junte-se à comunidade HelloWP!

Converse conosco sobre WordPress, desenvolvimento web e compartilhe experiências com outros desenvolvedores.

- membros
- online
Participar

Usamos cookies para melhorar a sua experiência. Ao continuar, concorda com a nossa Política de Cookies.