WordPress Hackeado? Por Que Migrar para Next.js + Supabase É Sua Melhor Solução
Perdi a conta de quantas vezes um cliente chegou até nós com alguma variação da mesma história: "Nosso site WordPress foi hackeado. Limpamos. Foi hackeado novamente. Desistimos." O último foi uma empresa de ecommerce de médio porte cuja loja WooCommerce havia sido injetada com um skimmer de cartão de crédito escondido dentro de uma atualização de plugin que parecia legítima. Eles estavam vazando dados de pagamento de clientes há três semanas antes de alguém perceber. Isso não é um caso extremo. É terça-feira no ecossistema WordPress.
Este artigo não é sobre criticar WordPress. Ele alimentou uma enorme parte da web por boas razões. Mas a arquitetura que o tornou acessível em 2005 é a mesma arquitetura que o torna um ímã para ataques automatizados em 2025. Se você foi hackeado -- ou está cansado de gastar dinheiro em plugins de segurança que são eles próprios vetores de ataque -- este é seu guia de jogadas para migrar para algo fundamentalmente mais seguro.
Sumário
- O Problema de Segurança do WordPress É Arquitetural
- Vetores de Ataque Comuns do WordPress em 2025
- Por que a Arquitetura Headless Elimina Categorias Inteiras de Ataques
- Next.js + Supabase: Uma Stack Focada em Segurança
- Comparação de Superfície de Ataque: WordPress vs Headless
- O Guia de Migração: WordPress para Next.js + Supabase
- Endurecimento de Segurança Pós-Migração
- Custo Real da Segurança do WordPress vs Migração
- FAQ

O Problema de Segurança do WordPress É Arquitetural
Deixe-me ser claro sobre algo: o time central do WordPress faz um bom trabalho em segurança. O WordPress core, mantido atualizado, é razoavelmente seguro. Mas ninguém executa apenas o WordPress core. O site WordPress médio tem 20-30 plugins instalados. Cada um é uma dependência que você não escreveu, mantida por alguém que você não conhece, com acesso ao seu banco de dados, seu sistema de arquivos e os dados dos seus usuários.
Aqui está a coisa que continua sendo ignorada em artigos "melhores práticas de segurança do WordPress": o problema não é que proprietários de sites WordPress são negligentes. O problema é que a arquitetura do WordPress exige que você instale código PHP executável de terceiros diretamente no seu servidor para obter funcionalidade básica. É o equivalente a dar para cada contratado que trabalha na sua casa uma cópia da chave da sua casa -- permanentemente.
O banco de dados de vulnerabilidades do WPScan rastreou mais de 7.900 novas vulnerabilidades do WordPress em 2024, com plugins respondendo por aproximadamente 96% delas. O relatório de ameaças de 2024 da Sucuri descobriu que WordPress representou aproximadamente 95% de todas as infecções de CMS que limparam. E a Patchstack reportou que 33% das vulnerabilidades críticas do WordPress em 2024 não tinham correção disponível no momento da divulgação.
Estes não são bugs que podem ser corrigidos com melhores práticas de codificação. São propriedades emergentes da arquitetura em si.
Vetores de Ataque Comuns do WordPress em 2025
Antes de falarmos sobre a solução, vamos catalogar o que você realmente está se defendendo. Pessoalmente, fiz triagem de dezenas de sites WordPress comprometidos, e os ataques seguem padrões previsíveis.
Injeção SQL Através de Plugins
WordPress usa um banco de dados MySQL com um esquema bem documentado. Cada plugin que aceita entrada de usuário e toca no banco de dados é um ponto potencial de injeção SQL. A função $wpdb->prepare() existe, mas é opt-in. Desenvolvedores de plugins esquecem, usam mal, ou pulam completamente para queries "simples".
Uma vez rastreei uma injeção de volta para um plugin de formulário de contato que havia sido abandonado por 18 meses mas ainda estava instalado em 200.000+ sites. O atacante estava usando injeção baseada em UNION para despejar a tabela wp_users, pegar hashes de senha de admin, e quebrá-los offline.
-- Como uma injeção SQL típica do WordPress se parece nos logs
GET /wp-content/plugins/vulnerable-plugin/ajax.php?id=1%20UNION%20SELECT%201,user_login,user_pass,4,5%20FROM%20wp_users--
Injeção de Objetos PHP e Execução de Código Remoto
O uso intenso de serialize() e unserialize() do WordPress cria oportunidades para injeção de objetos PHP. Quando um plugin desserializa dados controlados pelo usuário (e muitos fazem), um atacante pode criar payloads que executam código arbitrário durante o processo de desserialização.
Em 2024, uma vulnerabilidade crítica de RCE em um plugin popular de backup (instalado em 5 milhões+ de sites) permitia que atacantes não autenticados executassem código PHP arbitrário. A correção levou 11 dias para ser disponibilizada. Onze dias onde cada site com esse plugin era alvo fácil.
Ataques de Cadeia de Suprimento de Plugins
Este é o que mais me assusta. Atacantes compram plugins abandonados com grandes bases de instalação, enviam uma "atualização de segurança" contendo uma backdoor, e os mecanismos de auto-atualização do WordPress distribuem o malware para cada site rodando aquele plugin. Aconteceu com Display Widgets (300.000 instalações) e Social Warfare (70.000 instalações), e esses são apenas os que foram descobertos.
Ataques de Força Bruta em wp-login.php
Todo site WordPress expõe /wp-login.php e /xmlrpc.php por padrão. Botnets automatizadas batem nestes endpoints constantemente. A Wordfence reportou bloquear uma média de 3 bilhões de requisições maliciosas por mês através de sua rede em 2024. Mesmo com rate limiting e autenticação de dois fatores, você está gastando recursos de servidor processando esses ataques.
Cross-Site Scripting (XSS) via Temas e Plugins
XSS armazenado no WordPress é particularmente perigoso porque o painel administrativo e o site público compartilham o mesmo contexto de sessão. Um payload XSS injetado através de um comentário, uma submissão de formulário, ou uma configuração de plugin vulnerável pode escalar para acesso total de admin.
Por que a Arquitetura Headless Elimina Categorias Inteiras de Ataques
Aqui é onde as coisas ficam interessantes. Uma arquitetura headless não apenas reduz sua superfície de ataque -- elimina categorias inteiras de ataques removendo as condições que os tornam possíveis.
Em uma configuração tradicional do WordPress, o mesmo servidor que renderiza seu HTML também:
- Executa código PHP de 20+ plugins de terceiros
- Gerencia autenticação de usuário
- Se conecta ao banco de dados
- Serve a interface de administração
- Processa uploads de arquivo
- Processa submissões de formulário
Isso é muita responsabilidade para uma única aplicação. Em uma configuração headless com Next.js e Supabase, essas responsabilidades são separadas entre serviços isolados:
- Frontend (Next.js em Vercel/Netlify): HTML/JS estático servido de uma CDN. Sem runtime de servidor exposto à internet pública na maioria dos casos.
- Banco de dados + Auth (Supabase): Postgres gerenciado com Row Level Security, nunca diretamente exposto aos usuários finais.
- Camada de API: Funções serverless com endpoints explícitos e mínimos.
- CMS (se necessário): CMS headless rodando em sua própria infraestrutura isolada.
Não há PHP para injetar. Não há diretório de plugins com acesso de escrita. Não há sessão compartilhada entre o admin e o site público. Não há wp-login.php para bots baterem.
Você não precisa de um WAF para proteger uma superfície de ataque que não existe.

Next.js + Supabase: Uma Stack Focada em Segurança
Vamos ser específicos sobre por que essa combinação particular funciona tão bem de um ponto de vista de segurança.
Next.js: O Frontend Que Não Executa Código
Quando você constrói um site Next.js com static generation (SSG) ou incremental static regeneration (ISR), o que é deployado são arquivos HTML, CSS e JavaScript em uma CDN. Não há servidor de aplicação processando requisições em tempo real. Você não pode fazer injeção SQL em uma CDN.
Para funcionalidade dinâmica, Next.js Server Actions e Route Handlers rodam como funções serverless. Cada função é:
- Isolada em seu próprio contexto de execução
- Sem estado (sem memória compartilhada entre requisições)
- De curta duração (cold start, executa, termina)
- Explicitamente definida (sem descoberta automática de endpoints)
// Next.js Route Handler -- explícito, tipado, mínimo
import { createClient } from '@/lib/supabase/server'
import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
const ContactSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
message: z.string().min(10).max(5000),
})
export async function POST(request: NextRequest) {
const body = await request.json()
const parsed = ContactSchema.safeParse(body)
if (!parsed.success) {
return NextResponse.json({ error: 'Invalid input' }, { status: 400 })
}
const supabase = await createClient()
const { error } = await supabase
.from('contact_submissions')
.insert(parsed.data)
if (error) {
return NextResponse.json({ error: 'Submission failed' }, { status: 500 })
}
return NextResponse.json({ success: true })
}
Compare isso com um plugin de formulário de contato do WordPress que tem que se conectar ao sistema de ações do WordPress, incluir seu próprio handler AJAX, gerenciar sua própria verificação de nonce, e construir suas próprias queries SQL. A versão Next.js tem menos partes em movimento, entrada validada via Zod, e queries parametrizadas através do cliente Supabase.
Supabase: Postgres com Row Level Security
Supabase oferece um banco de dados PostgreSQL gerenciado com uma funcionalidade matadora: Row Level Security (RLS). Em vez de confiar que seu código de aplicação vai forçar controle de acesso (o modelo WordPress), você define políticas de segurança no nível do banco de dados.
-- Apenas usuários autenticados podem ler seus próprios dados
CREATE POLICY "Users can view own profile"
ON profiles
FOR SELECT
USING (auth.uid() = user_id);
-- Público pode inserir mas não ler
CREATE POLICY "Anyone can submit contact form"
ON contact_submissions
FOR INSERT
WITH CHECK (true);
CREATE POLICY "Only admins can read submissions"
ON contact_submissions
FOR SELECT
USING (auth.jwt() ->> 'role' = 'admin');
Mesmo se um atacante encontrar uma forma de fazer queries arbitrárias do Supabase (o que é muito mais difícil sem um contexto de execução PHP), as políticas RLS impedem que eles acessem dados que não deveriam ver. Isso é defesa em profundidade que WordPress fundamentalmente não pode oferecer porque seu sistema de permissões é implementado em código PHP, não no nível do banco de dados.
Supabase também lida com autenticação com suporte embutido para email/senha, magic links, provedores OAuth, e autenticação multifator. Sem plugin necessário. Sem código de terceiros rodando no seu servidor.
Comparação de Superfície de Ataque: WordPress vs Headless
Vamos colocar lado a lado.
| Vetor de Ataque | WordPress | Next.js + Supabase |
|---|---|---|
| Injeção SQL | Alto risco -- plugins constroem queries brutas | Quase zero -- queries parametrizadas via cliente Supabase, RLS como backup |
| PHP/Execução de Código Remoto | Alto risco -- plugins executam PHP do lado do servidor | Não aplicável -- sem runtime PHP |
| Cadeia de Suprimento de Plugins | Risco crítico -- auto-updates distribuem malware | Não aplicável -- sem ecossistema de plugins |
| Força Bruta (login) | Sempre exposto (wp-login.php, xmlrpc.php) |
Acesso admin através de Supabase Auth ou dashboard separado, sem endpoint de login público necessário |
| XSS (Armazenado) | Alto risco -- contexto compartilhado admin/público | Baixo risco -- React escapa output por padrão, admin e público são apps separados |
| Exploração de Upload de Arquivo | Alto risco -- arquivos PHP carregados podem executar | Baixo risco -- uploads vão para armazenamento de objetos (Supabase Storage/S3), nunca executados como código |
| Exposição de Banco de Dados | Acesso direto a MySQL se servidor é comprometido | Banco de dados atrás da infraestrutura Supabase, políticas RLS como guarda final |
| DDoS na Origem | Servidor deve processar cada requisição | Ativos estáticos em CDN, origem raramente é atingida |
| Enumeração de Caminho Conhecido | wp-admin, wp-content, wp-includes todos digitalizáveis |
Sem caminhos previsíveis, sem rotas de admin expostas |
O Guia de Migração: WordPress para Next.js + Supabase
Certo, você está convencido (ou seu site hackeado o convenceu). Aqui está como fazer isso de verdade. Executamos essa migração em Social Animal o suficiente para ter um processo repetível.
Fase 1: Triagem e Auditoria de Conteúdo (Semana 1)
Antes de tocar em qualquer código, você precisa entender o que você realmente tem.
- Exporte todo o conteúdo do WordPress usando WP-CLI ou a REST API. Não confie em exportações XML -- elas perdem campos de meta e tipos de post customizados.
- Catalogue toda a funcionalidade fornecida por plugins. Faça uma planilha: nome do plugin, o que faz, se você realmente precisa, e o que o substitui.
- Mapeie estruturas de URL para preservação de SEO. Cada URL existente precisa de um redirecionamento ou de uma rota correspondente em Next.js.
- Identifique recursos dinâmicos -- formulários, busca, contas de usuário, ecommerce -- que precisam de endpoints de API.
# Exporte conteúdo do WordPress via REST API
curl -s "https://yoursite.com/wp-json/wp/v2/posts?per_page=100&page=1" | jq '.' > posts_page1.json
curl -s "https://yoursite.com/wp-json/wp/v2/pages?per_page=100" | jq '.' > pages.json
curl -s "https://yoursite.com/wp-json/wp/v2/media?per_page=100" | jq '.' > media.json
Fase 2: Migração de Dados e Schema Supabase (Semana 2)
Designe seu schema do banco de dados Supabase baseado na auditoria de conteúdo. Não apenas replique o schema do WordPress -- ele é inchado com tabelas de metadados e blobs de dados serializados.
-- Schema limpo e propositalmente construído
CREATE TABLE posts (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
title TEXT NOT NULL,
slug TEXT UNIQUE NOT NULL,
content TEXT,
excerpt TEXT,
featured_image TEXT,
status TEXT DEFAULT 'draft' CHECK (status IN ('draft', 'published', 'archived')),
published_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
author_id UUID REFERENCES auth.users(id)
);
-- Abilite RLS imediatamente
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Published posts are public"
ON posts FOR SELECT
USING (status = 'published');
CREATE POLICY "Authors can manage own posts"
ON posts FOR ALL
USING (auth.uid() = author_id);
Escreva um script de migração (Node.js ou Python) que transforma exportações JSON do WordPress em seu novo schema e as insere no Supabase.
Fase 3: Build Next.js (Semanas 3-5)
Construa seu frontend Next.js. Se você está trabalhando com um time que conhece a stack, isso acontece rápido. Se você precisar de ajuda, nosso time de desenvolvimento Next.js fez essa migração o suficiente para ter opiniões fortes sobre os padrões certos.
Decisões arquiteturais-chave:
- Geração estática para páginas de conteúdo -- posts de blog, landing pages, páginas sobre. Esses se tornam arquivos HTML em uma CDN.
- Componentes de servidor para dados dinâmicos -- busque do Supabase em tempo de requisição com cache.
- Route handlers para submissões de formulário -- formulários de contato, inscrições em newsletter, etc.
- Middleware para redirecionamentos -- lidar com todas as suas URLs antigas do WordPress.
// next.config.ts -- lidar com redirecionamentos de URL do WordPress
const nextConfig = {
async redirects() {
return [
{
source: '/category/:slug',
destination: '/blog/category/:slug',
permanent: true,
},
{
source: '/:year(\\d{4})/:month(\\d{2})/:slug',
destination: '/blog/:slug',
permanent: true,
},
// wp-login.php -- envie bots para um 410
{
source: '/wp-login.php',
destination: '/gone',
permanent: true,
},
{
source: '/wp-admin/:path*',
destination: '/gone',
permanent: true,
},
]
},
}
Fase 4: Teste e Validação de SEO (Semana 6)
- Execute Screaming Frog contra o novo site para verificar se cada URL antiga se resolve ou redireciona.
- Valide que dados estruturados (JSON-LD) estão presentes em todas as páginas.
- Teste todos os formulários e recursos dinâmicos.
- Execute verificações de Lighthouse e Core Web Vitals -- você quase certamente verá melhorias já que você agora está servindo de uma CDN.
- Configure monitoramento com Vercel Analytics ou sua ferramenta preferida.
Fase 5: Lançamento e Troca de DNS (Semana 6-7)
Faça deploy para Vercel ou Netlify, atualize DNS, e configure monitoramento. Mantenha a instância antiga do WordPress offline mas acessível por 30 dias caso você precise referenciar algo.
Se seu site tem tráfego significativo ou funcionalidade de ecommerce, considere uma integração de CMS headless para gerenciamento de conteúdo e fale com a gente sobre Astro como uma alternativa de frontend para sites com muito conteúdo onde o desempenho de build importa.
Endurecimento de Segurança Pós-Migração
Uma vez que você está na nova stack, aqui está sua lista de verificação de segurança:
- Habilite RLS no Supabase em toda tabela. Sem exceções. Se uma tabela não tem políticas, ela é inacessível (bom padrão) ou completamente aberta (ruim).
- Use variáveis de ambiente para todos os segredos. Vercel e Netlify lidam bem com isso. Nunca faça commit de chaves de API.
- Configure backups de banco de dados Supabase. Recuperação point-in-time está disponível em planos Pro ($25/mês).
- Configure headers de Content Security Policy no seu middleware Next.js.
- Habilite proteção contra DDoS do Vercel (incluído em todos os planos).
- Configure monitoramento de uptime -- usamos Better Uptime, mas Checkly e monitoramento embutido do Vercel também funcionam.
- Audite suas políticas RLS do Supabase trimestralmente. Use o editor SQL do Supabase para testar políticas com diferentes contextos de usuário.
// middleware.ts -- headers de segurança
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const response = NextResponse.next()
response.headers.set('X-Frame-Options', 'DENY')
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
response.headers.set(
'Content-Security-Policy',
"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
)
response.headers.set(
'Permissions-Policy',
'camera=(), microphone=(), geolocation=()'
)
return response
}
Custo Real da Segurança do WordPress vs Migração
Vamos falar sobre dinheiro, porque isso é o que realmente impulsiona decisões.
| Categoria de Custo | WordPress (Anual) | Next.js + Supabase (Anual) |
|---|---|---|
| Hosting | $300-1.200 (WP gerenciado) | $0-240 (Vercel Pro) |
| Plugins de segurança (Wordfence/Sucuri) | $200-500 | $0 (não necessário) |
| SSL/CDN | $0-200 | $0 (incluído) |
| Limpeza de malware (se hackeado) | $500-2.500 por incidente | N/A |
| Tempo de desenvolvedor em patches de segurança | $2.000-5.000 | $500-1.000 |
| Banco de dados (Supabase) | Incluído em hosting | $0-300 (Free tier a Pro) |
| Total | $3.000-9.400 | $500-1.540 |
E isso é antes de você considerar o custo de downtime, perda de confiança do cliente, e possíveis penalidades regulatórias se dados de clientes são comprometidos. Uma única violação reportável sob GDPR pode custar dezenas de milhares em overhead legal e de conformidade.
A migração em si normalmente custa entre $10.000-40.000 dependendo da complexidade do site. Para a maioria dos negócios, isso se paga dentro de 1-2 anos apenas em economia de segurança -- e você obtém um site mais rápido e mais fácil de manter no processo. Confira nossa página de preços para especificidades em projetos de migração.
FAQ
O WordPress é realmente tão inseguro, ou isso é exagerado?
O WordPress core é mantido bem. O problema é que virtualmente ninguém executa apenas core. O ecossistema de plugins é onde 96% das vulnerabilidades vivem, e você não pode rodar um site WordPress útil sem plugins. Não é exagerado -- Sucuri limpou malware de mais de 60.000 sites WordPress em 2024 sozinho. A arquitetura exige que você confie em código PHP de terceiros no seu servidor, e essa confiança é explorada constantemente.
Não posso apenas usar melhores plugins de segurança em vez de migrar?
Plugins de segurança são eles próprios código PHP rodando no seu servidor com acesso profundo ao sistema. Wordfence e Sucuri são bem mantidos, mas são band-aids em um problema arquitetural. Eles também adicionam carga ao servidor, podem conflitar com outros plugins, e tiveram suas próprias vulnerabilidades ao longo dos anos. Você está adicionando complexidade para resolver um problema de complexidade.
Quanto tempo uma migração do WordPress para Next.js normalmente leva?
Para um site comercial padrão (10-50 páginas, blog, formulários de contato), normalmente completamos migrações em 5-7 semanas. Sites de ecommerce com WooCommerce são mais complexos e podem levar 8-14 semanas dependendo do tamanho do catálogo de produtos e funcionalidade customizada. Se você tem um site mais simples, entre em contato conosco e podemos dar um cronograma mais específico.
Vou perder meus rankings de SEO ao migrar do WordPress?
Não, se você fizer certo. Os passos críticos são: preservar todas as estruturas de URL ou configurar redirecionamentos 301 apropriados, manter sua marcação de dados estruturados, manter seu conteúdo intacto, e enviar sitemaps atualizados para o Google Search Console. A maioria dos nossos clientes de migração veem melhorias de ranking dentro de 2-3 meses porque as pontuações de Core Web Vitals melhoram dramaticamente quando você muda para um site estático servido de uma CDN.
E sobre edição de conteúdo? WordPress é fácil para usuários não técnicos.
Essa é uma preocupação legítima. Você tem opções: Supabase com um dashboard administrativo customizado, ou um CMS headless como Sanity, Contentful, ou Payload CMS que oferece uma experiência de edição visual similar ao WordPress. Lidamos com integrações de CMS headless regularmente e podemos recomendar a escolha certa para as necessidades do seu time.
O Supabase é seguro o suficiente para uso em produção?
Supabase roda em infraestrutura AWS com conformidade SOC 2 Type II. O banco de dados subjacente é PostgreSQL, que tem um forte histórico de segurança. Políticas de Row Level Security forçam controle de acesso no nível do banco de dados, o que é na verdade mais seguro que o sistema de permissões baseado em PHP do WordPress. Supabase também oferece recuperação point-in-time, conexões criptografadas, e restrições de rede em planos pagos.
E se meu site WordPress foi hackeado e preciso de ajuda imediata?
Primeiro, coloque o site offline imediatamente para parar mais dano e vazamento de dados. Segundo, preserve evidência forense (dumps de banco de dados, logs de acesso, snapshots do sistema de arquivos). Terceiro, não apenas limpe e coloque de volta -- você provavelmente será reinfectado dentro de semanas. Use o incidente como o catalisador para migrar. Entre em contato com nosso time e podemos ajudar com triagem imediata e planejamento de migração.
Preciso migrar tudo de uma vez, ou posso fazer incrementalmente?
Migração incremental é possível mas adiciona complexidade. Você pode rodar Next.js como o frontend enquanto mantém WordPress como um backend de CMS headless temporariamente, então remova WordPress completamente depois. Porém, isso significa que WordPress ainda está rodando e ainda precisa de manutenção de segurança durante a transição. Para a maioria dos sites, um cutover limpo é mais rápido, mais barato, e elimina risco de segurança mais rapidamente.