Incidente: invasão do WordPress de cursos (ago–out/2026)

Entre agosto e outubro de 2026 o WordPress de cursos.artesmarciaisonline.com.br foi usado por atacantes para publicar cerca de 188 mil posts de spam (cassinos e apostas) com uma conta de administrador legítima. Também recebeu webshells e contas de administrador falsas. O caso foi descoberto em 02/10/2026, durante a migração da VM Azure para o OKE, e contido no mesmo dia.

Horários em horário de Brasília (BRT, UTC-3), salvo indicação. O plugin Activity Log grava em BRT. Os arquivos da VM e o banco do cluster usam UTC. As conversões já foram feitas.

Resumo executivo

  • Vetor principal (com evidência): a senha da conta de administrador ID 1 foi descoberta por força bruta, sofrida continuamente desde pelo menos abril/2026. Com ela, uma botnet publicou o spam pelo XML-RPC (xmlrpc.php), sem nunca passar pela tela de login.

  • Agravantes: cerca de 70 plugins desatualizados, com atualizações desligadas de propósito, vários deles com falhas críticas públicas exploráveis sem login; tema pirateado; cadastro de usuários aberto.

  • Impacto: spam de SEO no domínio, controle total de administrador, webshells na VM antiga, senha do banco exposta e possível acesso a dados pessoais dos alunos. As quedas de setembro atribuídas à "época de provas" eram, muito provavelmente, carga gerada pelo spam.

  • Situação em 02/10/2026: site limpo e no ar no OKE; VM antiga parada; senhas do banco, salts e sessões trocados; XML-RPC bloqueado; conta ID 1 excluída. O software continua vulnerável até a execução do guia de atualização.

Linha do tempo

Quando (BRT) Evento

abr–ago/2026

Força bruta contínua contra a conta ID 1 registrada no Activity Log: 312 tentativas em abril, 1.668 em maio (411 IPs distintos), 283 em junho, 24 em julho e 256 em agosto.

24/08 12:01

Primeiro acesso confirmado como conta ID 1: um post service_ping_test é criado (IP 45.134.180.126) e enviado para a lixeira 1 segundo depois, de outro IP (138.99.37.152). É uma ferramenta automática testando se a credencial publica. Nenhum evento de login.

24/08 18:13

Post de teste Content Review … (ID 30192), o primeiro que permaneceu publicado.

25–31/08

Mais testes (cw-check-https://test123.com, Test post title, imagens cw-image-*) e os primeiros spams (cassino, apostas em turco, texto em russo).

07/09 06:22

Início do spam em massa, a partir das faixas 2a0b:bcc0::/32 e 185.153.197.0/24.

17–23/09

Quedas recorrentes do site na VM, tratadas como falta de capacidade na "época de provas": resize da VM, disco Premium e aumento de pm.max_children (ADR 0005 do repositório iac).

24/09 03:01

Conta megan criada sem login (requisição anônima, IP 137.184.111.69), já como administradora.

24/09 09:14

Conta upagrade criada sem login (IP 51.195.119.212), como assinante.

26/09 22:25

Conta adminsss criada sem login (IP 103.139.11.248), como administradora, sem e-mail.

27/09 10:44–11:18

Webshells e droppers gravados na VM: filefuns.php na raiz; cache.php/index.php em pastas com nome duplicado; .htaccess somente leitura em mu-plugins; wp-includes/fonts.php vazio; pasta images/ e robots.txt na raiz.

28/09

Pico de spam: 21.949 posts num único dia.

29/09 08:41–15:27

bunk_56ziqp.php na raiz do cursos; Nx_vb10id.php na raiz do sistemafuji; functions.php do tema filho alterado com código ofuscado.

30/09 00:57

ug.php (61 KB, gerenciador de arquivos/webshell) na raiz do sistemafuji.

01/10

10.880 posts de spam vindos de 571 IPs distintos.

01/10 23:01

Modo manutenção ativado na VM como parte da migração. O spam na VM para nesse minuto.

02/10 ≈00:00

DNS de cursos e do apex apontado para o OKE.

02/10 00:08–00:25

17 posts de spam já no OKE, via XML-RPC.

02/10 00:25

Timeouts levam à investigação, o spam é descoberto e o wp-cursos é desligado (0 réplicas). Começa a resposta ao incidente.

02/10 madrugada

Investigação em modo só leitura (arquivos, banco, Activity Log); containers da VM parados.

02/10 01:12–01:20

Limpeza do banco: spam, revisões e contas falsas removidos; páginas legítimas restauradas.

02/10 ≈01:45

Senhas do MariaDB trocadas; wp-cursos religado.

02/10 01:47–01:56

783 posts de spam publicados via XML-RPC, de 2 IPs, nos minutos seguintes ao religamento.

02/10 01:49

Salts do wp-config.php trocados.

02/10 01:55

xmlrpc.php bloqueado no nginx do pod. O spam para.

02/10 ≈01:57

Proxy da Cloudflare religado no registro cursos.

02/10

Conta ID 1 excluída, com o conteúdo legítimo transferido para a conta ID 2.

02/10 ≈11:05

A primeira execução da checagem periódica (/wp-invasao) mostra que o bloqueio do XML-RPC era contornável: POST /xmlrpc.php/xmlrpc.php executava o XML-RPC (o nginx só casava o caminho exato). Desde o religamento, o log do pod tinha dezenas de POSTs nesse caminho e o Activity Log registrava dezenas de senhas erradas. A mesma checagem encontra dois links ocultos de spam de SEO na home (dlwordpress.com e dlandroid24.com, em blocos com left:-9999px), injetados de forma ofuscada por um plugin pirata. Eles já estavam nos backups de 2018 e não fazem parte desta invasão.

02/10 11:26

nginx do pod corrigido (location ^~ /xmlrpc.php e try_files $uri =404;), aplicado com reload, sem reiniciar o pod.

02/10 ≈11:29

Regra de WAF da Cloudflare trocada para starts_with(http.request.uri.path, "/xmlrpc.php"). Verificado: todas as variações do caminho são bloqueadas na borda e não aparecem no log do pod.

02/10 ≈13:50

Origem dos links ocultos encontrada, listando os callbacks do filtro the_content com o WordPress carregado pela linha de comando: a função sorry_function, anexada no fim de plugins/advanced-custom-fields-pro/acf.php (ACF PRO 5.5.9 pirata, arquivo datado de 20/09/2018). Para visitante não logado, em páginas e posts, ela envolvia o conteúdo com os dois <div> ocultos, escritos em octal/hexadecimal (por isso a busca por texto não achava). Bloco removido (7 linhas, php -l ok), cache do WP Fastest Cache limpo; home, cursos e contato verificados sem o spam. Cópia do arquivo original guardada fora do cluster como evidência (SHA-256 2eef6506…0735e). Nenhum outro plugin ou tema tem o mesmo padrão de ofuscação.

02/10 ≈14:10

Ao preparar o sandbox, descoberto que os backups antigos eram baixáveis publicamente: wp-content/ai1wm-backups/.wpress (4,3 GB, site e banco completos, de 2018 a 2020), wp-content/updraft/-db.gz (2018 a 2024), wp-content/debug.log e, o mais grave, wp-content/aiowps_backups/: o All In One WP Security gerava um dump completo e atual do banco a cada hora (.sql de ~49 MB, os 2 mais recentes), com hashes de senha, dados de alunos e configurações de integrações. Todos com HTTP 200; os nomes têm data, hora e sufixo aleatório de 10 caracteres. Esses plugins se protegem com .htaccess, que o nginx ignora (o mesmo valia na VM). Os logs disponíveis (~13 h, só do pod atual) não mostram download por terceiros; antes disso, não há como saber.

02/10 14:26

Bloqueio no nginx (commit 99e38ba no gitops): diretórios de backup, .wpress/.sql/.log e arquivos ocultos. O dump que ficou no cache da Cloudflare por causa do teste foi purgado. Backups copiados para fora do cluster (91 arquivos, 4,4 GB, conferidos por SHA-256) e apagados do volume às ~15:25, junto com o desligamento do backup automático do AIOWPS (aiowps_enable_automated_backups). O webroot caiu de 5,4 GB para 950 MB.

Como o ataque funcionou

incidente-fluxo

Por que a conclusão é XML-RPC com a senha da conta ID 1:

  • todo o spam foi registrado como ação da conta ID 1, a partir de centenas de IPs rotativos, e nenhum desses eventos tem login correspondente. A autenticação pelo XML-RPC não gera evento de login no Activity Log;

  • a conta sofria força bruta havia meses;

  • depois do religamento no OKE, com a senha ainda válida, o spam voltou em minutos e parou no instante em que o xmlrpc.php foi bloqueado;

  • logo depois do religamento, o nginx do pod registrou 1.884 chamadas ao xmlrpc.php em 5 minutos, 75% de todo o tráfego.

O que não foi possível confirmar: como as contas megan e adminsss foram criadas como administradoras sem login. Isso indica outra falha, explorável anonimamente. As candidatas plausíveis entre as vulnerabilidades confirmadas nas versões instaladas são o bypass de autenticação do miniOrange Social Login (CVE-2023-2982) e as SQL injections sem login do Paid Memberships Pro, do LearnPress e do WP Fastest Cache (ver plugins.adoc#vulns). Nenhuma delas foi comprovada. Os logs de acesso do nginx da VM antiga (/opt/docker/nginx/logs/) não foram analisados por completo e podem mostrar as requisições que criaram essas contas: os IPs e horários estão em Indicadores de comprometimento.

Indicadores de comprometimento

Tabela 1. Arquivos (VM Azure; horários de modificação em UTC)
Arquivo Modificado (UTC) Tamanho Observação

cursos:/bunk_56ziqp.php

29/09 11:41

1.287 B

webshell/dropper na raiz

cursos:/filefuns.php

27/09 13:44

1.973 B

webshell na raiz

cursos:/images/, /robots.txt

27/09 14:18

—

criados pelo atacante

cursos:/wp-includes/fonts.php

27/09 14:18

0 B

não existe no WordPress 4.9

cursos:/wp-content/mu-plugins/.htaccess

27/09 14:18

127 B

somente leitura

cursos:/wp-content/uploads/revslider/home-page/home-page/cache.php (+ index.php)

27/09 14:18

5.667 B

dropper em pasta duplicada; foi copiado para o OKE e removido

…/mce/mce/, …/config/config/, …/tpl/tpl/, …/Cookie/Cookie/ (cache.php + index.php)

set/2026

—

mesmo padrão de pasta duplicada, dentro de plugins e do tema

cursos:/wp-content/themes/eduma-child/functions.php

29/09 18:27

7.360 B

código ofuscado injetado

sistemafuji:/Nx_vb10id.php

29/09 14:43

1.281 B

webshell na raiz

sistemafuji:/ug.php

30/09 03:57

61.168 B

gerenciador de arquivos/webshell

Banco de dados
  • Posts com autor = conta ID 1 a partir do ID 30190, muitos com data futura (agendados para dezembro/2026), títulos em espanhol, alemão, polonês, turco e russo.

  • Páginas Nova Home (ID 7979) e Home (ID 4524) editadas pela conta ID 1, com links para sites de cassino, apostas e anabolizantes.

  • Contas megan (ID 3755, admin, e-mail falso no próprio domínio), upagrade (ID 3756) e adminsss (ID 3757, admin, sem e-mail).

Rede (principais origens no Activity Log)
  • Primeiros acessos: 45.134.180.126, 138.99.37.152, 194.59.8.96.

  • Spam em massa: faixas 2a0b:bcc0::/32 e 185.153.197.0/24, além de 185.153.199.239, 185.244.214.180 e 82.102.22.24.

  • Criação de contas: 137.184.111.69, 51.195.119.212, 103.139.11.248.

Quase todas as origens são proxies ou botnets rotativos. Bloquear por IP tem pouco efeito; a proteção efetiva é por credencial, por endpoint (XML-RPC) e por WAF.

Impacto

Área Impacto

Reputação e SEO

Cerca de 188 mil URLs de spam publicadas e indexáveis sob o domínio, com sitemaps (post-sitemap50.xml). Pedido de remoção no Google Search Console pendente.

Controle do site

Acesso de administrador com a conta ID 1 desde 24/08 e duas contas admin falsas desde 24/09.

Segredos

Senha root do MariaDB, legível como variável de ambiente pelos containers WordPress da VM; salts do wp-config.php; hashes de senha de todos os usuários; credenciais de integrações guardadas no banco (SMTP, Mailchimp, gateways de pagamento, reCAPTCHA, ManageWP).

Dados pessoais

O atacante teve acesso de administrador e ao banco: nomes, e-mails, pedidos e progresso das contas de alunos (os IDs de usuário chegam a ~3.750) podem ter sido acessados. Avaliar a comunicação à ANPD e aos titulares (LGPD).

Disponibilidade

Quedas em setembro na VM. Na migração, timeouts (504) no OKE causados pelo volume de spam e pelas chamadas ao XML-RPC.

Infraestrutura do FUJI

Sem evidência de acesso. O PostgreSQL do FUJI, na mesma VM, só aceita conexões de 127.0.0.1 e da rede do AKS, e os containers WordPress saíam por 172.17–20.x. O host da VM não mostrou persistência (crontab, logins SSH e processos normais). No OKE, o pod do WordPress tinha caminho de rede até o PostgreSQL de produção e o IMDS da Oracle, mas não há indício de que tenha sido usado.

Contenção e erradicação

Ação Como Verificação

Tirar do ar

wp-cursos com 0 réplicas no OKE; containers da VM parados com restart=no (volumes preservados como evidência)

Portas 80/443/8080 da VM fechadas

Limpar o banco

Remoção dos posts, páginas, anexos e embeds a partir do ID 30192 com autor = conta ID 1, mais revisões, metadados, termos e comentários; 3 contas falsas e todas as sessões removidas

Restaram os 19 posts legítimos, 85 páginas, 82 cursos, 6.075 aulas, 4.271 pedidos LearnPress e 6 administradores legítimos; banco de ~2,9 GB para ~400 MB

Restaurar páginas

Nova Home e Home voltaram à última revisão anterior ao ataque (2019 e 2018)

Sem links de spam; tamanhos iguais aos das revisões originais

Limpar arquivos

Remoção do dropper em uploads, do cache de páginas do WP Fastest Cache e das 90 imagens de spam (11 originais + miniaturas)

Nenhum .php em uploads; a cópia do OKE não tinha os webshells da raiz nem o tema alterado

Trocar segredos

Senhas novas do root e do usuário de aplicação do MariaDB (só nos Secrets); 8 salts do wp-config.php regenerados

Login do root com a senha nova; site conectando ao banco

Fechar o vetor

xmlrpc.php bloqueado no nginx do pod (403); proxy da Cloudflare religado; conta ID 1 excluída (conteúdo transferido para a conta ID 2). Às 11:26–11:29 o bloqueio foi refeito para cobrir /xmlrpc.php/…​ no nginx e no WAF da Cloudflare (ver a linha do tempo)

Nenhum post novo depois de 01:55; URLs de spam retornando 404

Pendências

Item Dono Situação

Apagar os 784 posts de spam (e as revisões) publicados entre 01:47 e 01:56 de 02/10, atribuídos à conta ID 2 após a exclusão da conta ID 1, e limpar o cache de páginas

Infra

feito em 02/10

Trocar as senhas dos 5 administradores restantes e rever quem precisa ser administrador

Escola

pendente

Trocar as credenciais de integrações guardadas no banco (SMTP, Mailchimp, gateways de pagamento, reCAPTCHA)

Escola

pendente

Decidir sobre o ManageWP (plugin worker): remover se não for usado

Escola

pendente

Revisar o cadastro aberto (users_can_register = 1)

Escola

pendente

Regra de WAF na Cloudflare bloqueando /xmlrpc.php e variações (starts_with)

Infra

feito em 02/10

Remover os links ocultos de spam de SEO da home (dlwordpress.com, dlandroid24.com), injetados pela sorry_function do ACF PRO pirata

Infra

feito em 02/10

Avaliar a exposição pública dos backups (.wpress com site e banco completos, dumps do UpdraftPlus, dumps horários do AIOWPS com o banco atual) e do debug.log, acessíveis até 02/10/2026, no contexto da LGPD; considerar como possível origem das credenciais usadas na invasão

Escola

pendente

Backup real do banco e do volume, fora do cluster (o do AIOWPS ficava dentro do próprio site e foi desligado)

Infra

pendente

Substituir o ACF PRO pirata por uma cópia licenciada (ou remover o plugin). Reinstalar de fonte não oficial traz a injeção de volta

Escola

pendente

Rodar a checagem periódica (/wp-invasao, no iac) até concluir a atualização

Infra

em andamento

Executar o guia de atualização (tema licenciado, core, plugins, PHP, MariaDB)

Infra + Escola

pendente

Avaliar a comunicação à ANPD e aos titulares (LGPD)

Escola

pendente

Pedir no Google Search Console a remoção das URLs de spam

Escola

pendente

Checar o IAM da OCI (permissões dos nós via IMDS) e o audit log de 13/09 a 02/10

Infra

pendente

NetworkPolicy isolando o namespace (o cluster hoje não tem controller)

Infra

pendente

Remover o registro DNS ftp.artesmarciaisonline.com.br (aponta para a VM)

Infra

pendente

Antes de destruir a VM (hoje desalocada): copiar e analisar os logs do nginx (/opt/docker/nginx/logs/) em busca das requisições que criaram megan e adminsss

Infra

pendente

Confirmar as 3 chaves SSH da VM (arquivo alterado em 21/09)

Infra

pendente

Limpar os 15 posts de spam do wp-fuji (desligado)

Infra

pendente

Corrigir o ADR 0005 no iac: as quedas de setembro eram spam, não alunos

Infra

pendente

Backup automatizado e monitoramento externo fora da VM

Infra

pendente

Lições aprendidas

  • Desligar atualizações não é estabilidade. O Easy Updates Manager com tudo desligado, mais o WP Downgrade, mantiveram falhas críticas conhecidas abertas por anos.

  • Força bruta registrada é um alerta, não ruído. O Activity Log mostrava milhares de tentativas contra a conta principal desde abril. Senha forte, 2FA e XML-RPC bloqueado teriam evitado o vetor principal.

  • Testar o bloqueio pelo comportamento, não pelo status. O primeiro bloqueio do XML-RPC devolvia 403 no caminho exato, mas /xmlrpc.php/xmlrpc.php continuava executando. Só um teste funcional (demo.sayHello respondendo ou não) mostrou a brecha.

  • Desconfiar de "falta de capacidade" sem explicação. As quedas de setembro foram tratadas com mais CPU, disco e workers. Uma olhada no número de posts ou no log de acesso teria mostrado o ataque três semanas antes.

  • Secret em variável de ambiente é legível por quem executa código no container. A senha root do banco nunca deveria estar no ambiente do WordPress.

  • Migração é auditoria. O incidente só apareceu porque o site foi movido e medido. Ao migrar sistemas legados, inventariar conteúdo, usuários e arquivos inesperados.

  • Cópias pirateadas não são gratuitas. O tema "nulled" impede atualizar e é, por si só, um vetor comum de backdoor.

  • O Activity Log foi a principal fonte forense. Manter um plugin de auditoria ativo, e idealmente enviar os registros para fora do site, é o que permitiu reconstruir o ataque.