|

Seguridad en WP: seguridad de wp-admin | cambiar la URL de acceso, limitar los intentos de inicio de sesión y XML-RPC

La seguridad de wp-admin son los ajustes que frenan los ataques de fuerza bruta que llegan por el panel de administración y la pantalla de acceso de WordPress. Al revisar los registros de acceso de un servidor Nginx + Apache con varios sitios WordPress, las solicitudes automáticas a xmlrpc.php seguían llegando incluso después de cambiar la URL de acceso, así que también apliqué un límite de velocidad en el servidor.

1️⃣ Por qué atacan wp-admin y wp-login.php

Que la dirección del panel de WordPress sea conocida es un punto débil, pero se puede compensar reforzando la seguridad. Todos los sitios WordPress usan el mismo /wp-admin/ y [wp-login.php], y al abrir /wp-admin/ sin sesión iniciada se pasa a la pantalla de acceso de [wp-login.php].

Los ataques llegan como fuerza bruta, probando una y otra vez usuarios y contraseñas en esta pantalla de acceso. Por eso, en la seguridad de wp-admin, frenar los intentos de acceso va antes que ocultar la dirección.

Dos entradas al acceso de WordPress
Acceso desde el navegador
/wp-admin/
Sin sesión, redirige a la pantalla de acceso (302)
wp-login.php
Pantalla de acceso · usuario y contraseña
Apps · solicitudes automáticas
xmlrpc.php
Envía usuario y contraseña en una solicitud POST sin pantalla de acceso
No pasa por la pantalla de acceso
system.multicall prueba varias contraseñas en una solicitud · la dirección no cambia aunque cambies la URL de acceso
Misma comprobación de usuario y contraseña
Ambas entradas comprueban la cuenta con la misma función de autenticación de WordPress
Los ataques de fuerza bruta entran por la entrada que esté abierta. Cambiar la URL de acceso solo afecta a la entrada de arriba, así que xmlrpc.php hay que cerrarlo o limitar sus solicitudes por separado.

2️⃣ Efecto y límites de cambiar la URL de acceso

Al cambiar la URL de acceso con un plugin de seguridad, el [wp-login.php] predeterminado devuelve un 404, y los ataques automáticos que insisten en la dirección por defecto no llegan a la pantalla de acceso. La nueva dirección hay que comunicarla aparte a quien tenga una cuenta de administrador.

🧭 Entradas al acceso de WordPress
Diagrama explicativo
⬜ Sin plugin
🛡️ Hide My WP
🚪 Entrada de acceso
/wp-login.php · /wp-admin/Misma dirección en todos los WordPress
Pantalla de acceso404
/newloginDirección cambiada · solo la conocen los administradores
Pantalla de acceso
POST /xmlrpc.phpComprueba la contraseña sin pantalla de acceso
Responde a la comprobación de contraseñaDesactivado 405
Medido en un sitio de prueba · solicitudes sin sesión
→
🤖 Ataques automáticos
Entradas donde se pueden probar contraseñas en una dirección conocida
2
1
Ninguna
Sin plugin, las contraseñas se pueden probar en dos sitios: el mismo [wp-login.php] de todos los WordPress y [xmlrpc.php], que comprueba contraseñas sin pantalla de acceso.
Al cambiar la URL de acceso, [wp-login.php] y /wp-admin/ devuelven 404, pero [xmlrpc.php] sigue respondiendo si el usuario y la contraseña son correctos.
Si además desactivas XML-RPC, las solicitudes de acceso a [xmlrpc.php] terminan con una respuesta de que el servicio XML-RPC está desactivado, y ya no se pueden probar contraseñas en una dirección conocida.

Este método requiere poco trabajo, pero si olvidas la nueva dirección no podrás entrar al panel y tendrás que renombrar la carpeta de ese plugin por FTP o con un gestor de archivos para desactivarlo. En un sitio que administran varias personas, conviene anotar la dirección en un solo lugar.

3️⃣ Limitar los intentos de acceso y la verificación en dos pasos

Aunque cambies la URL de acceso, si la nueva dirección se conoce, los intentos de adivinar contraseñas continúan. El núcleo de WordPress no limita los inicios de sesión fallidos, así que por muchas contraseñas erróneas que se introduzcan, vuelve a abrirse la misma pantalla.

🧭 Limitar intentos de acceso y verificación en dos pasos
Diagrama explicativo
⬜ Sin plugin
🛡️ Plugin de seguridad
🔑 Accesos desde la misma IP
1.ºContraseña incorrecta
Otra vez la pantalla de accesoQuedan 3
2.ºContraseña incorrecta
Otra vez la pantalla de accesoQuedan 2
3.ºContraseña incorrecta
Otra vez la pantalla de accesoQueda 1
4.ºContraseña incorrecta
Otra vez la pantalla de accesoBloqueo de 20 min
5.ºBloqueadoContraseña incorrectaAcceso · solicitudes XML-RPC
Otra vez la pantalla de accesoxmlrpc.php también 403
Introducir contraseñaContraseña correcta
Pantalla del código
Authentication Code6 dígitos de la app de autenticación · cambia cada 30 s
Administración
Atacante que solo conoce la contraseñaNo conoce el código
Se queda en la pantalla del código
Medido en un sitio de prueba · solicitudes seguidas desde la misma IP
→
🤖 Ataques automáticos
¿Se pueden seguir probando contraseñas?
Sin límite
Bloqueo al 4.º
Se detiene en el código
Sin plugin, aunque se introduzca una contraseña incorrecta seis veces desde la misma IP, cada vez vuelve a abrirse la misma pantalla de acceso.
Con el límite de intentos activo, cada fallo muestra los intentos que quedan, y al 4.º fallo esa IP no puede iniciar sesión durante 20 minutos. Mientras dura el bloqueo, las solicitudes a xmlrpc.php también terminan en 403.
Con la verificación en dos pasos activa, aunque la contraseña sea correcta, el panel solo se abre tras introducir el [Authentication Code] de 6 dígitos que la app de autenticación genera cada 30 segundos.

Un plugin de límite de intentos bloquea durante un tiempo la IP que supera el número permitido, y la verificación en dos pasos pide además un código de la app de autenticación del móvil aunque la contraseña sea correcta. Al activarla, guarda también los códigos de respaldo por si pierdes el móvil.

4️⃣ Cerrar xmlrpc.php

[xmlrpc.php] es una segunda entrada que recibe usuario y contraseña sin pasar por la pantalla de acceso, y con el método [system.multicall] puede probar varias contraseñas en una sola solicitud.

Los registros de acceso de un servidor Nginx + Apache con varios sitios WordPress mostraron 2.250 solicitudes POST a [xmlrpc.php] entre las 0:00 y las 9:50 del 13 de octubre. Llegaron desde 22 IP y su User-Agent se hacía pasar por Jetpack y WordPress.com.

Si no usas la app móvil de WordPress ni Jetpack, bloquea las solicitudes a [xmlrpc.php] en la configuración de Nginx o usa el ajuste para desactivar XML-RPC de un plugin de seguridad.

# Dentro del bloque server — rechazar solicitudes a xmlrpc.php
location = /xmlrpc.php {
    deny all;
}

Con este ajuste, las solicitudes GET y POST a [xmlrpc.php] terminan todas en 403 sin llegar a PHP. La opción de desactivar XML-RPC de un plugin de seguridad solo rechaza las solicitudes que requieren acceso y el archivo sigue respondiendo, así que para reducir también las ejecuciones de PHP conviene bloquearlo en Nginx.

5️⃣ Bloquear en el servidor: restricción de IP para administrar y límite de velocidad

Si solo administras desde una IP fija, permitir [wp-login.php] y /wp-admin/ únicamente a esa IP en Nginx es el método más fiable. No sirve si la IP de tu casa u oficina cambia a menudo.

Bloquear todo /wp-admin/ puede parecer suficiente, pero funciones del lado del visitante como la búsqueda o el carrito suelen enviar solicitudes a [admin-ajax.php], así que ese archivo debe quedar abierto.

# Dentro del bloque server — encima del location de PHP
location = /wp-login.php {
    allow 203.0.113.10;   # IP fija desde la que administras
    deny all;
    # Copia aquí debajo la configuración del location de PHP
}

Si abres [wp-login.php] desde una IP distinta de la permitida, sale un 403; desde la IP permitida se abre la pantalla de acceso. Dentro del location tienes que copiar tal cual la configuración de PHP del sitio (fastcgi_pass, etc.) para que la pantalla de acceso funcione con normalidad.

Si no puedes fijar la IP, puedes aplicar un límite de velocidad a las solicitudes PHP de visitantes sin sesión; el proceso de limitarlas a 30 por minuto para que las solicitudes automáticas no acaparen los recursos del servidor se explica en aviso de php-fpm max_children (artículo aparte).

# Bloque http — contar por IP solo las solicitudes sin cookie de sesión
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 del location de PHP
limit_req zone=php_anon burst=60 nodelay;
limit_req_status 429;

Cuando una IP sin sesión envía solicitudes PHP seguidas, se atienden hasta la 61.ª y después se devuelve 429; las solicitudes con cookie de sesión no cuentan. Si la caché de páginas responde sin pasar por PHP, la navegación normal de los visitantes no llega a este límite.

ℹ️ Aviso de afiliados
El contenido de este sitio incluye enlaces de afiliado. Cuando un visitante compra un producto o servicio a través de uno de ellos, el sitio recibe una comisión del vendedor. El importe que paga el comprador(baja durante las promociones ↓)no aumenta. Los precios, descuentos y existencias publicados corresponden al momento de redacción y pueden variar, así que confírmalos con el vendedor antes de comprar. Los productos se eligen y evalúan con criterios propios, y las comisiones no influyen en el orden ni en el contenido de las reseñas.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Demuestra que eres humano: 5   +   2   =