En un sitio WordPress pequeño, la seguridad no es un proyecto: es una base que se coloca una vez, correctamente, y de la que se deja de hablar. Tres piezas, media jornada de puesta en marcha, y la práctica totalidad de los ataques automatizados deja de producir efecto. Esta es esa base, en orden de despliegue.
Por qué una base mínima y no una fortaleza
La mayor parte de lo que golpea a un WordPress pequeño es ruido automatizado: robots que solicitan wp-login.php, escaneos de vulnerabilidades conocidas, intentos de enumeración de usuarios mediante la API REST. Ninguno de esos ataques apunta a un sitio en particular: rastrean toda la web. La base descrita a continuación corta ese volumen. El resto — ataque dirigido, fallo inédito en una extensión concreta — no se resuelve con tres líneas de configuración y prácticamente nunca afecta a un sitio de presentación.
El mejor endurecimiento no es el que lo bloquea todo: es el que seguirá instalado y actualizado seis meses después.
Pieza 1 — Wordfence, la capa aplicativa
Wordfence protege más de cinco millones de sitios y su versión gratuita cubre lo esencial: cortafuegos aplicativo, escáner de software malicioso que compara los ficheros del núcleo con los del repositorio oficial, limitación de tasa, protección contra ataques de fuerza bruta y doble autenticación.
Ajustes mínimos tras la instalación:
- Pasar el cortafuegos al modo Extended Protection, que se ejecuta antes que PHP y no como una simple extensión.
- Activar la doble autenticación en todas las cuentas de administrador.
- Activar el bloqueo de enumeración de usuarios y ocultar la versión de WordPress.
- Reducir las alertas por correo a las críticas: un flujo constante de notificaciones acaba sin leerse.
Pieza 2 — Fail2ban, la capa de red
Wordfence actúa a nivel de PHP. Fail2ban actúa antes, a nivel de servidor: lee los registros de Nginx y bloquea la dirección IP en el cortafuegos del sistema en cuanto se repite un patrón de ataque. El atacante deja entonces de consumir recursos de PHP.
# /etc/fail2ban/filter.d/wp-login.conf
[Definition]
failregex = ^<HOST> -.*"POST /wp-login.php
^<HOST> -.*"POST /xmlrpc.php
ignoreregex =# /etc/fail2ban/jail.d/wordpress.conf
[wp-login]
enabled = true
filter = wp-login
logpath = /home/*/logs/nginx/access.log
port = http,https
maxretry = 3
findtime = 3600
bantime = 3600CF-Connecting-IP mediante el módulo RealIP) debe verificarse antes de armar la regla.El filtro se prueba siempre antes de activarlo:
fail2ban-regex /home/misitio/logs/nginx/access.log
/etc/fail2ban/filter.d/wp-login.confPieza 3 — Contraseñas de aplicación
Las contraseñas de aplicación, nativas en WordPress, permiten dar a un script, una integración o una rutina automatizada un identificador revocable distinto de la contraseña principal de la cuenta. Cada integración obtiene la suya; revocarla no afecta a ninguna otra.
De ahí dos reglas de explotación: no reutilizar nunca una contraseña de aplicación entre integraciones y comprobar que ninguna extensión de seguridad las desactiva globalmente — Wordfence ofrece ese ajuste, y activarlo corta silenciosamente todas las integraciones REST del sitio.
Complementos sin coste
| Medida | Efecto |
|---|---|
Cabeceras de seguridad (X-Content-Type-Options, Referrer-Policy, Permissions-Policy) | Reducción de la superficie de ataque en el navegador |
| Desactivación de la edición de ficheros en la administración | Impide modificar código desde una cuenta comprometida |
| Cuentas de administrador nominativas, sin usuario «admin» | Elimina el objetivo por defecto de la fuerza bruta |
| Copias de seguridad cifradas fuera del servidor de producción | La única medida que repara realmente tras un incidente |
Lo que hay que retener
Tres piezas bastan para cubrir casi todo el riesgo real de un sitio pequeño: una capa aplicativa, una capa de red e identificadores revocables para las integraciones. Cualquier dispositivo adicional debe juzgarse por una sola vara: ¿seguirá mantenido dentro de seis meses?
Es la base que despliego en la treintena de sitios que autoalojo, tras CloudPanel y Cloudflare. El incidente que más me costó no fue una intrusión: fue el ajuste de Wordfence que desactiva las contraseñas de aplicación y que cortó todas mis rutinas REST, sin ninguna alerta. — Simon Janvier
