secaudit.eu
Proteção

Enumeração de utilizadores no WordPress: REST API e autores

Enumeração de utilizadores no WordPress: teste que nomes de login o seu site revela via REST API, URLs de autor, sitemaps e erros de login, e aplique correções seguras.

Por , AngelForce OÜ 7 min de leitura

Também em: English Deutsch Français Español Italiano Polski Türkçe

Numa instalação WordPress predefinida, qualquer pessoa consegue, em regra, descobrir os seus nomes de login em menos de um minuto. A enumeração de utilizadores no WordPress funciona através de cinco ou seis canais incorporados: a REST API, os redirecionamentos ?author=1, os URLs dos arquivos de autor, o sitemap de utilizadores, as mensagens de erro de login e, nalguns casos, os feeds e os dados oEmbed. Este artigo mostra como testar cada canal no seu próprio site e como fechá-lo com uma correção pontual que não estraga o editor de blocos.

O que é a enumeração de utilizadores no WordPress e quanto importa

Enumerar utilizadores é recolher nomes de conta válidos de um site. Um atacante que saiba que mkeller existe pode gastar todas as tentativas de palavra-passe, e todas as palavras-passe divulgadas noutras fugas de dados, numa conta real, em vez de adivinhar admin, info e test.

Convém ser claro quanto ao que ocultar nomes alcança: é um obstáculo menor, não uma proteção. O que impede a tomada de uma conta é a autenticação de dois fatores e a limitação de tentativas de login, por isso configure-as primeiro (autenticação de dois fatores no WordPress, proteção contra força bruta). Depois feche as fugas abaixo, por esta ordem: testar, corrigir, voltar a testar.

Diagrama: cinco canais que revelam nomes de login do WordPress, cada um com a sua correção
Onde os nomes de login são revelados e a correção pontual para cada canal

Teste o seu próprio site: seis sítios onde os nomes de utilizador são revelados

Execute estes testes apenas em sites que lhe pertençam ou que giva. Teste sem sessão iniciada, a partir de um terminal ou de uma janela privada do navegador, porque as sessões autenticadas veem mais. Substitua example.com pelo seu domínio.

  1. REST API. O núcleo lista os utilizadores que publicaram conteúdo. Veja o campo slug, que é o slug do autor e costuma ser idêntico ao login.
curl -s https://example.com/wp-json/wp/v2/users | grep -o '"slug":"[^"]*"'
curl -s "https://example.com/?rest_route=/wp/v2/users" | grep -o '"slug":"[^"]*"'
  1. Redirecionamentos por ID de autor. O WordPress redireciona ?author=N para o URL amigável do autor. Experimente 1, 2, 3 e assim sucessivamente.
curl -sI "https://example.com/?author=1" | grep -i '^location'
  1. HTML do tema. Ligações de autor nos artigos e classes CSS como comment-author-<slug> nos comentários de utilizadores registados.
curl -s https://example.com/a-post/ | grep -oE '/author/[^/"]+/|comment-author-[a-z0-9-]+' | sort -u
  1. Sitemap de utilizadores. Abra https://example.com/wp-sitemap-users-1.xml no navegador.
  1. Erros de login. Em wp-login.php, introduza um nome de utilizador inventado e, depois, um real com a palavra-passe errada. Se as mensagens forem diferentes, o formulário confirma contas válidas. O formulário de recuperação de palavra-passe comporta-se da mesma forma. Limite-se a duas ou três tentativas, para que a sua própria limitação de tentativas não o bloqueie.
  1. Feeds e oEmbed. O feed mostra os nomes públicos em dc:creator. O endpoint oEmbed devolve author_name e author_url, e esse URL contém o slug do autor.
curl -s https://example.com/feed/ | grep -i 'dc:creator'
curl -s "https://example.com/wp-json/oembed/1.0/embed?url=https://example.com/a-post/"
CanalTesteO que revela
Utilizadores REST/wp-json/wp/v2/usersSlug, nome, ID
Redirecionamento de autor/?author=1Slug em Location
HTML do temaMarcação de artigos e comentáriosSlug
Sitemap de utilizadores/wp-sitemap-users-1.xmlURLs de autor com slug
Erros de loginDesconhecido vs palavra-passe erradaLogins válidos
Feed / oEmbeddc:creator, author_urlNome público, slug

O OWASP Web Security Testing Guide trata o teste de enumeração de contas com mais profundidade, caso queira um método estruturado.

Restringir o endpoint REST de utilizadores apenas para visitantes anónimos

Atue apenas sobre a rota de utilizadores e apenas em pedidos sem utilizador autenticado. O editor de blocos usa /wp/v2/users no seletor de autor, e as aplicações móveis e muitos plugins chamam-no com autenticação. Se remover a rota para toda a gente, deixam de funcionar.

Crie o ficheiro wp-content/mu-plugins/user-enumeration.php. Os plugins de uso obrigatório (must-use) carregam automaticamente e não podem ser desativados a partir do painel de administração. O filtro rest_endpoints permite retirar rotas antes de serem servidas:

<?php
/**
 * Plugin Name: Limit user enumeration
 */

add_filter( 'rest_endpoints', function ( $endpoints ) {
    if ( is_user_logged_in() ) {
        return $endpoints;
    }
    unset( $endpoints['/wp/v2/users'] );
    unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
    return $endpoints;
} );

Volte a executar o teste com curl. Deverá agora receber o erro rest_no_route com estado 404. Depois inicie sessão, abra um artigo no editor e confirme que o painel de autor continua a listar utilizadores.

Se tiver um front-end headless ou uma aplicação que leia dados de autor de forma anónima, este excerto vai estragá-los. Nesse caso, exponha apenas os campos de que precisa através de um endpoint personalizado. A referência da REST API para utilizadores lista o que o endpoint devolve.

Impedir os redirecionamentos por ID de autor e decidir se precisa de arquivos de autor

Quando alguém pede /?author=2, o WordPress identifica o utilizador e o seu redirecionamento canónico envia o visitante para /author/<slug>/. O cabeçalho Location denuncia o slug, e um script percorre os IDs de 1 a 50 em segundos.

Acrescente isto a seguir ao primeiro excerto, no mesmo mu-plugin. Corre antes do redirecionamento canónico e responde a pedidos anónimos com o parâmetro author com um simples 404, pelo que nenhum cabeçalho Location revela o slug:

add_action( 'template_redirect', function () {
    if ( is_user_logged_in() ) {
        return;
    }
    if ( isset( $_GET['author'] ) ) {
        wp_die( 'Not found.', '', array( 'response' => 404 ) );
    }
}, 1 );

Volte a testar com curl -sI "https://example.com/?author=1". Deverá agora obter um 404 e nenhum cabeçalho Location.

Num blogue empresarial com um só autor, ou num site sem páginas públicas de autor, vá mais longe e desative os arquivos de autor. A maioria dos plugins de SEO tem uma opção para isso, e alguns temas também. Com honestidade quanto ao limite: se o seu tema imprime ligações "por <autor>" em cada artigo, o slug continua no HTML. É disso que tratam as duas secções seguintes.

Remover o sitemap de utilizadores onde ninguém precisa dele

Os sitemaps do núcleo, introduzidos no WordPress 5.5, incluem um fornecedor de utilizadores que lista todos os arquivos de autor. Poucos sites empresariais ganham alguma coisa com isso. O filtro wp_sitemaps_add_provider remove-o:

add_filter( 'wp_sitemaps_add_provider', function ( $provider, $name ) {
    if ( 'users' === $name ) {
        return false;
    }
    return $provider;
}, 10, 2 );

Abra novamente /wp-sitemap-users-1.xml; deverá agora devolver um 404. Se um plugin de SEO substituir os sitemaps do núcleo, este filtro não tem efeito sobre o resultado desse plugin. Procure nas definições de sitemap do plugin um sitemap de autores e desative-o aí.

Diferenciar nomes públicos e slugs de autor dos nomes de login

Em Utilizadores > Perfil, defina uma Alcunha e escolha-a em Mostrar publicamente como. Isto cobre os feeds, o author_name do oEmbed e as linhas "por".

Eis a armadilha. O slug do autor (user_nicename) é gerado a partir do login quando a conta é criada e não muda quando altera o nome público. Os seus artigos podem dizer "Equipa editorial" enquanto o URL continua a ser /author/mkeller/. Corrija com o WP-CLI:

wp db export before-nicename.sql
wp user list --fields=ID,user_login,user_nicename,display_name
wp user update 2 --user_nicename=editorial-team

Use letras minúsculas, algarismos e hífenes, e mantenha cada slug único. Os URLs de autor antigos mudam, por isso conte com alguns 404 ou acrescente um redirecionamento se essas páginas tinham tráfego.

Nas contas novas, evite admin, o nome da empresa e o nome do domínio como logins. Se contas antigas ou partilhadas fizerem parte do problema, limpe-as primeiro: segurança das funções de utilizador no WordPress.

Mensagens de erro de login genéricas

O filtro login_errors substitui as mensagens apresentadas no ecrã de login por um único texto neutro:

add_filter( 'login_errors', function () {
    return '<strong>Error:</strong> The login details are incorrect.';
} );

Isto substitui também mensagens úteis, como o aviso de campo vazio, pelo que os seus utilizadores recebem menos orientação. E também não torna o site opaco. O formulário de recuperação de palavra-passe continua a comportar-se de forma diferente para contas válidas, já que uma conta real conduz ao ecrã "verifique o seu email". Alguns plugins acrescentam os seus próprios formulários de login, e a página A Minha Conta do WooCommerce tem mensagens próprias. Encare isto como uma questão de coerência, não como um controlo forte.

O que ocultar nomes de utilizador não impede

Os atacantes experimentam nomes e endereços de email comuns quer o seu site os revele, quer não, e o WordPress aceita o endereço de email como login. O credential stuffing, que reutiliza pares de utilizador e palavra-passe de outras fugas de dados, não precisa de enumeração nenhuma. Uma lista de utilizadores perfeitamente oculta não serve de nada contra uma palavra-passe reutilizada.

Assim, a ordem para o site de uma pequena empresa é:

  1. Autenticação de dois fatores para todos os administradores e editores (guia de configuração).
  2. Limitação de tentativas de login e uma decisão sobre o XML-RPC (proteção contra força bruta).
  3. As correções de enumeração acima, testadas com os comandos curl.
  4. Incluir o resultado na sua revisão regular (lista de verificação de segurança do WordPress).

O plugin Security Audit & Compliance da secaudit.eu inclui limitação de tentativas de login e limitação de pedidos REST anónimos, e a sua análise de hardening reporta achados de configuração para que veja o que ainda está em aberto → secaudit.eu

O seu próximo passo: execute hoje os seis testes deste artigo no seu site, registe os resultados e corrija os canais que mostrem um nome de login real.

FAQ

Bloquear /wp/v2/users estraga o editor de blocos?

Não, se o restringir a pedidos anónimos, como no excerto acima. O editor envia pedidos autenticados, pelo que o seletor de autor continua a funcionar. Remover a rota para utilizadores autenticados é que o estragaria.

O "admin" continua a ser um risco se tiver 2FA?

Muito menos. Com 2FA, uma palavra-passe adivinhada não basta, por si só, para entrar. Mas o admin atrai tentativas constantes, que enchem os registos e podem desencadear bloqueios, pelo que continua a valer a pena substituí-lo.

Devo mudar o próprio login e como?

O WordPress não tem nenhum botão para alterar um nome de login. Crie um novo administrador com um login neutro e 2FA, inicie sessão com ele, depois elimine a conta antiga e atribua o conteúdo à nova quando o WordPress perguntar. Mantenha sempre um administrador operacional. Os pormenores estão em segurança das funções de utilizador no WordPress.

Verifique o seu site

O Security Audit & Compliance é o plugin WordPress da secaudit.eu: procura malware, spam oculto, ficheiros do núcleo alterados e código vulnerável, e associa as conclusões ao art. 32.º do RGPD, ao art. 21.º da NIS2 e ao OWASP Top 10.

Ver o que o plugin verifica
Melike Görel

Melike Görel escreve os guias da secaudit.eu sobre segurança do WordPress e conformidade com as regras da UE para a AngelForce OÜ, a empresa de software de Taline responsável pela secaudit.eu.

Elaborado com apoio de IA e verificado antes da publicação. Este artigo é informação geral e não constitui aconselhamento jurídico.