
WordPress CVE-2026-87902 kit de ferramentas LFI-to-RCE com uma cadeia de exploração weaponizada (PEAR RCE, webshell, criação de admin, loot) e uma versão SafeChecker não intrusiva e auditor de risco.

USO EXCLUSIVAMENTE ÉTICO – TESTES DE SEGURANÇA AUTORIZADOS
Este repositório fornece ferramentas apenas para profissionais de segurança autorizados, blue teams e testadores de penetração.
O acesso não autorizado a sistemas informáticos é ilegal ao abrigo da CFAA (EUA), Computer Misuse Act (Reino Unido), TCK 243/244 (Turquia) e leis semelhantes em todo o mundo.
CVE‑2026‑87902 é uma vulnerabilidade crítica de path traversal e inclusão local de ficheiros (LFI) não autenticada no WordPress Core (versões 4.7.0 a 7.1.1) que permite a um atacante não autenticado incluir ficheiros .php locais arbitrários através do parâmetro de consulta pagename e, sob condições específicas do servidor, escalar para execução remota de código (RCE) encadeando o ficheiro PEAR pearcmd.php. Pontuação CVSS: 9.2 (Crítica). Divulgada por Robert Ressl através do programa HackerOne do WordPress em julho de 2026. Corrigida na 7.1.2 em 22 de setembro de 2026, com backports até à 4.7.
A falha afeta todas as versões do WordPress desde 2016 — uma década de versões que passaram pela revisão de código sem deteção. A causa raiz é uma única chamada de validação em falta num dos caminhos de código mais percorridos do CMS.
Resolução de template não sanitizada – get_page_template() em wp-includes/template.php constrói candidatos a template a partir da variável de consulta pagename. Um caminho de código vizinho na mesma função aplica validate_file() para bloquear sequências ../, mas o ramo $pagename não a chama. Qualquer traversal em pagename passa sem verificação.
Bypass de traversal com dupla codificação – O WordPress aplica sanitize_title_for_query() a pagename, que substitui pontos literais (.) por hífenes para prevenir traversal. Mas a função opera sobre input já descodificado e não descodifica recursivamente. Um atacante envia %252e%252e%252f; o servidor web descodifica-o uma vez para %2e%2e%2f; o sanitizador não vê pontos literais e deixa passar; depois get_page_template() chama urldecode() novamente dentro da função, produzindo ../.
Pré-condição do diretório do tema – O tema ativo deve conter um diretório de nível superior cujo nome comece por page- (por exemplo, page-templates/). O nome de ficheiro construído page-{pagename}.php escapa então a raiz do tema através do traversal. Temas padrão mais antigos (Twenty Twelve, Twenty Fourteen) e temas populares de terceiros (Neve, Hestia, Sydney) incluem este diretório. Temas filhos que herdam de tais temas pais também satisfazem a pré-condição.
Sink de LFI em locate_template() – O caminho candidato é passado para locate_template(), que procura nos diretórios do tema. Como o traversal resolve para um ficheiro fora desses diretórios, e a função verifica apenas file_exists(), qualquer ficheiro .php legível é incluído com privilégios totais do servidor web. Isto torna a LFI incondicional em qualquer site não corrigido que cumpra a pré-condição do tema — incluindo wp-config.php com as suas credenciais de base de dados e salts de autenticação.
Escalação para RCE via PEAR pearcmd.php – O PEAR é distribuído com muitas instalações de PHP. O seu pearcmd.php é normalmente apenas CLI, mas quando register_argc_argv=On, o PHP preenche $_SERVER['argv'] a partir da query string do URL. O atacante inclui pearcmd.php via LFI, passa config-create como argumento e fornece código PHP mais um caminho de saída (/tmp/shell.php). O PEAR escreve o código do atacante no disco; um segundo include executa-o.
Segunda rota de exploração – Um pedido que combine name (slug da página inicial), page_id (ID da página de posts), preview=true e um payload pagename desvia o WP_Query para o seu ramo post_name, que nunca reescreve pagename através de sanitize_title_for_query(). Isto permite pontos literais no traversal. Requer um tema sem single.php.
Requisitos de configuração do servidor – A RCE depende de duas condições comuns em implementações reais: pearcmd.php presente/legível (frequente em alojamento partilhado, cPanel, imagens Docker oficiais do PHP) e register_argc_argv=On (padrão em PHP abaixo de 8.5). O PHP 8.5 alterou o padrão para Off. Num servidor moderno PHP 8.5+ sem PEAR, a exploração para na LFI.
A correção – O WordPress 7.1.2 adiciona duas camadas de defesa: (a) a chamada validate_file() em falta no ramo pagename, e (b) uma nova função _wp_is_template_path_allowed() chamada por locate_template() para todos os templates resolvidos. A função rejeita caminhos que contenham .., depois resolve o caminho real via realpath() e verifica se este se encontra dentro de um dos diretórios de tema permitidos. Esta defesa em profundidade fecha o sink, não apenas uma rota para ele.
Exploração ativa em ambiente real – Primeiros pedidos maliciosos observados 5 horas após o lançamento da correção (17:44 UTC, 22 de setembro de 2026). O tráfego aumentou dez vezes no dia seguinte. Foram observadas três fases: reconhecimento config-show → deteção de ficheiros core → weaponização config-create. Os nomes de ficheiro dos payloads incluíam wp-pear-rce-flag.php, poc87902.php, luci_*.php, zeta_*.php, escritos em /tmp e /var/tmp. IPs atacantes: 169.58.48.193, 169.58.48.195, 2001:df1:e8c0::106b.
Impacto – Execução de código com privilégios do servidor web. Tomada de controlo total do site, roubo de credenciais de wp-config.php, exfiltração de dados, instalação de webshell, criação de utilizador administrador, reverse shell, ataques à cadeia de fornecimento através de plugins/temas modificados e movimento lateral para serviços conectados. A pontuação CVSS 9.2 reflete exploração pela rede, sem autenticação, com impacto elevado na confidencialidade/integridade/disponibilidade. A elevada complexidade de ataque reflete as pré-condições do tema e do servidor, mas em alojamento partilhado típico essas condições são frequentemente cumpridas.