Elderward

Scanner de malware e resposta a incidentes para WordPress. Instale o plugin, rode uma varredura pelo painel e descubra o que entrou no site e por onde, sem alterar nada.

$ cd wp-content/plugins
$ git clone https://github.com/fioa8c/elderward.git elderward
$ wp plugin activate elderward

Gratuito e GPL. Ainda não está no WordPress.org.

Uma varredura, direto do painel

Abra o Elderward no menu do painel e clique em Start scan. A varredura roda em segundo plano pelo WP-Cron, então você pode fechar a aba, e ela não altera nada no site.

wp-admin › Elderward
ElderwardMalware scanner and incident response for WordPress
ScanSignaturesHardeningRecoveryAI assistants

Scan this site

  • WordPress, plugin and theme files compared with the official copies
  • Known malware in your files
  • Suspicious entries in the database and admin accounts
  • Files with faked dates, and the server crontab
  • Access logs in /var/log/apache2
Start scan

Last scan: complete. Started 2 Nov 2026 14:02, finished 14:09.

Findings

Export as text Export as JSON
AllHIGHMEDIUMLOWINFOFalse positives
SeverityTypeWhereDetailsActions
HIGHUPLOADS_PHPwp-content/uploads/2024/03/cache.phpexecutable PHP inside wp-content/uploads - usually a webshell dropped through an upload formMark as false positive
Download sample
Look up on VirusTotal
HIGHDB_OPTION_IOCdb:wp_options:widget_textdb.option.hidden-iframe: Hidden iframe inside an option value - a classic drive-by injectionMark as false positive
MEDIUMDB_NEW_ADMINdb:wp_users:ID=7administrator "wp-sync" <wp-sync@example.com> registered 2024-03-12 03:16:40 - created within the last 30 days, the classic takeover artifact; verify who created itMark as false positive
LOWINTEGRITY_MISSINGwp-admin/css/about.min.csscore 6.6.2: file from the official package is missingMark as false positive
A página do Elderward no wp-admin: rode a varredura e leia os achados do mais grave ao mais leve. Por enquanto a interface do plugin está só em inglês.

O que uma varredura examina

Sete verificações num relatório só. Tudo o que impede uma verificação, como um arquivo ilegível ou uma extensão PHP ausente, aparece como erro em vez de ser pulado.

Verificações rápidasUPLOADS_PHP, PHP_PREPEND, MU_PLUGIN, HIDDEN_PHP
Os esconderijos baratos dos invasores: PHP executável em wp-content/uploads, ganchos auto_prepend_file em .user.ini, php.ini e .htaccess, mu-plugins que carregam sem precisar de ativação e arquivos PHP ocultos (começando com ponto).
IntegridadeINTEGRITY_MODIFIED, INTEGRITY_MISSING, INTEGRITY_EXTRA
O core, cada plugin e cada tema comparados com o pacote oficial do wordpress.org da versão instalada. PHP sobrando dentro do core ou de um plugin é o clássico webshell plantado. Plugins premium e temas filhos que não podem ser verificados aparecem como tal, então um relatório limpo nunca significa, em silêncio, "não verificado".
Banco de dadosDB_NEW_ADMIN, DB_ROLE_CAPS, DB_OPTION_IOC, DB_POST_IOC
Só leitura. Lista todos os administradores e destaca os recentes, aponta papéis que não são de admin mas ganharam poderes de tomada de controle, PHP, iframes ocultos ou JavaScript ofuscado em opções e posts, siteurl ou home sequestrados e active_plugins adulterado.
Logs de acessoLOG_IOC, LOG_FILE_CORRELATION
Opcional: informe um arquivo ou pasta de logs nas configurações, incluindo arquivos rotacionados e .gz. Acessos a webshells, tentativas de exploit em plugins vulneráveis conhecidos, sondagens de .env, injeção de código e enxurradas de força bruta, além dos arquivos modificados minutos depois desse tráfego.
Assinaturas de malwareMALWARE_FOUND, SIGNATURE_MATCH
Injeções conhecidas, como as campanhas JavaScript ndsw/ndsx e wqpq, mais as assinaturas que você escrever. Pelo painel isso roda em modo de simulação. A limpeza é feita pela linha de comando.
Datas de modificaçãoTIMESTAMP_OUTLIER, TIMESTAMP_TIMESTOMP
Arquivos alterados depois do resto do pacote, e PHP cuja data de modificação foi recuada com touch. São pistas, não provas.
CrontabCRONTAB_IOC
O crontab do usuário que roda o PHP, verificado em busca de decodificadores base64 encadeados por pipe, downloads do pastebin e droppers em diretórios tmp.

Além da varredura

O resto da página do Elderward, aba por aba.

Revisar achadosAba Scan
Marque um achado como falso positivo, com uma nota. Num arquivo, a marca só vale enquanto ele for byte a byte o mesmo que você revisou. Download sample empacota o arquivo suspeito num zip criptografado com a senha infected, e achados de arquivo têm um link para consultar o hash no VirusTotal. Exporte o relatório em texto ou NDJSON.
Varreduras agendadasAba Scan, Settings
Diárias, duas vezes por dia ou semanais, no fuso horário do site. Se o WP-Cron não for confiável no seu servidor, rode as varreduras só enquanto a página estiver aberta.
Assinaturas própriasAba Signatures
Texto exato ou expressões regulares para arquivos, valores de opções ou conteúdo de posts. Teste contra uma amostra colada ou um arquivo do site e depois compartilhe em JSON com outros sites e com a linha de comando. Assinaturas próprias só detectam.
Blindagem do servidorAba Hardening
Regras de servidor que bloqueiam PHP em uploads, cópias do wp-config.php, arquivos ocultos, backups e logs, arquivos internos do WordPress e listagem de pastas. Comece pelo modelo Recommended ou Strict, ou escolha cada proteção. No Apache e no LiteSpeed ele grava no .htaccess e desfaz tudo se o site parar de responder. No Nginx você baixa um arquivo para incluir na configuração. Check now testa o que o servidor de fato bloqueia.
Modo de recuperaçãoAba Recovery
Uma página protegida por chave que funciona quando o WordPress não carrega, depois de uma tela branca ou um erro crítico. Mostra os erros de PHP que derrubaram o site e o plugin ou tema responsável, e roda a varredura completa. Sem chave, responde 404.
Assistentes de IAAba AI assistants
No WordPress 6.9 ou mais novo, com o plugin MCP Adapter, Claude, ChatGPT, Antigravity ou Cursor podem rodar varreduras, explicar achados, ler arquivos suspeitos e escrever assinaturas com você. Eles não limpam nem alteram arquivos. Sem MCP? Copie um resumo para qualquer chat.

Proteções que ele nunca quebra

Ele roda em sites já comprometidos, então trata todo nome de arquivo, linha de log e resposta de API como hostil.

  • A varredura não altera nada

    As varreduras do painel só geram relatório. Os únicos arquivos que o painel grava são as regras de .htaccess que você aplicar e a chave de recuperação que você criar.

  • Nada sai do servidor

    Sem conta e sem telemetria. As únicas requisições externas vão para o wordpress.org, atrás de checksums e pacotes oficiais.

  • A verificação TLS fica ligada

    Um "tudo limpo" jamais pode vir de um invasor posicionado entre o site e o wordpress.org.

  • O banco de dados só é lido

    Apenas consultas SELECT, o wp-config.php é lido sem ser executado e os valores guardados nunca passam por unserialize, o que poderia disparar uma injeção de objeto PHP.

  • Verificação bloqueada não passa em silêncio

    Uma extensão ausente, um banco inacessível ou um log ilegível vira um achado ERROR, nunca é pulado em silêncio. Um relatório limpo significa que todos os scanners de fato olharam.

  • Falso positivo não esconde arquivo alterado

    A marca num arquivo guarda o SHA-256 dele. Se o arquivo mudar, o achado volta.

  • Assistentes olham, nunca mexem

    Nenhuma ferramenta de IA limpa, restaura ou grava arquivos. Tudo o que é escaneado vai marcado como dado não confiável, então um arquivo plantado não consegue dar ordens ao assistente.

  • Restaurações são verificadas antes

    Cada arquivo do zip oficial é conferido byte a byte com os checksums de referência antes de ser gravado. Um pacote adulterado é recusado, e arquivos sobrando nunca são apagados.

  • A blindagem se desfaz sozinha

    Depois de gravar as regras, o Elderward carrega a página inicial, o login e uma requisição do painel. Se algum deles quebrar, todos os arquivos voltam exatamente como estavam.

A limpeza acontece no terminal

Limpar e restaurar gravam arquivos, então rodam pelo WP-CLI, onde você faz backup e simula antes. Cada scanner também é um comando wp elderward, com saída pronta para pipe.

investigator@host: /var/www/html

      

Limpar e restaurar

$ wp elderward scan --dryrun
$ wp elderward scan
$ wp elderward integrity --restore --dryrun
$ wp elderward integrity --restore --quarantine-dir=/path/outside/webroot

Arquivos limpos são gravados num arquivo temporário e renomeados no lugar, então uma gravação que falha não trunca o original. --quarantine-dir guarda cada original como evidência.

Quando o WordPress não carrega

Abra o modo de recuperação, ou rode os mesmos scanners a partir da pasta do plugin com a CLI independente. Ela precisa de PHP 5.6 e de nenhum WordPress funcionando.

$ php bin/elderward.php scanall=1 scandirectory=/path/to/wp-root
$ php bin/elderward.php help=1

Texto

Uma linha por achado, no mesmo formato em todos os scanners. Caminhos e conteúdo de logs vêm do servidor comprometido, então caracteres de controle e vírgulas em caminhos são codificados com %. Um nome de arquivo malicioso não consegue forjar uma linha de achado.

SEVERITY,TYPE,path,detail

JSON

--format=json imprime um evento por linha no stdout e manda o progresso para o stderr. A exportação JSON do painel usa os mesmos eventos.

{"event":"finding","severity":"HIGH",
 "type":"LOG_IOC","path":"...","detail":"..."}

O que o código de saída diz

  1. 0

    Limpo, ou só achados informativos.

  2. 1

    Erro de uso ou fatal. Confira os argumentos.

  3. 2

    Achados LOW, MEDIUM ou ERROR para revisar.

  4. 3

    Achados HIGH. Uma limpeza bem-sucedida também sai com 3: havia malware.

Como instalar

O Elderward ainda não está no WordPress.org, então instale pelo GitHub.

Baixe o plugin

$ cd wp-content/plugins
$ git clone https://github.com/fioa8c/elderward.git elderward
$ wp plugin activate elderward

Ou baixe o repositório como zip e descompacte em wp-content/plugins/elderward/. A pasta precisa se chamar elderward.

Depois de ativar

  1. Abra o Elderward no menu do painel, ou no Network Admin em multisite, e clique em Start scan.
  2. Em Settings, informe onde ficam os logs de acesso e, se quiser, ative as varreduras automáticas.
  3. Aplique o modelo Recommended na aba Hardening.
  4. Crie uma chave de recuperação na aba Recovery, para o modo de recuperação estar pronto se o site quebrar.
  5. Faça backup e depois limpe com os comandos WP-CLI mostrados abaixo dos resultados.

Requisitos

  • WordPress 6.0 ou mais novo e PHP 7.2 ou mais novo. A CLI independente e o modo de recuperação rodam em PHP 5.6.
  • Acesso ao shell só para limpar ou restaurar arquivos. O painel não precisa disso.
  • WordPress 6.9 e o plugin MCP Adapter para os assistentes de IA.
  • Apache ou LiteSpeed com AllowOverride para as regras de blindagem que o Elderward grava. No Nginx, alguém com acesso ao servidor inclui o arquivo gerado.
  • Algumas verificações usam extensões PHP que servidores mais fechados não têm: zlib para logs .gz, zip para temas e qualquer restauração, shell_exec para o crontab. A falta de uma delas aparece como ERROR.

Faça backup antes de limpar. Simule antes com --dryrun.

Ele encontra malware conhecido. Uma varredura limpa não prova que o site está limpo, e os alertas de log incluem muitas tentativas que falharam.

Envie o que ele deixou passar

O Elderward só conhece malware que alguém já pegou. Se você limpar um site e achar algo que ele não apontou, abra uma issue no GitHub com uma amostra para que a próxima varredura pegue.

O que colocar na issue

  • A amostra. O Download sample do achado gera um zip criptografado com a senha infected, com um manifesto de onde e por que ele foi apontado. O GitHub não aceita um anexo .php solto.
  • O hash SHA-256 e o caminho onde você o encontrou.
  • Como ele era carregado: um include no functions.php, um mu-plugin, uma entrada no cron, auto_prepend_file ou outra coisa.
  • As versões do WordPress, dos plugins e do tema, se você tiver.
  • Para tráfego de ataque, as linhas correspondentes do log de acesso.
  • Se você escreveu uma assinatura que pega o arquivo, exporte pela aba Signatures e anexe o JSON.

Prepare pelo terminal

$ shasum -a 256 suspicious.php
$ zip -j -P infected sample.zip suspicious.php

Issues são públicas. Remova tudo o que identifique o site antes de enviar.

Isso inclui nomes de domínio, credenciais do banco, salts, endereços de e-mail e IPs de visitantes nas linhas de log. Nunca anexe o wp-config.php nem um dump do banco.