O bug de checkout que era um skimmer de cartão

6 min de leitura devteam
skimmer de cartão

Passamos três semanas consertando um checkout que não funcionava. O Wordfence Premium dizia que o site estava limpo.


Uma loja online. Pagamentos falhando na primeira tentativa. No celular, ao escolher “cartão”, o campo do código de segurança aparecia cortado. A cliente perdia vendas todo dia e ninguém sabia dizer por quê.

Então fizemos o que todo mundo faz.

Trocamos o plugin de pagamento. Depois trocamos de novo. Rodamos uma varredura completa com Wordfence Premium — limpo, nada encontrado. Ajustamos o reCAPTCHA. Limpamos caches, testamos em vários navegadores, desativamos funcionalidades uma por uma e lemos os logs do gateway linha por linha.

Cada correção funcionava por um dia. Depois o problema voltava.

Três semanas. Nem a cliente nem nós tínhamos a menor ideia do que estava realmente acontecendo.

Site Doctor finalmente achou

Olhamos o DOM em um celular de verdade e vimos algo estranho: o formulário de pagamento do Stripe estava sendo montado duas vezes. Um iframe correto, e outro colapsado em 0×0 dentro do mesmo contêiner. A sincronização de altura estava conversando com o iframe errado — por isso o campo aparecia cortado.

A pergunta seguinte foi a que destravou tudo: o que estava duplicando o iframe?

Um snippet de código do próprio site. Um snippet legítimo, criado pela equipe semanas antes, ao qual alguém tinha acrescentado uma função:

$custom_recaptha_license_token = 'PHNjcmlwdD5jb25zdCBsb2FkanMg…';
if ( ! is_checkout() ) { return; }
echo base64_decode( $custom_recaptha_license_token );

Repare no detalhe: a variável se chama recaptha. Escrito errado de propósito, para que o olho leia “reCAPTCHA” e siga em frente. E o código só executa no checkout — que é exatamente por que todos os testes que fizemos em outras páginas voltavam limpos.

Ao decodificar o base64: um <script> que carregava um JavaScript externo de um domínio que não era nosso.

Um skimmer de cartão. Estava roubando daquela loja enquanto nós culpávamos o gateway, o cache e o navegador.

Site Doctor

O que havia embaixo

Puxamos esse fio. O que apareceu:

Um plugin backdoor plantado cinco meses antes, com nome de fantasia e assinado como se tivesse sido escrito por um desenvolvedor do core do WordPress. Ele se removia da lista de plugins do wp-admin, e se reativava sozinho se você o desativasse — em admin_init e em shutdown. Desativar não adiantava: era preciso apagar os arquivos.

A cada login, ele enviava o usuário e a senha em texto puro para um servidor remoto, cujo endereço estava criptografado em AES dentro do código. Isso rodou por cinco meses e meio, e é por isso que a rotação de credenciais não foi opcional.

O jQuery do core do WordPress com cerca de 6 KB de código ofuscado colado depois da biblioteca legítima. Carregava em todas as páginas.

Um backdoor de inclusão de arquivos escondido no uninstall.php de um plugin popular e sem relação nenhuma com o resto.

Três contas de administrador falsas, uma delas criada via API com Postman — não pelo painel — usando o backdoor como executor.

Remover qualquer um deles isoladamente teria deixado o site ainda comprometido.

O detalhe que fecha o círculo

Ao cortar o skimmer, a montagem dupla do iframe desapareceu.

O bug de renderização que perseguimos por três semanas era o malware. Não um sintoma paralelo, não uma coincidência: a mesma linha de código que roubava os cartões era a que quebrava o formulário.

Da varredura até o site limpo: cerca de uma hora.

Três coisas que eu levo disso

1. Um bug estranho e persistente pode ser sintoma, não causa. Se algo “não faz sentido” depois de você descartar o óbvio, considere que outra pessoa esteja executando código no seu site.

2. O plugin de segurança em verde não é prova de que você está limpo. O backdoor se escondia da própria listagem de plugins. Quem o entregou foi comparar os arquivos do core contra os checksums oficiais — wp core verify-checksums expôs o jQuery adulterado, e wp plugin verify-checksums encontrou o LFI. Nenhum dos dois é esperto. São só raramente executados.

3. A entrada não foi “o hackeamento”. Foi a conta de um usuário com permissões baixas. O backdoor fez o resto.

E uma coisa que não conseguimos determinar: o vetor de entrada original. Os logs da hospedagem daquele mês já estavam fora do período de retenção. Isso continua sendo um buraco aberto no nosso próprio relatório, não algo que possamos dizer que fechamos.

Quem encontrou e quem resolve

Vale separar, porque são duas ferramentas nossas e fazem coisas diferentes.

Quem encontrou foi o Site Doctor. Ele lê o site inteiro em modo somente leitura — arquivos, banco, opções, cron, o código dos plugins — e foi ali que apareceu o snippet, o plugin que se escondia da própria lista e os 6 KB colados no jQuery.

Quem bloqueia é o SysWP Shield. Depois que você sabe o que procurar, ele impede que volte.

O Wordfence Premium estava instalado, ativo e em dia. Rodou e deu limpo.

Antes de você clicar

O Site Doctor é um plugin somente leitura que você instala uma vez por site. Depois disso, você pergunta em português — pelo Claude ou pelo ChatGPT — e ele vai buscar a resposta dentro do site. Ele não consegue modificar nada: a operação de escrita não existe no código dele. Por isso dá para instalar no site de um cliente sem pedir autorização a ninguém.

Se você administra sites WordPress e já teve aquele momento de “o plugin diz que está limpo mas tem alguma coisa errada”, dá uma olhada nele.

Se preferir, mande um site. A gente olha e te diz por escrito o que encontrou em 24 horas — inclusive se não encontrar nada.

MCP Wordpress Segurança WordPress Site Doctor Threat Intelligence WordPress Firewall

Gostou? Coloque em prática.

Teste o SYSWP grátis por 5 dias e veja como nossa plataforma resolve isso na prática.

Começar grátis →
Verified by Auditto
Protected by SysWP Shield