Ataques a lojas PrestaShop: skimmers, pagamentos desviados e backdoors que já vimos
Formulários de cartão falsos no pagamento, cobranças que vão parar à conta de outra pessoa, backdoors escondidas em módulos que ninguém usa. Sem dizer de quem, contamos o que encontrámos ao limpar lojas PrestaShop, como tratamos um incidente e porque é a loja desatualizada que acaba nesta lista.
Uma loja online não é atacada como nos filmes. Não há ecrãs vermelhos nem caveiras na página inicial. O normal é precisamente o contrário: a loja funciona perfeitamente, as encomendas entram, os clientes pagam e o dono não nota nada. Entretanto, alguém está a copiar os cartões no passo de pagamento, a receber numa conta que não é a sua ou a guardar uma backdoor para voltar quando quiser.
Na Rekire limpamos lojas PrestaShop comprometidas com mais frequência do que gostaríamos. Este artigo reúne o que vimos nesses trabalhos. Os casos são reais, mas contamo-los de forma a ser impossível saber de que loja se trata: sem setor, sem cidade, sem datas, sem números e sem detalhes que permitam encontrá-la. O que importa não é quem, mas como, porque o como repete-se.
É um artigo longo de propósito. Se tem uma loja numa versão antiga do PrestaShop, pedimos-lhe que o leia até ao fim.
O que é um skimmer e porque é o ataque preferido contra uma loja
Um skimmer (também chamado clonador de cartões ou ataque do tipo Magecart) é um pedaço de JavaScript que se infiltra na sua loja e rouba os dados do cartão no momento em que o cliente os escreve. Número, validade, CVV e nome do titular seguem para um servidor do atacante, e a encomenda continua o seu curso normal.
É o ataque mais rentável que existe contra uma loja online, por três motivos:
- Não estraga nada. O cliente compra, você recebe, ninguém se queixa. Os dados roubados são usados semanas depois, noutro sítio, e quando o banco do cliente deteta a fraude ninguém relaciona o cartão com a sua loja.
- Não precisa de que o seu gateway de pagamento seja vulnerável. Tanto faz que use o TPA virtual do seu banco, a Stripe ou o PayPal. O skimmer não ataca o gateway: ataca a página onde o cliente está.
- Escala. Uma loja com tráfego normal entrega dezenas de cartões por semana sem que o atacante tenha de fazer mais nada.
Caso 1: o formulário de cartão que não existia
O primeiro sinal foi um aviso automático do nosso módulo de segurança: um template do passo de pagamento do tema tinha mudado sem que ninguém tivesse mexido no tema.
Ao puxar o fio, apareceu a sequência completa, reconstruída com os registos do servidor:
- Alguém entrou no painel do alojamento com o utilizador e a palavra-passe corretos. Não foi uma falha do PrestaShop: a palavra-passe tinha sido divulgada.
- A partir do gestor de ficheiros do painel, escreveu cerca de 60 KB de JavaScript num ficheiro do próprio tema que até então estava vazio. Um ficheiro com um nome aborrecido, daqueles que ninguém abre.
- Acrescentou uma única linha no fim do template do passo de pagamento: um
<script src>que carregava esse ficheiro. A partir do mesmo domínio da loja, pelo que nenhum filtro de «domínios externos» o teria assinalado. - Carregou um pequeno PHP para limpar a cache de templates, executou-o e foi-se embora. Tudo em menos de vinte minutos.
O JavaScript não fazia nada enquanto o cliente navegava. Só se ativava quando o cliente escolhia a opção de pagamento com cartão. Nesse momento mostrava um formulário de cartão idêntico ao da loja e, ao ser preenchido, enviava os dados codificados com navigator.sendBeacon para outra loja online, também atacada, que servia de caixa de correio. Usar o site de outra vítima como destino é habitual: um domínio comercial normal não levanta suspeitas.
Esteve ativo durante cerca de uma semana. O trabalho posterior foi tão importante como a limpeza: tirar a lista de encomendas e pagamentos desses dias para avisar a entidade de pagamento e avaliar com o responsável da loja a notificação à AEPD (a autoridade espanhola de proteção de dados), que o RGPD (artigo 33.º) exige num prazo máximo de 72 horas a partir do momento em que se tem conhecimento da violação.
O que apareceu por baixo
Ao rever os funcionários do back-office encontrámos algo pior: mais de vinte superadministradores falsos, todos com o mesmo e-mail e o nome «Prestashop Addons», criados em rajadas de um segundo meses antes. Essa forma de os criar — muitos de uma vez, com o mesmo e-mail — é a assinatura de uma injeção de SQL, não de alguém que entra pelo formulário de início de sessão. A origem mais provável era um controlador de um construtor de páginas de um tema comercial que respondia a qualquer pessoa, sem verificar a sessão, e metia um parâmetro sem filtrar dentro de uma consulta.
Nenhuma auditoria anterior os tinha detetado. A loja estava de porta aberta há meses, e o skimmer foi apenas o que acabou por se notar.
Caso 2: os pagamentos que iam para outra conta
Este é o caso que melhor explica porque dizemos que um ataque não se vê. A loja vendia com normalidade. As encomendas com cartão apareciam no back-office como pagas, com o número da operação, o estado correto e a fatura. Tudo batia certo… exceto que esse dinheiro nunca chegou ao banco da loja.
O atacante tinha substituído o ficheiro principal do módulo de pagamento do banco por uma cópia modificada. A modificação fazia o seguinte:
- Trocava o pagamento com cartão por um formulário de um gateway internacional ligado a uma conta do atacante. Deixava o Bizum intacto e escondia outro método, para que o cliente fosse diretamente para o cartão.
- Escrevia nas tabelas do módulo do banco um registo falso, de forma que a encomenda parecia um pagamento normal no back-office.
- Não se ativava para os funcionários da loja nem para e-mails que pareciam de testes ou da agência que fazia a manutenção. Quem testava a loja via o pagamento de sempre.
- Avisava o atacante de cada cobrança pelo Telegram.
- Guardava as suas chaves fora da pasta web, no diretório pessoal da conta de alojamento.
- E podia autodestruir-se, restaurando os ficheiros originais que tinha guardado ao lado.
A entrada foi por FTP, com a conta principal do alojamento, que tinha a mesma palavra-passe do painel. Os registos de FTP mostravam dezenas de sessões a partir do mesmo endereço durante semanas, a carregar e retocar ficheiros como se fosse mais um programador.
E como foi descoberto? Por um erro do próprio atacante, e é aqui que está a parte que nos interessa. A loja tinha acabado de migrar para o PrestaShop 9. O código malicioso estava escrito para a versão antiga e, ao reinjetá-lo, o atacante carregou os ficheiros do módulo de pagamento da loja antiga. No PrestaShop 9 esses ficheiros já não funcionavam: a loja ficou em branco. Sem essa falha, o desvio teria continuado. Ao cruzar as encomendas com o rasto deixado pelo código falso, apareceram dezenas de cobranças desviadas ao longo de vários meses.
Caso 3: backdoors onde ninguém olha
Um skimmer ou um desvio exigem que o atacante consiga escrever na sua loja. Para voltar quando quiser, deixa uma web shell: um ficheiro PHP que, chamado pelo seu URL, lhe permite executar comandos ou escrever ficheiros no seu servidor. Estas são algumas das que encontrámos, e repare onde estavam:
- Uma linha de 30 bytes (um
evaldo que chegar no pedido) dentro da pasta de um módulo que não estava instalado. A pasta estava no disco há anos, ninguém a revia e o PrestaShop 1.7 executa qualquer.phpdemodules/se alguém o pedir por URL. - Um ficheiro com menos de 200 bytes, com um nome que começava por um ponto, na raiz da loja. Só fazia uma coisa: escrever no servidor qualquer ficheiro que recebesse. Nenhum scanner automático o viu; apareceu ao comparar a loja, ficheiro a ficheiro, com uma cópia anterior.
- Uma shell completa de mais de 80 KB (gestor de ficheiros, execução de comandos, carregamento de ficheiros) dentro da pasta de um módulo nativo do PrestaShop, com o cabeçalho de licença do PrestaShop, autor «PrestaShop» e funções com nomes inocentes. Uma cópia exata estava noutro módulo abandonado, para o caso de apagarem a primeira.
- Um gestor de ficheiros disfarçado de leitor de códigos QR, escrito em PHP limpo e legível, dentro de um plugin de um WordPress que partilhava o alojamento com a loja. A partir daí, o JavaScript do tema do PrestaShop foi reescrito sem tocar no PrestaShop em momento algum.
- Uma linha na pasta
vendor/de um módulo que incluía um ficheiro com extensão.jpeg… que era PHP. A loja tinha passado por duas limpezas com essa porta aberta, porque a ferramenta usada excluíavendor/por predefinição. - Um carregador de 6 KB dentro de um módulo de transporte, de resto legítimo, que abria um WebSocket e executava o que lhe mandassem. No disco não havia mais nada: o código malicioso chegava em cada visita e servia para levar o URL do back-office, com o seu token, para um domínio externo.
As sabotagens de um só carácter
O caso que mais nos ensinou foi o de uma loja onde, além das backdoors, o atacante tinha alterado dois ficheiros do núcleo do PrestaShop. Num deles, uma expressão regular que limpa etiquetas HTML foi relaxada para deixar de limpar. No outro, retirou o fecho do índice de classes que o PrestaShop gera, de forma que qualquer coisa acrescentada no fim era executada como código: reinfeção automática sem precisar de nenhum ficheiro próprio.
Nenhuma regra de pesquisa de padrões teria visto isto. Quem o encontrou foi a comparação byte a byte com o ZIP oficial do PrestaShop dessa mesma versão.
Por onde entram (quase sempre)
Com todos os casos em cima da mesa, as vias de entrada repetem-se:
| Via de entrada | O que vimos | O que a fecha |
|---|---|---|
| Palavra-passe do painel ou do FTP divulgada | Início de sessão válido no painel do alojamento ou no FTP principal, sem qualquer falha técnica | Palavras-passe únicas, 2FA no painel, SFTP, contas FTP mínimas e rotação após qualquer incidente |
| Módulo com injeção de SQL | Superadministradores criados em rajada; controladores públicos que não verificam nada | Módulos atualizados, retirar os que não se usam, rever periodicamente a lista de funcionários |
Ficheiros PHP acessíveis em modules/ | Web shells em módulos desinstalados ou abandonados | PrestaShop 9 (bloqueia-o de origem) ou um .htaccess com exceções bem pensadas |
| Outro site no mesmo alojamento | Um WordPress sem manutenção usado para escrever na loja | Separar as contas de alojamento ou manter os dois sites igualmente atualizados |
| O computador de quem administra | Programas que roubam palavras-passe guardadas no navegador e no cliente de FTP | Não guardar palavras-passe do FTP no cliente, gestor de palavras-passe, 2FA |
Repare que só uma das cinco é uma falha de programação «pura». As restantes são manutenção: o que está instalado, o que sobra e quem tem as chaves.
Porque é que quase todas as lojas atacadas eram antigas
Não é por acaso. Em quase todos os incidentes em que trabalhámos, a loja estava em PrestaShop 1.6 ou 1.7, com PHP 7.x e com módulos que não eram atualizados há anos. Isso soma riscos que se multiplicam entre si:
- O PHP 7.4 deixou de receber correções de segurança no final de 2022, e as versões anteriores ainda antes. Uma falha nova no PHP nunca vai ser corrigida para o seu servidor.
- Os ramos antigos do PrestaShop já não recebem correções, e muitos módulos de terceiros deixaram de publicar versões para eles. Quando é publicada uma vulnerabilidade de um módulo popular, a correção sai para a versão atual. Se não a consegue instalar porque a sua loja é demasiado antiga, a vulnerabilidade é pública e a sua loja continua aberta.
- As lojas antigas acumulam módulos órfãos: pastas de módulos experimentados e desinstalados há anos que continuam no disco e que, na 1.7, podem ser executados por URL. No PrestaShop 9, o
.htaccessdemodules/já bloqueia a execução direta de PHP. - Quanto mais antiga é a loja, mais medo dá mexer-lhe. E o que não se mexe não se revê.
Atualizar não é uma garantia absoluta: a loja do caso 2 já estava no PrestaShop 9, mas o atacante tinha entrado antes, com a palavra-passe do alojamento. O que uma loja atualizada faz é fechar as vias de entrada conhecidas e fazer com que qualquer alteração estranha se note. Uma loja antiga é uma loja onde as vias conhecidas continuam abertas e onde ninguém compara nada com nada.
O que fazemos na Rekire quando uma loja foi atacada
Quando nos chega uma loja comprometida, seguimos sempre a mesma ordem. A ordem importa: apagar primeiro o ficheiro malicioso é a forma mais rápida de o atacante voltar pelo mesmo sítio uma semana depois.
- Cópia forense antes de tocar em qualquer coisa. Ficheiros e base de dados, guardados fora do site. Se apagar sem copiar, perde a prova do que aconteceu, desde quando e que dados ficaram expostos.
- Trabalhar sobre uma cópia isolada. Trazemos a loja para o nosso ambiente, sem acesso à Internet, com o correio capturado e os gateways desativados, para a analisar sem o risco de escrever a clientes ou fazer cobranças.
- Comparar com algo conhecido. O núcleo, com o ZIP oficial da mesma versão do PrestaShop. Os módulos, com o seu pacote original. A loja inteira, com uma cópia anterior, se existir. O que muda sem motivo é o primeiro suspeito.
- Rever o que não são ficheiros. Funcionários e perfis, contas de webservice e as suas permissões, tarefas agendadas do servidor, chaves de configuração dos gateways, JavaScript dentro de páginas CMS, da configuração ou das descrições de produto.
- Encontrar a via de entrada. Registos de acesso web, do FTP e do painel. Sem saber por onde entraram, a limpeza é provisória.
- Fechar a entrada e depois limpar. Corrigir ou retirar o módulo vulnerável, blindar as pastas, eliminar contas FTP a mais. Depois, quarentena do que é malicioso, que fica guardado como prova em vez de ser apagado.
- Alterar todas as credenciais. Painel, FTP, base de dados, funcionários, chaves de API de gateways e serviços. E terminar todas as sessões abertas do back-office.
- Medir o dano. Que encomendas e pagamentos passaram pela loja enquanto o código esteve ativo, para avisar a entidade de pagamento e decidir com o responsável pelo tratamento a notificação à AEPD.
- Deixar vigilância. Uma linha de base limpa e avisos que disparam no exato momento em que algo volte a mudar.
- Propor a solução de fundo. Se a loja está numa versão sem suporte, o plano de migração. Limpar uma loja antiga sem a migrar é ganhar tempo, não resolver.
RKR Security Alert: o módulo que nasceu de tudo isto
Cada um dos incidentes que contamos aqui obrigou-nos a fazer à mão verificações que podiam ser automatizadas. Daí nasceu o RKR Security Alert, o módulo de segurança que desenvolvemos na Rekire e que usamos nas nossas próprias auditorias. Funciona do PrestaShop 1.7.6 ao 9.2, precisamente porque as lojas que mais precisam dele são as que ainda não migraram.
O que vigia
- Os dados de pagamento e a configuração. Guarda uma fotografia da configuração, dos módulos, dos funcionários, dos URL da loja e das contas de webservice, e compara-a com o estado atual. Não depende dos eventos do PrestaShop: se alguém alterar algo diretamente por SQL, contornando o back-office, a alteração aparece na mesma. As alterações nos gateways de pagamento são marcadas como críticas.
- Os funcionários. Criações, alterações e eliminações, com destaque para as contas de superadministrador. Os administradores falsos do caso 1 teriam gerado um aviso no próprio dia em que foram criados.
- Os acessos. Entrada no back-office a partir de um IP novo, com país, cidade e aviso se for um proxy, uma VPN ou um centro de dados.
- Os templates do pagamento. Impressão digital de todos os templates do checkout de todos os temas instalados, não só do ativo. Basta que um deles mude para haver aviso: foi exatamente o que denunciou o caso 1.
- Os módulos por versão. Se os ficheiros de um módulo mudarem sem que a sua versão tenha mudado, ou se aparecer um novo, é emitido um aviso. É o que teria denunciado a substituição do módulo de pagamento do caso 2.
- As tarefas agendadas e a blindagem das pastas.
O que procura nos ficheiros
- Clonadores de pagamento, backdoors e web shells, execução de comandos, ofuscação, JavaScript injetado e código escondido em imagens.
- Web shells reconhecidas pelo que sabem fazer e não só por assinaturas: listar, escrever e apagar ficheiros com um caminho recebido por parâmetro. É assim que se apanham as que estão escritas em PHP limpo, como o falso leitor de QR do caso 3.
- Comparação do núcleo com o ZIP oficial do PrestaShop, que é a única coisa que deteta a alteração de um só carácter num ficheiro legítimo.
- Uma deteção crítica não pode ser ocultada com um padrão de caminho: aprendemo-lo com a loja que passou por duas limpezas com um carregador em
vendor/.
A análise é feita por partes e é retomada onde ficou, por isso não falha por causa do limite de tempo do servidor, e cada deteção traz a prova: o que encontrou, em que linha e a partir de onde é alcançável.
A sentinela do navegador
Há ataques que não deixam nada no disco, como o carregador por WebSocket do caso 3, ou que só aparecem quando o cliente faz alguma coisa, como o formulário falso do caso 1. Para esses, o módulo inclui uma sentinela que observa a página já montada no navegador: avisa se aparecer um campo de cartão fora de um iframe depois de a página carregar, se o checkout enviar dados para um domínio novo com sendBeacon, fetch ou XHR, se for aberto um WebSocket externo ou se uma página escrever na área de transferência um comando de sistema sem que o utilizador tenha clicado em nada (a técnica do captcha falso conhecida como ClickFix). A sentinela nunca guarda o conteúdo desses pedidos: num checkout conteriam dados de cartões reais.
Pensado para lojas que já chegam comprometidas
Instala-se em modo primeira auditoria: não dá nada como «normal» até rever o relatório. Se a loja já estava infetada quando o instalou, a infeção não entra na linha de base. Os avisos chegam pelo Telegram, classificados por gravidade (pode separar um grupo para o que é importante e outro para o que é informativo), e ficam também na caixa de entrada do painel, mesmo que não use o Telegram.
E uma decisão de design que nos parece importante: nada sai da sua loja. A análise é feita no seu servidor com regras que vêm com o módulo. Nenhum ficheiro, fragmento ou dado da sua base de dados é enviado a ninguém.
Lista de verificação para esta semana
Se chegou até aqui, isto é o que pode fazer sem a ajuda de ninguém:
- Entre em Parâmetros avançados → Equipa e reveja cada funcionário. Se houver algum que não reconheça, sobretudo com perfil de superadministrador, trate a loja como comprometida.
- Concilie as cobranças da última semana no painel do seu gateway com as encomendas pagas da loja.
- Faça uma compra de teste com um e-mail que não seja da loja, a partir de um navegador sem sessão de administrador, e veja se o formulário de pagamento é o de sempre.
- Altere a palavra-passe do painel do alojamento e do FTP, garantindo que não se repete em nenhum outro sítio, e ative a verificação em dois passos do painel se o seu fornecedor a disponibilizar.
- Peça ao seu alojamento a lista de contas FTP e apague as que não usa.
- Veja em Módulos o que tem instalado e, no FTP, que pastas existem em
modules/. O que estiver no disco e não na lista está a mais. - Verifique que versão do PrestaShop e do PHP tem. Se for PrestaShop 1.6 ou 1.7, ou PHP 7.x, marque uma data para a migração.
Migrar não é um luxo: é a maior medida de segurança
Sabemos que migrar uma loja dá preguiça e mete respeito. É preciso rever módulos, tema, URL, pagamentos, faturas. Mas depois de ver por dentro todos estes casos, a nossa conclusão é clara: a loja mais cara de manter é a que não se atualiza. Um incidente custa a limpeza, a notificação, os estornos, o tempo da equipa e, sobretudo, a confiança dos clientes cujos cartões foram usados noutro sítio.
Uma migração para o PrestaShop 9 com um PHP atual fecha de uma vez as vias de entrada conhecidas das versões antigas, obriga-o a fazer o inventário do que tem instalado e deixa-o numa versão que continua a receber correções. Se, além disso, vigiar o que muda, a próxima tentativa nota-se no próprio dia.
Como resolvê-lo no PrestaShop
O RKR Security Alert vigia a configuração, os pagamentos, os funcionários, os acessos, os templates do checkout e os ficheiros, compara o núcleo com o ZIP oficial e avisa pelo Telegram assim que algo muda, do PrestaShop 1.7.6 ao 9.2. O RKR Sentinel avisa-o dos erros do site antes de os clientes lhos contarem, e uma loja que de repente fica em branco, como a do caso 2, é um erro que convém ver ao minuto. O RKR Order Guard evita encomendas, estados de pagamento e faturas duplicados, para que aquilo que o back-office diz seja fiável quando o concilia com o banco.
E se suspeita de que a sua loja está comprometida ou quer migrá-la antes que esteja, com os pacotes de horas de suporte da Rekire fazemos a auditoria, a limpeza com o método deste artigo e a migração para o PrestaShop 9.