Potential RCE with a compromised security key in craft/cms
Prioriza la corrección. Ella está bajo explotación confirmada por CISA.
Apply mitigations per vendor instructions or discontinue use of the product if mitigations are unavailable.
Resumen
Falha de code injection (CWE-94) no fluxo de restauração de backup de banco de dados do Craft CMS, que permite RCE completo no servidor — mas apenas se a security key da aplicação já estiver comprometida. O CVSS de 8.1 é alto, porém o pré-requisito (posse da security key) restringe bastante quem está realmente exposto: não é uma falha explorável remotamente por um atacante anônimo sem esse segredo.
Detalle técnico
O problema está em UpdaterController::actionRestoreDb(). O método chamava Craft::$app->getDb()->restore($this->data['dbBackupPath']) passando diretamente um caminho de arquivo vindo de dados controlados pelo cliente, sem validar se esse caminho existia ou se estava contido dentro do diretório oficial de backups (storage/backups). O comando de restore do Yii2/Craft monta e executa uma chamada de shell (mysql/pg_restore, dependendo do driver de banco) usando esse caminho como argumento — se o valor puder ser manipulado, o atacante injeta comando arbitrário ou faz o processo tratar um arquivo arbitrário do disco como se fosse um dump de banco, alcançando execução de código no servidor. É classificado pela CISA como CWE-94, code injection causado por validação inadequada do caminho de backup do banco.
O campo $this->data que alimenta o dbBackupPath não é um parâmetro de request comum e aberto: no fluxo do Updater, esses dados normalmente são protegidos/assinados usando a security key da aplicação (o segredo criptográfico configurado em config/general.php ou via variável de ambiente, usado por Craft::$app->getSecurity() para validar/decriptar payloads). Isso explica por que a falha só é explorável quando a security key já foi comprometida: sem ela, o atacante não consegue forjar um payload de dados válido que o controlador aceite processar com um dbBackupPath arbitrário.
A correção (commit e59e22b) adiciona duas verificações antes de chamar restore(): file_exists($backupPath) e FileHelper::isWithin($backupPath, Craft::$app->getPath()->getDbBackupPath()), lançando BadRequestHttpException se o caminho não existir ou estiver fora do diretório de backups esperado. Ou seja, o patch não elimina a necessidade de proteger a security key — ele fecha a porta de escape de diretório/injeção que a posse da key abria.
Cómo se explota
Pré-requisito indispensável e raramente destacado no título da CVE: o atacante precisa já possuir a security key da instalação Craft. Isso normalmente vem de exposição de .env, config/general.php, repositórios de código vazados, backups de arquivos acessíveis publicamente, ou outra falha anterior que leia arquivos de configuração. Sem a key, o endpoint do Updater não aceita um payload de dados forjado e a cadeia de exploração não se completa — por isso AV:N mas AC:H no vetor CVSS.
Com a key em mãos, o atacante forja o payload de dados que o UpdaterController espera (o campo que carrega dbBackupPath), definindo esse caminho para um arquivo sob seu controle ou para explorar a ausência de contenção de diretório, disparando a rotina de restauração de banco. Como o valor do caminho chega sem sanitização até o comando de restore executado via shell, isso resulta em execução de código arbitrário no servidor, com o mesmo nível de privilégio do processo PHP/Craft (potencialmente todo o container ou VM da aplicação).
A CVE está no catálogo KEV da CISA (adicionada em 2025-02-20, prazo de correção 2025-03-13), confirmando exploração ativa observada, embora a CISA não indique se há uso em campanhas de ransomware. A necessidade de posse prévia da security key sugere que a exploração em massa provavelmente ocorreu em conjunto com outras falhas ou exposições que vazaram esse segredo — não é um ataque de um único passo contra qualquer instalação Craft na internet.
Versiones
Cómo protegerse
Atualizar para Craft 5.5.8 (ramo 5) ou 4.13.8 (ramo 4), que adicionam validação de existência e contenção do caminho de backup dentro do diretório oficial antes de executar o restore. Essa é a correção real da causa raiz (a falta de validação do path) e deve ser aplicada independentemente de você acreditar que sua security key está segura.
Se a atualização não for possível agora, o fornecedor recomenda rotacionar a security key imediatamente e garantir que ela não fique exposta (fora de repositórios versionados, fora do webroot, lida por variável de ambiente). Isso remove o pré-requisito de exploração — mas é mitigação parcial: se a causa que expôs a key originalmente persistir (por exemplo, .env acessível via HTTP, painel de configuração exposto, backup de código-fonte público), uma nova key pode ser comprometida da mesma forma e o problema reaparece.
Não funciona como mitigação apenas restringir acesso ao painel administrativo do Craft sem tratar a exposição da security key nem aplicar o patch — a falha de validação do caminho de backup continua presente até a atualização, e a chave, uma vez vazada, compromete toda a proteção que dados assinados oferecem no restante da aplicação, não só neste endpoint.
Cómo detectar
Nos logs de erro do Craft/PHP, procure por exceções BadRequestHttpException com mensagem 'Invalid backup path' — isso indica que o patch está ativo e bloqueou uma tentativa de path fora do diretório de backups ou inexistente; sua ausência em versão não corrigida não significa ausência de tentativa, apenas que o comando de restore não logava esse tipo de rejeição antes do patch. Verifique também requisições HTTP dirigidas às rotas de ações do controller de Updater (fluxo de atualização/restore do Craft) fora do horário normal de manutenção/deploy.
Não há assinatura de payload pública conhecida, já que a exploração depende de um segredo específico da instalação (a security key) — não existe um indicador de comprometimento genérico aplicável entre diferentes instalações Craft. O sinal mais confiável de risco não é tráfego, e sim auditoria: verificar se a security key da instalação já foi exposta em algum momento (histórico de repositório, backups públicos, logs de erro com stack trace, arquivos .env acessíveis).