O scanner não lhe está a mentir, estão a mentir-lhe a ele
A 29 de julho de 2026, Joe Youngblood publicou um alerta a dizer que o hack japonês de palavras-chave está a passar por sites WordPress a grande velocidade e, nas palavras dele, “easily defeating WordFence, Securi, and Malcare along with other security methods / plugins.”
Esta última parte é a interessante, e não é uma falha desses produtos da forma que parece. A razão pela qual a análise volta limpa é que o payload não está lá quando o scanner o pede.
O conteúdo injetado é servido de forma condicional. O site guarda um web shell, e o shell decide no momento do pedido se injeta ou não. Se o pedido se parece com um browser, devolve a sua página normal. Se o pedido se parece com o Googlebot, devolve uma página cheia de palavras-chave de comércio eletrónico japonês a ligar para produtos contrafeitos. O seu plugin de segurança pede a página em nome próprio, recebe a versão normal e não reporta nada.
É por isto que o primeiro sintoma quase nunca aparece no site. Aparece na Search Console, ou num resultado do Google para a sua própria marca, ou numa queda de tráfego que ninguém consegue explicar.
Prove-o com um comando antes de mexer em seja o que for
Antes de começar a apagar ficheiros, perceba com o que está realmente a lidar. Peça o mesmo URL duas vezes a partir da linha de comandos:
curl -s https://exemplo.pt/uma-pagina/ > browser.html
curl -s -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
https://exemplo.pt/uma-pagina/ > crawler.html
diff browser.html crawler.html
Se os dois forem diferentes, e a versão do rastreador trouxer ligações ou palavras-chave que a versão do browser não tem, tem cloaking e o diagnóstico está feito. Sem análises de plugins, sem adivinhações.
Faça o mesmo com o seu sitemap. Um sintoma que costuma andar de mãos dadas com este é a Search Console reportar que o sitemap “parece ser uma página HTML” enquanto o sitemap carrega corretamente no seu browser. É o mesmo mecanismo: alguma coisa interceta a rota do sitemap e serve outra coisa ao rastreador.
Mais dois sítios para verificar, ambos fora do site:
- Search Console, Problemas de segurança. Se o Google já classificou o site, o relatório nomeia o padrão e guarda o pedido de revisão de que vai precisar mais tarde.
- Search Console, Desempenho, filtrado por consultas que não reconhece. Termos de comércio eletrónico japonês num site português ou alemão não são ambíguos.
O que cada ferramenta consegue e não consegue ver
Vale a pena ser preciso sobre porque é que os scanners voltam limpos, porque a conclusão “o plugin falhou” leva as pessoas a comprar outro plugin em vez de mudarem de método.
| Método | Vê um ficheiro do core modificado | Vê um shell em uploads | Vê conteúdo servido só a rastreadores | Vê uma semente plantada há meses |
|---|---|---|---|---|
| Análise de malware por plugin (baseada em assinaturas) | normalmente | frequentemente | não | só se o ficheiro corresponder a uma assinatura |
wp core verify-checksums | sim, de forma determinística | não, uploads não têm somas de verificação | não | sim, se o ficheiro estiver dentro do core |
| Grep por base64 e eval | sim, com falsos positivos | sim | não | sim, se o payload não estiver ofuscado |
| Teste de cloaking com dois pedidos | não | não | sim | sim, indiretamente, prova que o site continua a servir |
| Problemas de segurança na Search Console | não | não | sim, depois de o Google o ter classificado | não |
O padrão dessa tabela é o ponto todo. Todos os métodos que inspecionam ficheiros respondem a “existe alguma coisa no sistema de ficheiros”, e todos os métodos que inspecionam comportamento respondem a “este site está neste momento a mentir aos rastreadores”. Precisa dos dois, e só um deles é vendido como produto.
Apanhá-lo cedo, e apanhar uma recaída
O intervalo entre a infeção e a descoberta é onde acontece o dano de SEO. Há três sinais que chegam antes da queda de tráfego.
Impressões para consultas que não fazem sentido nenhum para o seu negócio. Search Console, Desempenho, ordenar por impressões, procurar qualquer coisa num alfabeto em que não publica. É normalmente o sinal mais precoce que tem à mão e custa um minuto por semana.
Uma página que dispara do nada. Na vaga atual, a primeira página injetada mostra muitas vezes um salto súbito de impressões antes das restantes seguirem. Uma página em que não toca há um ano a ter subitamente desempenho merece trinta segundos de curiosidade.
O favicon nos resultados a mudar. Youngblood nota que esta vaga traz um favicon distinto, visível na Search Console. Um favicon que não definiu é um ficheiro que não escreveu.
Depois de limpar, o mesmo teste de dois pedidos serve muito bem de monitor de recaída. Corre a partir de qualquer máquina com curl, e não a partir do próprio site, o que importa porque um site comprometido é mau juiz do seu próprio estado:
#!/usr/bin/env bash
# cloaking-watch.sh - alerta se a vista do rastreador divergir da vista do browser
URL="https://exemplo.pt/"
UA_BOT="Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
a=$(curl -s --max-time 20 "$URL" | md5sum | cut -d' ' -f1)
b=$(curl -s --max-time 20 -A "$UA_BOT" "$URL" | md5sum | cut -d' ' -f1)
if [ "$a" != "$b" ]; then
echo "DIVERGENCE on $URL at $(date -u +%FT%TZ)"
exit 1
fi
Duas ressalvas antes de pôr isto no cron. Páginas com conteúdo rotativo, testes A/B ou blocos personalizados vão diferir de forma legítima, por isso aponte-o para uma página estável, como um artigo perene ou o sitemap. E um shell bem feito consegue analisar mais do que o user agent, incluindo a gama de IP de origem, por isso um resultado limpo aqui é indício e não prova. Ainda assim apanha o caso comum, e apanha-o dentro de um dia em vez de um trimestre.
Distingui-lo das outras variantes de spam
Há três infeções a que se chama “spam de SEO” e cada uma pede um primeiro passo diferente, por isso vale a pena gastar um minuto a perceber qual delas tem.
O spam farmacêutico mete palavras-chave de medicamentos nos títulos, nos excertos e no conteúdo dos artigos. Vive na base de dados, é visível para qualquer visitante e encontra-se procurando em wp_posts e wp_options os termos que o Google está a mostrar. Se um SELECT encontra as palavras, o seu caso é este e não o japonês.
O spam de casinos e apostas fica a meio caminho entre os dois. Faz cloaking com frequência, tal como a variante japonesa, mas tende a chegar acompanhado de blocos hreflang injetados e de versões linguísticas inventadas das suas páginas, porque quem o opera quer vários mercados ao mesmo tempo. Se a vista do rastreador mostra ligações para idiomas alternativos que nunca criou, é por aí que deve procurar.
O hack japonês de palavras-chave deixa a base de dados em paz. O payload está em ficheiros, é apresentado no momento do pedido e só a rastreadores, e é essa combinação que derrota tanto a pesquisa na base de dados como a análise por plugin.
Existe ainda uma variante de redirecionamento só para telemóvel que liga e desliga conforme o user agent, tal como esta, exceto que verifica se o pedido vem de um telemóvel em vez de verificar se vem do Googlebot. Se os seus visitantes dizem que estão a ser enviados para outro site e os seus testes no computador continuam a dar limpo, repita o teste de dois pedidos com uma string de user agent de telemóvel em vez do Googlebot. O mecanismo é idêntico, só muda a condição.
Verifique ficheiros de forma determinística, depois olhe para as datas
O texto de Youngblood sugere procurar base64 no sistema de ficheiros e pedir a um modelo de IA que reveja a lista. Funciona, mas é o segundo passo e não o primeiro, porque pede a um modelo que adivinhe que ficheiros pertencem ao WordPress. O WordPress já sabe:
wp core verify-checksums
wp plugin verify-checksums --all
Isto compara cada ficheiro do core e dos plugins com as somas de verificação oficiais do WordPress.org e nomeia tudo o que foi modificado ou acrescentado. É determinístico, demora segundos e produz uma lista muito mais curta para analisar do que um grep de base64 por toda a árvore.
O que as somas de verificação não conseguem validar: o seu tema, tudo o que for premium, wp-content/uploads e mu-plugins. É aí que entra a passagem manual:
grep -rl --include="*.php" -E "base64_decode|eval\(|gzinflate|str_rot13" wp-content/ | head -50
find wp-content/uploads -name "*.php"
ls -la wp-content/mu-plugins/
Um ficheiro PHP dentro de uploads não tem qualquer razão legítima para existir. Nem tem um ficheiro em mu-plugins que não tenha sido escrito por si, e essa pasta merece atenção especial porque carrega automaticamente e nunca aparece na lista de plugins.
Depois ordene o que encontrou por data de modificação. A maioria dos ficheiros injetados partilha normalmente uma única data e hora, que é o momento do ataque visível. A exceção é aquilo a que Youngblood chama semente: um único ficheiro plantado semanas, meses ou por vezes anos antes, com uma data que não coincide com mais nada. Se limpar tudo menos a semente, a infeção volta, e volta em silêncio.
O teste prático para saber se o apanhou: reponha um index.php limpo, espere dois minutos e volte a ler o ficheiro. Se voltou ao estado anterior, alguma coisa continua a correr e a reescrevê-lo, e ainda não terminou.
A ordem que faz a diferença
A ordem da limpeza é onde as recuperações correm mal, e a sequência não é intuitiva.
Copie antes de limpar. Faça primeiro uma cópia completa dos ficheiros e uma exportação da base de dados no estado comprometido. Repor um backup por cima destrói a única prova de como se deu a entrada, e se o próprio backup já estiver infetado fica sem termo de comparação. Como o ficheiro semente pode anteceder o ataque visível em meses, trate “vamos repor a cópia do mês passado” como uma suposição e não como solução. Em Portugal, o padrão que aparece com mais frequência nestas limpezas é o cliente confiar num plugin de backup que escreve os seus próprios arquivos dentro de wp-content, ou seja, dentro da árvore infetada: cada arquivo aparentemente antigo já traz o shell lá dentro. Antes de repor o que quer que seja, confirme a janela de retenção real do seu alojamento (muitos planos geridos guardam trinta dias, os partilhados bastante menos) e compare-a com a data da semente. Se a semente é mais antiga do que a retenção, não existe backup limpo e a limpeza tem de ser feita ficheiro a ficheiro.
Limpe, depois rode credenciais, depois trate da pesquisa. Por esta ordem. Rodar credenciais antes de o shell desaparecer é entregar as novas.
Rode mais do que palavras-passe. É o passo em que quase todos os guias ficam pelo caminho:
- As palavras-passe de aplicação, no perfil de cada utilizador em Utilizadores, sobrevivem a uma mudança de palavra-passe e mantêm acesso total à REST API. São por utilizador, são fáceis de criar programaticamente assim que um atacante tem administrador, e a maioria das pessoas nem sabe que a funcionalidade existe. Liste-as e apague-as.
- Os proprietários delegados na Search Console, em Definições, Utilizadores e permissões, vivem completamente fora do seu site. Nada do que fizer no WordPress os remove. Verifique também a validação de propriedade, à procura de ficheiros HTML ou registos DNS TXT esquecidos.
- Credenciais de base de dados e de FTP ou SSH, porque se a entrada foi credential stuffing contra o
wp-admin, tudo o resto que partilhava essa palavra-passe está igualmente exposto.
Só depois a pesquisa. Regenere o sitemap, confirme com um teste de URL em direto na Inspeção de URL da Search Console que o Googlebot recebe agora a página verdadeira, e peça uma revisão no relatório de Problemas de segurança. Voltar a submeter um sitemap não levanta uma ação manual; o pedido de revisão sim.
Duas partes do conselho padrão que vale a pena contestar
O alerta que deu origem a este artigo é um bom relato de campo, e duas das suas recomendações merecem contestação.
“Peça imediatamente a remoção do site inteiro através da Search Console.” É um instrumento mais pesado do que a situação normalmente exige. A ferramenta de remoções esconde URLs dos resultados durante cerca de seis meses; não muda nada na infeção nem na forma como o Google acaba por reavaliar o site. Remover os padrões de URL injetados com uma remoção por prefixo é proporcional. Remover o site inteiro remove também as páginas que continuam a trazer pedidos de orçamento, e cada uma delas tem de voltar através de um cancelamento e de um novo rastreio que não controla. Guarde a versão total para quando as páginas injetadas forem genuinamente mais do que as reais, e não como primeiro passo.
“Arranje qualquer desculpa imaginável para lançar um comunicado de imprensa e atrair novo interesse do Googlebot.” O novo rastreio é impulsionado por coisas que consegue realmente influenciar: valores lastmod corretos no sitemap, ligações internas a partir de páginas rastreadas com frequência e pedidos de Inspeção de URL nas páginas que interessam. Um comunicado de imprensa é uma forma cara de comprar meia dúzia de visitas do rastreador.
O resto desse texto, em particular a observação sobre o ficheiro semente ter uma data única e o aviso para voltar a verificar o index.php depois de o repor, corresponde ao que estas limpezas são na prática.
Fechar a porta que o ataque usou mesmo
A cadeia de entrada reportada nesta vaga é específica: credential stuffing contra o wp-admin com listas de e-mails e palavras-passe divulgadas, depois a instalação de um plugin para obter acesso ao sistema de ficheiros, depois o carregamento de um único ficheiro de payload. Cada um desses passos tem um controlo que o trava.
Autenticação de dois fatores em todos os administradores. O credential stuffing funciona porque a palavra-passe já é conhecida. O segundo fator torna uma palavra-passe correta insuficiente, e é esse o ataque todo.
DISALLOW_FILE_MODS. No wp-config.php:
define( 'DISALLOW_FILE_MODS', true );
Isto bloqueia por completo a instalação de plugins e temas a partir do painel. Na cadeia reportada, é o passo dois. Um atacante com uma sessão de administrador válida não consegue instalar o plugin de gestão de ficheiros que lhe dá o sistema de ficheiros. A contrapartida é real e deve conhecê-la: as atualizações automáticas também param, por isso as atualizações passam a correr por WP-CLI ou por um pipeline de deployment. Num site que é publicado a partir de um repositório, é assim que deveria funcionar de qualquer forma.
Sem execução de PHP em uploads. Ao nível do servidor web, não num plugin. Isto desvaloriza o caminho mais comum, de “o atacante carregou um ficheiro” para “o atacante executa código”.
Menos administradores. Pessoal da agência, um programador que ajudou uma vez, um técnico de suporte de há dois anos. Cada um deles é uma credencial que pode ser testada em massa. Baixe o papel de quem não precisa dele.
Vigie a Search Console em vez do painel. O painel é precisamente onde este ataque é invisível por desenho. Uma olhadela semanal ao Desempenho, à procura de consultas que não reconhece, apanha-o mais cedo do que qualquer análise.
O que dizer ao cliente ou à chefia
Se está a limpar isto para outra pessoa, a parte difícil da conversa não é técnica, é sobre tempo. A limpeza mede-se em horas e a recuperação mede-se em semanas, e essas duas coisas colapsam facilmente numa única expectativa: resolve-se hoje à noite, o tráfego volta amanhã. Não volta, porque o Google tem de revisitar páginas que já tinha classificado como spam, e a fila depende da frequência com que rastreava o site antes disto.
A segunda coisa que vale a pena dizer com clareza: não consegue responder honestamente a “houve dados de clientes levados” quando os logs do servidor têm sete dias de retenção e o ficheiro semente é de fevereiro. A resposta é “não sabemos e não vamos vir a saber”, e isso é informação, não fuga à pergunta. Numa loja que guarda dados pessoais, essa lacuna pesa na decisão sobre se existe ou não obrigação de notificar uma violação de dados, por isso deve ficar em cima da mesa logo no início e não uma semana depois.
A terceira: o custo desta infeção raramente é a limpeza. É o tráfego que não chegou durante essas semanas, e esse número merece ser calculado em conjunto a partir dos dados anteriores à infeção, em vez de ficar como uma vaga sensação de que as coisas caíram.
Se está a meio de um caso destes agora
A versão curta: prove o cloaking com o teste de dois pedidos, verifique o core e os plugins com somas de verificação, cace a semente pela data de modificação, copie tudo antes de repor seja o que for, e lembre-se de que as palavras-passe de aplicação e os proprietários delegados na Search Console sobrevivem à mudança de palavras-passe que está prestes a fazer.
Corremos esta sequência como parte de uma auditoria de segurança WordPress, e o processo de limpeza mais alargado, incluindo o trabalho na base de dados e a revisão de logs, está no nosso guia para limpar um WordPress hackeado.
Última atualização: 30 de julho de 2026, depois de reportada a vaga atual.







