
Desserialização Insegura no install.php do e107 CMS
Relatado: 18 de setembro de 2025
CVE Atribuído: 9 de outubro de 2025
Publicado: 2 de fevereiro de 2026
ID CVE: CVE-2025-61505
Descobridor: Anas Abderrahman Benbarek
Uma vulnerabilidade de Injeção de Objeto PHP (CWE-502: Desserialização de Dados Não Confiáveis) foi descoberta no script de instalação (install.php) do e107 CMS versão 2.3.3.
A vulnerabilidade permite que atacantes remotos não autenticados criem dados serializados maliciosos, potencialmente levando à execução arbitrária de código, manipulação de dados ou outras ações maliciosas — dependendo da presença de classes gadget exploráveis na base de código do e107 ou em suas dependências.
O problema decorre do uso inseguro da função unserialize() do PHP em dados controlados pelo usuário, sem qualquer restrição (como a opção allowed_classes). Embora limitado à fase de instalação, representa um risco significativo durante a configuração em servidores expostos, pois o instalador lida com operações sensíveis, como criação de banco de dados e escrita de arquivos.
install.php)O processo de instalação do e107 CMS é multiestágio. As entradas do usuário (idioma, credenciais do banco de dados, detalhes do admin, etc.) são persistidas entre as etapas usando um array serializado armazenado no parâmetro POST previous_steps. Esses dados são codificados em base64 para transmissão e decodificados/desserializados no servidor.
O problema central é a passagem direta da entrada do usuário decodificada para unserialize() sem validação, saneamento ou lista de permissões de classes. Isso ocorre em dois lugares:
if(isset($_POST['previous_steps']))
{
$tmp = unserialize(base64_decode($_POST['previous_steps']));
$override = (isset($tmp['paths']) && isset($tmp['paths']['hash'])) ? array('site_path'=>$tmp['paths']['hash']) : array();
unset($tmp);
}
O script assume que previous_steps contém dados serializados confiáveis de etapas anteriores do formulário. Mas, como é um parâmetro POST simples, um atacante o controla completamente. base64_decode() transforma a entrada em binário, e unserialize() a reconstrói em objetos ou arrays PHP. Se a entrada contiver notação de objeto (começando com O:), o PHP instancia essas classes se elas existirem no escopo atual ou forem carregadas automaticamente. Isso pode acionar imediatamente __wakeup() ou outros métodos mágicos, potencialmente causando efeitos colaterais como escrita de arquivos ou chamadas inesperadas ao banco de dados, caso existam cadeias gadget.
Nota sobre explorabilidade: O sucesso depende das classes gadget disponíveis. Sem elas, o impacto pode se limitar a travamentos ou corrupção de dados.
if(isset($_POST['previous_steps']))
{
$this->previous_steps = unserialize(base64_decode($_POST['previous_steps']));
// ... (lógica de filtragem e restauração de senha)
unset($_POST['previous_steps']);
}
Esta instância é mais perigosa porque os dados desserializados se tornam parte do estado do objeto ($this->previous_steps) e influenciam ações posteriores do instalador (configuração do MySQL, criação de admin, geração de arquivos de configuração). A injeção de objeto aqui pode persistir durante todo o processo de instalação e afetar operações de alto privilégio. Novamente, nenhuma restrição allowed_classes significa que qualquer classe carregada automaticamente (núcleo, manipuladores, plugins, bibliotecas) pode ser instanciada.
Nota sobre explorabilidade: A exploração no mundo real geralmente requer o encadeamento de múltiplos objetos (uma "cadeia gadget") para alcançar comportamento perigoso, como execução de código. Por exemplo, o __wakeup() de uma classe pode chamar outro método que avalia strings controladas pelo usuário. Sem tais cadeias, o impacto pode ficar na negação de serviço (ex.: esgotamento de recursos em destrutores). O contexto de alto privilégio do instalador (escrita de e107_config.php, criação de diretórios) amplifica os riscos, mas a remoção do script após a instalação reduz a exposição a longo prazo.
A vulnerabilidade é acessível por meio de requisições HTTP POST não autenticadas para /install.php durante qualquer estágio da configuração.
install.php — Exclua ou renomeie o script imediatamente após a instalação..htaccess, nginx ou mova o arquivo para fora da raiz web durante a implantação.unserialize() por json_decode() para persistência de estado, ou no mínimo use:unserialize($data, ['allowed_classes' => false]);