Segurança WP: segurança do wp-admin | trocar a URL de login, limitar logins, XML-RPC

Aviso de afiliados v3.1
Aviso de afiliados v3.2 (somente celular)

A segurança do wp-admin reúne as configurações que barram ataques de força bruta contra o painel de administração e a tela de login do WordPress. Ao analisar os logs de acesso de um servidor Nginx + Apache que hospeda vários sites WordPress, vi que as requisições automáticas para o xmlrpc.php continuavam chegando mesmo depois da troca da URL de login, e por isso também apliquei um limite de taxa no nível do servidor.

1️⃣ Por que o wp-admin e o wp-login.php são atacados

O fato de o endereço de administração do WordPress ser conhecido é uma fraqueza, mas dá para compensar isso reforçando a segurança. Todo site WordPress usa o mesmo /wp-admin/ e o mesmo [wp-login.php] e, se você abrir o /wp-admin/ sem estar logado, vai para a tela de login do [wp-login.php].

Os ataques chegam como força bruta: nomes de usuário e senhas são testados repetidamente nessa tela de login. Por isso, na segurança do wp-admin, barrar as tentativas de login vem antes de esconder o endereço.

As duas entradas do login do WordPress
Acesso pelo navegador
/wp-admin/
Sem login, vai para a tela de login (302)
wp-login.php
Tela de login · digitar nome de usuário e senha
Apps · requisições automáticas
xmlrpc.php
Nome de usuário e senha vão numa requisição POST, sem tela de login
Não passa pela tela de login
Com system.multicall, várias senhas numa só requisição · o endereço não muda nem trocando a URL de login
Mesma verificação de usuário e senha
As duas entradas verificam a conta com a mesma função de autenticação do WordPress
Os ataques de força bruta entram pela entrada que estiver aberta. Trocar a URL de login vale só para a entrada de cima, por isso o xmlrpc.php precisa ser fechado à parte ou ter o número de requisições limitado.

2️⃣ Efeitos e limites de trocar a URL de login

Ao trocar a URL de login com um plugin de segurança, o [wp-login.php] padrão passa a devolver um erro 404, e os ataques automáticos que insistem no endereço padrão nem chegam à tela de login. O novo endereço precisa ser informado à parte a quem tem conta de administrador.

🧭 Entradas do login do WordPress
Diagrama explicativo
⬜ Sem plugin
🛡️ Hide My WP
🚪 Entrada de login
/wp-login.php · /wp-admin/O mesmo endereço em todo WordPress
Tela de login404
/newloginEndereço trocado · só os administradores sabem
Tela de login
POST /xmlrpc.phpVerifica a senha sem tela de login
Responde à verificação de senhaDesativado 405
Medido num site de teste · requisições sem login
→
🤖 Ataques automáticos
Entradas onde dá para testar senhas num endereço conhecido
2
1
Nenhuma
Sem plugin, as senhas podem ser testadas em dois lugares: no [wp-login.php], igual em todo site WordPress, e no [xmlrpc.php], que verifica a senha sem tela de login.
Com a URL de login trocada, o [wp-login.php] e o /wp-admin/ devolvem 404, mas o [xmlrpc.php] continua respondendo se o nome de usuário e a senha estão corretos.
Desativando também o XML-RPC, as requisições de login ao [xmlrpc.php] terminam com a resposta de que o serviço XML-RPC está desativado, e não dá mais para testar senhas num endereço conhecido.

Esse método dá pouco trabalho, mas, se você esquecer o novo endereço, não consegue entrar no painel e precisa desativar o plugin renomeando a pasta dele por FTP ou pelo gerenciador de arquivos. Em sites administrados por várias pessoas, o certo é anotar o endereço num só lugar.

3️⃣ Limitar tentativas de login e autenticação de dois fatores

Mesmo com a URL de login trocada, se o novo endereço vazar, as tentativas de adivinhar a senha continuam. O núcleo do WordPress não limita as falhas de login: não importa quantas vezes você erre a senha, a mesma tela de login abre de novo.

🧭 Limitar tentativas de login e autenticação de dois fatores
Diagrama explicativo
⬜ Sem plugin
🛡️ Plugin de segurança
🔑 Logins do mesmo IP
1ªSenha errada
De volta à tela de loginRestam 3
2ªSenha errada
De volta à tela de loginRestam 2
3ªSenha errada
De volta à tela de loginResta 1
4ªSenha errada
De volta à tela de loginBloqueado por 20 min
5ªBloqueadoSenha erradaLogin · requisições XML-RPC
De volta à tela de loginxmlrpc.php também 403
Digitar a senhaSenha correta
Tela de código
Authentication Code6 dígitos do app autenticador · muda a cada 30 s
Painel de administração
Atacante que só descobriu a senhaNão sabe o código
Para na tela do código
Medido num site de teste · requisições seguidas do mesmo IP
→
🤖 Ataques automáticos
Dá para continuar testando senhas?
Sem limite
Bloqueado na 4ª
Para no código
Sem plugin, mesmo errando a senha seis vezes do mesmo IP, a mesma tela de login abre de novo a cada vez.
Com o limite de tentativas ativado, cada erro mostra quantas tentativas restam, e no 4º erro aquele IP fica 20 minutos sem conseguir fazer login. Durante o bloqueio, as requisições ao xmlrpc.php também terminam em 403.
Com a autenticação de dois fatores ativada, mesmo com a senha certa o painel só abre depois de digitar o [Authentication Code] de 6 dígitos que o app autenticador gera a cada 30 segundos.

Um plugin de limite de tentativas bloqueia por um tempo o IP que passa do número permitido, e a autenticação de dois fatores pede, mesmo com a senha certa, um código do app autenticador no celular. Ao ativar a autenticação de dois fatores, guarde também os códigos de backup para o caso de perder o celular.

4️⃣ Fechar o xmlrpc.php

O [xmlrpc.php] é uma segunda entrada que recebe nome de usuário e senha sem passar pela tela de login, e com o método [system.multicall] dá para testar várias senhas numa só requisição.

Nos logs de acesso de um servidor Nginx + Apache que hospeda vários sites WordPress, chegaram ao [xmlrpc.php] 2.250 requisições POST em 13 de outubro, entre 0h e 9h50. Elas vieram de 22 IPs, e o User-Agent se passava por Jetpack e WordPress.com.

Se você não usa o app móvel do WordPress nem o Jetpack, bloqueie as requisições ao [xmlrpc.php] na configuração do Nginx ou use a opção de desativar o XML-RPC do plugin de segurança.

# Dentro do bloco server — recusar requisições ao xmlrpc.php
location = /xmlrpc.php {
    deny all;
}

Com essa configuração, todas as requisições GET e POST ao [xmlrpc.php] terminam em 403 sem chegar ao PHP. A opção de desativar o XML-RPC do plugin de segurança recusa só as requisições que exigem login e o arquivo continua respondendo, então, para reduzir também as execuções de PHP, o melhor é bloquear no Nginx.

5️⃣ Bloquear no servidor: restringir o acesso de administração por IP e limite de taxa

Se você administra o site só a partir de um IP fixo, o método mais seguro é liberar o [wp-login.php] e o /wp-admin/ no Nginx apenas para esse IP. Não serve para quem tem o IP de casa ou do escritório mudando com frequência.

Bloquear o /wp-admin/ inteiro pode parecer suficiente, mas recursos da parte pública, como a busca ou o carrinho, muitas vezes enviam requisições ao [admin-ajax.php], então esse arquivo precisa ficar liberado.

# Dentro do bloco server — acima do location que processa o PHP
location = /wp-login.php {
    allow 203.0.113.10;   # Seu IP fixo de administração
    deny all;
    # Abaixo, copie as configurações do location que processa o PHP
}

Abrindo o [wp-login.php] de um IP que não seja o definido, aparece um 403; do IP definido, a tela de login abre. Dentro do location, é preciso copiar as configurações de PHP do site (fastcgi_pass etc.) do jeito que estão para a tela de login funcionar normalmente.

Se não dá para fixar o IP, existe a opção de aplicar um limite de taxa às requisições PHP de visitantes não logados; o processo de limitar a 30 por minuto, para que requisições automáticas não tomem os recursos do servidor, está no artigo Aviso de php-fpm max_children dedicado ao assunto.

# Bloco http — contar por IP só as requisições sem cookie de login
map $http_cookie $php_anon_key {
    default                 $binary_remote_addr;
    "~*wordpress_logged_in" "";
}
limit_req_zone $php_anon_key zone=php_anon:10m rate=30r/m;

# Dentro do location que processa o PHP
limit_req zone=php_anon burst=60 nodelay;
limit_req_status 429;

Quando um único IP sem login envia requisições PHP em sequência, até a 61ª são processadas e, depois disso, volta um 429; requisições com cookie de login não entram na conta. Se o cache de página responde sem passar pelo PHP, a navegação dos visitantes comuns não esbarra nesse limite.

ℹ️ Aviso de afiliados
O conteúdo deste site contém links de afiliados. Quando um visitante compra um produto ou serviço por meio de um desses links, o site recebe uma comissão do vendedor. O valor que o comprador paga (em promoções, ele diminui ↓) não aumenta por causa disso. Preços, descontos e informações de estoque valem para o momento em que o texto foi escrito e podem ter mudado, por isso confirme com o vendedor antes de comprar. Os produtos são escolhidos e avaliados por critérios próprios, e o recebimento de comissão não influencia a ordem de apresentação nem o conteúdo das avaliações.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Demonstre sua humanidade: 4   +   5   =