Login seguro no WordPress: 2FA, passkeys e proteção contra força bruta
PT-PT

Login seguro no WordPress: 2FA, passkeys e proteção contra força bruta

Última verificação: 1 de maio de 2026
13min de leitura
Guia

A maioria dos incidentes “WordPress hackeado” para os quais sou chamado não são zero-days. São credential stuffing contra admin com uma password vazada num dump de fórum de 2019, a bater em /wp-login.php a partir de um pool rotativo de proxies residenciais. O dono do site culpa o WordPress; a causa real é que a segurança do login foi tratada como um único interruptor (“password forte”) em vez de quatro ou cinco controlos em camadas. O CNCS (Centro Nacional de Cibersegurança) repete o mesmo padrão nos relatórios trimestrais que publica para PMEs portuguesas.

Este guia percorre as camadas que configuro em sites cliente reais: higiene de nome de utilizador, 2FA com escape WP-CLI funcional, rate-limiting no Cloudflare e no servidor, é o caminho de recuperação para o dia em que alguém perde o telemóvel ou faz commit de uma application password num repositório público. Para sites sujeitos à CNPD, a obrigação de notificação de violação em 72h do Art. 33 do RGPD transforma cada um destes controlos em obrigação documentada, não recomendação.

#Como os logins WordPress são realmente atacados

Três padrões cobrem quase tudo o que vejo em logs de acesso:

  • Força bruta sobre /wp-login.php: bots fazem POST a wp-login.php com log=admin&pwd=.... Distribuído por centenas de IPs, frequentemente a partir de redes proxy residenciais como sucessores do 911.re. Rate limits por IP única não os param.
  • Credential stuffing: o mesmo endpoint, mas as credenciais vêm de corpus públicos de violações (“Collection #1” a #5, RockYou2024). O nome de utilizador é o e-mail ou login vazado. Pode ser mitigado com uma verificação contra haveibeenpwned ao definir a password.
  • Amplificação XML-RPC system.multicall: um POST a /xmlrpc.php com um corpo system.multicall permite testar centenas de passwords num único pedido HTTP, contornando rate limits por pedido. Se não usar a app móvel do WP nem o Jetpack, bloqueie xmlrpc.php no servidor.
  • Enumeração de utilizadores via REST API: ?rest_route=/wp/v2/users e /wp-json/wp/v2/users devolvem o slug real de cada autor publicado. Esse slug é o login. Combinado com os dumps anteriores, o atacante já tem metade do par credencial.

Hosts portugueses como Amen.pt e PTisp ativam ModSecurity por defeito com regras anti-brute-force, mas nenhum cobre os quatro vetores acima sem configuração adicional.

#Parte 1: a vulnerabilidade “admin” (enumeração de utilizadores)

Por que razão os hackers amam o nome de utilizador “admin”? Porque reduz o trabalho deles a metade.

Num ataque de força bruta, o atacante precisa de adivinhar duas coisas: o nome de utilizador é a password. Se usar “admin”, deu-lhes 50% das credenciais de graça.

#O problema do “ID 1”

Por defeito, o primeiro utilizador criado no WordPress tem o ID 1. Os hackers frequentemente analisam o-seu-site.com/?author=1. Se o seu site redirecionar para o-seu-site.com/author/admin/, revelou o seu nome de utilizador a cada atacante.

#A solução: remoção cirúrgica

Não pode simplesmente “renomear” um nome de utilizador no WordPress. Deve realizar um transplante que preserva todo o conteúdo enquanto elimina a conta vulnerável.

  1. Criar um novo Comandante:

    • Vá a Utilizadores -> Adicionar novo.
    • Nome de utilizador: Algo obscuro (por exemplo, Obsidian_Eagle_88). Evite usar o seu nome real ou qualquer coisa adivinhável a partir do seu domínio.
    • E-mail: O seu endereço de e-mail seguro.
    • Função: Administrador.
  2. Iniciar sessão como o novo Comandante: Use uma janela de navegação privada.

  3. Eliminar o antigo utilizador:

    • Vá a Utilizadores.
    • Passé o rato sobre “admin” e clique em Eliminar.
    • PASSO CRÍTICO: O WordPress perguntará: “O que deve ser feito com o conteúdo deste utilizador?”
    • Selecione: “Atribuir todo o conteúdo a:” -> [Selecioné o seu novo utilizador].

Bloquear enumeração de utilizadores via REST API:

// Bloquear enumeração de utilizadores via REST API
add_filter('rest_endpoints', function($endpoints) {
    if (isset($endpoints['/wp/v2/users'])) {
        unset($endpoints['/wp/v2/users']);
    }
    return $endpoints;
});

#Parte 2: 2FA é o problema do bloqueio

Uma password sozinha é um único ponto de falha. Com 2FA, o atacante precisa da password mais o segundo fator; com passkeys (mais à frente) já não há um segredo partilhado para ser vazado.

A parte que a maioria dos guias omite é o modo de falha: o que acontece quando o admin perde o telemóvel, sai da empresa, ou o segredo TOTP foi configurado num dispositivo entretanto apagado. Precisa de um escape WP-CLI documentado antes de impor 2FA, não depois.

# EmergencIA: desativar 2FA para um utilizador bloqueado (Two-Factor / WP 2FA)
wp user meta delete <user_id> _two_factor_enabled_providers
wp user meta delete <user_id> _two_factor_provider
wp user meta delete <user_id> _two_factor_options

# Ou listar o que esta configurado para saber o que remover
wp user meta list <user_id> --keys=_two_factor_enabled_providers,_two_factor_provider

Execute via SSH no servidor. Se o admin já não tiver SSH, o caminho de recuperação é o terminal do painel de alojamento ou uma query SQL contra wp_usermeta. Documente isto antes de precisar. Para sites sob CNPD, uma hora perdida à procura do procedimento come um terço do prazo legal de 72h.

#Os níveis de 2FA

1. Códigos SMS (Depreciado - não usar) O 2FA baseado em SMS é considerado inseguro. Os ataques de SIM swapping permitem que os hackers sequestrem números de telefone.

2. Apps TOTP (Segurança padrão) Apps de password de uso único baseadas no tempo (TOTP) como Google Authenticator, Authy ou Ente Auth geram códigos que mudam a cada 30 segundos:

  • Códigos gerados localmente no dispositivo
  • Sem transmissão de rede do segredo
  • Funciona offline

3. Chaves de segurança de hardware (O padrão irrefutável) Chaves de segurança físicas como YubiKey usam criptografia de chave pública para fornecer autenticação que não pode ser phishada.

#Auditar as application passwords

O core do WordPress traz application passwords (tokens de 24 caracteres para clientes REST API e XML-RPC). Saltam o 2FA por design. Já vi estás acabar em ficheiros .env carregados em repositórios públicos do GitHub é em relatórios de crash de apps móveis publicados em fóruns de suporte. Audite trimestralmente:

wp user application-password list <user_id>
wp user application-password delete <user_id> <uuid>

Se não usar a REST API para escritas autenticadas, desative completamente as application passwords com add_filter( 'wp_is_application_passwords_available', '__return_false' ); num mu-plugin.

#Parte 3: login sem password com Passkeys

Em 2026, estamos a avançar completamente para além das passwords. Os Passkeys representam o futuro da autenticação, utilizando a biometria no seu dispositivo (TouchID, FaceID, Windows Hello).

#Como funcionam os Passkeys

Os Passkeys usam o padrão WebAuthn para criar pares de chaves criptográficas:

  1. Registo: O seu dispositivo cria uma chave privada (armazenada com segurança) é uma chave pública (enviada para o servidor)
  2. Autenticação: O servidor envia um desafio; o seu dispositivo assina-o com a chave privada
  3. Verificação: O servidor verifica a assinatura com a chave pública armazenada

#Parte 4: rate-limiting de wp-login.php é xmlrpc.php

Mesmo que o 2FA bloqueie a tomada de controlo real, uma força bruta sem rate limit continua a queimar workers PHP-FPM é ligações MySQL. Em alojamento partilhado (frequente em sites portugueses pequenos é médios) pode derrubar o site sem nunca quebrar uma password. Quer rate limits em três camadas, nesta ordem de eficácIA: edge (Cloudflare), servidor (Nginx ou fail2ban), aplicação (plugin).

#Camada 0: regra de rate-limiting no Cloudflare

Se o site estiver atrás do Cloudflare (incluído no plano gratuito), esta é a regra com maior alavancagem. Dashboard → Security → WAF → Rate limiting rules:

  • Field: URI Path
  • Operator: equals
  • Value: /wp-login.php
  • When: 5 pedidos / 1 minuto da mesma IP
  • Then: Managed Challenge (ou Block durante 1 hora)

Adicione uma segunda regra para /xmlrpc.php se o mantiver ativo. A vantagem sobre o fail2ban: pára os pedidos no edge, antes de chegarem à origem.

#Camada 2: o CAPTCHA (Cloudflare Turnstile)

O Google reCAPTCHA é irritante e pode afetar a acessibilidade. O Cloudflare Turnstile é a alternativa moderna.

Por que razão o Cloudflare Turnstile?

  • Invisível: A maioria dos utilizadores nunca vê um desafio
  • Foco na privacidade: Nenhum dado pessoal enviado a terceiros
  • Acessibilidade: Funciona com leitores de ecrã
  • Gratuito: Nível gratuito generoso para a maioria dos sites

#Camada 3: nível do servidor (Fail2Ban)

O Fail2Ban analisa os logs do servidor e bané automaticamente os endereços IP que mostram comportamento malicioso.

Instalação no Ubuntu/Debian:

sudo apt update
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Configuração específica do WordPress:

Uma subtileza que a maioria dos tutoriais apanha mal: um POST falhado a wp-login.php devolve HTTP 200 (a página é re-renderizada com erro), é um bem sucedido devolve 302 (redirect para wp-admin). Logo, fazer match apenas sobre 200 apanha tanto as tentativas falhadas legítimas como os logins bem sucedidos, o que significa que se bane a si mesmo se errar a password três vezes. O padrão abaixo combina o 200 com o volumé de força bruta dentro do findtime do jail:

Criar /etc/fail2ban/filter.d/wordpress.conf:

[Definition]
failregex = ^<HOST> .* "POST /wp-login\.php.*" 200
            ^<HOST> .* "POST /xmlrpc\.php.*" 200
ignoreregex = ^<HOST> .* "POST /wp-login\.php.*" 302

Configuração Nginx para limitação de taxa:

# Definição da zona de limite de taxa (no bloco http)
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

# Aplicar ao wp-login.php
location = /wp-login.php {
    limit_req zone=login burst=5 nodelay;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

#Parte 5: monitorização é alertas de login

Não pode proteger o que não consegue ver. Use monitorização ao nível do servidor ou externa em vez de plugins de segurança:

  • Monitorize /var/log/nginx/access.log para logins falhados e pedidos wp-login.php
  • Use fail2ban para alertar sobre padrões de força bruta
  • Rotacione é arquive logs durante pelo menos 90 dias

#Parte 6: procedimentos de resposta a incidentes

Fase 1: deteção e identificação

  1. Reconhecer o incidente: atividade de administrador inesperada, ficheiros não familiares
  2. Avaliar o âmbito: Quais as contas comprometidas? Que ficheiros foram modificados?

Fase 2: contenção

  1. Alterar todas as passwords de administrador imediatamente
  2. Forçar o logout de todos os utilizadores (eliminar sessões WordPress)
  3. Bloquear endereços IP suspeitos ao nível da firewall

Fase 3: erradicação

  1. Restaurar ficheiros de núcleo WordPress a partir de fonte oficial
  2. Reinstalar todos os plugins a partir de WordPress.org
  3. Analisar a base de dados à procura de injeções maliciosas

Fase 4: recuperação

  1. Restaurar a partir de backup limpo, se disponível
  2. Verificar a integridade de todos os ficheiros restaurados
  3. Reativar o site com monitorização melhorada

#Parte 7: desativar a enumeração de utilizadores

Método Nginx:

# Bloquear enumeração de autores
if ($args ~* "author=([0-9]*)") {
    return 403;
}

# Bloquear enumeração de utilizadores via REST API
location ~* /wp-json/wp/v2/users {
    deny all;
    return 403;
}

#Parte 8: hardening nas bordas

#Limitar wp-admin a IPs conhecidas

Se a sua equipa trabalha a partir de um pequeno conjunto de IPs estáticos (escritório, VPN), uma allowlist CIDR sobre /wp-admin/ remove a superfície de ataque pública por completo. Tudo fora da allowlist recebe 403 antes do WordPress carregar. O trade-off é real: admins em viagem, freelancers em wifi de hotel, é acesso de emergência via telemóvel ficam bloqueados. Use só se tiver uma VPN documentada com uptime fiável.

location ^~ /wp-admin/ {
    allow 203.0.113.0/24;     # escritório
    allow 198.51.100.42/32;   # VPN
    deny all;
    # ...config fastcgi existenté
}
location = /wp-login.php {
    allow 203.0.113.0/24;
    allow 198.51.100.42/32;
    deny all;
}

Para sites atrás do Cloudflare, faça-o com uma regra WAF custom sobre http.request.uri.path matches "^/wp-(admin|login)" é not ip.src in {203.0.113.0/24}.

#Renomear wp-login.php

Mover o URL de login é obscuridade, não segurança. Reduz o tráfego de bots simples nos logs (útil para sinal-ruído) mas um atacante determinado faz scrape ao source de qualquer página. Trate isto como filtro de ruído, nunca como camada.

#Desativar a edição de ficheiros no admin

Duas constantes em wp-config.php fecham o caminho de escalada pós-comprometimento mais comum: um atacante com acesso admin a editar PHP de tema/plugin a partir do painel.

define( 'DISALLOW_FILE_EDIT', true );  // esconde Aparência > Editor de ficheiros do tema
define( 'DISALLOW_FILE_MODS', true );  // bloqueia também install/atualizações de plugins/temas

DISALLOW_FILE_MODS é agressivo porque parte as atualizações de um clique; use só em sites em que o código é deployado por CI é as atualizações correm via WP-CLI.

#Web Application Firewall

Um WAF filtra tráfego malicioso antes de chegar à instalação WordPress:

  • Cloudflare WAF: o plano gratuito inclui Managed Rules para WordPress; o plano Pro acrescenta OWASP CRS no paranoia level 1
  • ModSecurity + OWASP CRS: opção ao nível do servidor (Amen.pt é PTisp já o ativam por defeito). Paranoia level 1 é a baseline prática; PL2+ gera demasiados falsos positivos no Gutenberg
  • Sucuri: WAF premium com virtual patches específicos para WordPress

#SSL/TLS para páginas de login

Garanta que todo o site usa HTTPS, especialmente as páginas de login:

  1. Instalar um certificado SSL (Let’s Encrypt fornece certificados gratuitos)
  2. Forçar redirects HTTPS na configuração do servidor web
  3. Ativar HTTP Strict Transport Security (HSTS)
  4. Usar cookies seguros para a autenticação WordPress

#O que configuro realmente num site cliente

Não é uma checklist genérica. É a ordem de trabalho específica que corro ao endurecer um login WordPress de raiz:

  1. Eliminar o utilizador admin, reatribuir conteúdo, ajustar nickname é display_name do admin sobreviventé para que o slug não revele o login.
  2. Bloquear /wp-json/wp/v2/users é ?rest_route=/wp/v2/users para pedidos não autenticados via filtro rest_endpoints mostrado antes.
  3. Impor 2FA para todos os papéis administrator é editor, com TOTP por defeito é um runbook de recuperação wp user meta delete documentado no gestor de passwords da equipa.
  4. Auditar wp user application-password list para cada admin; eliminar tudo com mais de 90 dias ou não reconhecido.
  5. Adicionar uma regra de rate-limit Cloudflare sobre /wp-login.php (5/min, Managed Challenge) é uma segunda regra sobre /xmlrpc.php se não estiver bloqueado de raiz.
  6. Instalar fail2ban com o filtro wp-login que distingue 200 (falhado) de 302 (sucesso) para que utilizadores bloqueados não sejam banidos por engano.
  7. Definir DISALLOW_FILE_EDIT em wp-config.php. Adicionar DISALLOW_FILE_MODS apenas se a equipa fizer deploy via CI.
  8. Forçar HTTPS, HSTS com preload, é Set-Cookie: Secure; HttpOnly; SameSite=Lax para wordpress_logged_in_*.
  9. Confirmar que wp-config.php tem salts únicos (wp config shuffle-salts), que o utilizador da BD só tem os privilégios que o WordPress precisa (sem GRANT ALL), é que o acesso à base de dados está vinculado a localhost.

A segurança do login são quatro ou cinco controlos em camadas, não um. Salte uma camada é as outras ainda seguram; salte três é volta a depender só da password.


Reaudite as application passwords, os contadores de bans do fail2ban, é o runbook de recuperação de 2FA todos os trimestres. A maioria dos sites que herdo de outros operadores tem uma das três coisas desviada: uma app password antiga de um ex-colaborador, um fail2ban que não bane nada há 6 meses porque o caminho do log mudou, ou um setup de 2FA que ninguém sabe contornar quando o telemóvel do admin morre. Se o site cair sob notificação CNPD de 72h, este runbook não é opcional, é prova de diligência.

Saiba mais sobre serviços de segurança WordPress na WPPoland. Atualizado: 28 de janeiro de 2026

Próximo passo

Transforme o artigo numa implementação real

Este bloco reforça a ligação interna e conduz o leitor para o passo seguinte mais útil dentro da arquitetura do site.

A autenticação de dois fatores é realmente necessária para pequenos websites? #
Sim. Os atacantes usam ferramentas automatizadas que analisam toda a internet à procura de sites WordPress, independentemente do tamanho ou tráfego. Os sites pequenos são frequentemente visados especificamente porque é menos provável que tenham segurança robusta.
O que devo fazer se perder o acesso ao meu dispositivo 2FA? #
Gere e guarde sempre códigos de backup ao configurar 2FA. Guarde-os no seu gestor de passwords ou num local físico seguro. Se perder ambos o dispositivo 2FA é os códigos de backup, precisará de acesso à base de dados para desativar o 2FA manualmente.
Posso usar a mesma chave de hardware para múltiplos sites WordPress? #
Sim. As chaves de hardware como o YubiKey podem ser registadas em serviços ilimitados. Cada registo cria um par de chaves único, pelo que comprometer um site não afeta os outros.
Com que frequência devo alterar a minha password WordPress? #
Com 2FA ativado, a rotação de passwords é menos crítica. Concentre-se em usar uma password forte e única guardada num gestor de passwords. Altere as passwords imediatamente se suspeitar de comprometimento.
Os plugins de segurança abrandam o meu website? #
Não recomendamos a instalação de plugins de segurança. A segurança é construída ao nível do servidor: fail2ban, WAF (por exemplo, Cloudflare), passwords fortes, 2FA via alojamento ou soluções mínimas, e backups regulares.
Esconder o wp-login.php é suficiente para parar ataques de força bruta? #
Não. Mudar o URL de login é segurança por obscuridade. Ajuda a reduzir ataques automatizados, mas não impede atacantes determinados. Combine sempre com limitação de taxa, 2FA e passwords fortes.

Precisa de FAQ adaptado ao setor e mercado? Criamos uma versão alinhada com os seus objetivos de negócio.

Fale connosco

Artigos Relacionados

O guia técnico de 2500+ palavras para proteger o seu login WordPress. 2FA, Passkeys, Fail2Ban, alterar URL de login, CAPTCHA e segurança de nível militar.
segurança

Segurança logowania WordPress

O guia técnico de 2500+ palavras para proteger o seu login WordPress. 2FA, Passkeys, Fail2Ban, alterar URL de login, CAPTCHA e segurança de nível militar.

Elimine palavras-passe completamente com autenticação biométrica. Aprenda como implementar passkeys FIDO2/WebAuthn no WordPress para o método de login mais seguro disponível.
segurança

Passkeys para WordPress

Elimine palavras-passe completamente com autenticação biométrica. Aprenda como implementar passkeys FIDO2/WebAuthn no WordPress para o método de login mais seguro disponível.

Lista prática de constantes wp-config, regras Cloudflare e decisões de schema que mexem com TTFB, conformidade CNPD e ranking de lojas portuguesas.
wordpress

Hardening, desempenho e SEO no WordPress: o que move a agulha em 2026

Lista prática de constantes wp-config, regras Cloudflare e decisões de schema que mexem com TTFB, conformidade CNPD e ranking de lojas portuguesas.