HTTP Strict Transport Security (HSTS) es un mecanismo de seguridad que indica a los navegadores que se comuniquen con tu sitio web exclusivamente por HTTPS. Una vez que el navegador recibe la cabecera HSTS desde tu servidor, convertirá automáticamente cualquier petición HTTP a HTTPS durante el periodo especificado en la cabecera, incluso si el usuario escribe explícitamente http:// en la barra de direcciones o hace clic en un enlace HTTP antiguo.
Esto puede sonar como una pequeña comodidad, pero soluciona un problema real y peligroso. Vamos a ver exactamente por qué existe HSTS, cómo funciona en la práctica y qué necesitas saber como propietario de un sitio WordPress.
Cómo funcionan los ataques SSL Stripping sin HSTS
Imagina que un visitante abre su portátil en una cafetería y escribe tusitio.com en el navegador. Sin HSTS, el navegador envía primero una petición HTTP en texto plano a tu servidor. Tu servidor responde entonces con una redirección 301 a https://tusitio.com. Sin embargo, esa petición HTTP inicial está completamente sin cifrar. Viaja por la red WiFi de la cafetería como texto plano.
Un atacante en la misma red puede interceptar esa primera petición sin cifrar usando una técnica llamada SSL stripping. El atacante actúa como un proxy: mantiene una conexión HTTPS con tu servidor real pero entrega una versión HTTP en texto plano a la víctima. Desde la perspectiva del visitante, el sitio parece normal (la mayoría de la gente no comprueba el icono del candado). Mientras tanto, el atacante puede leer todo: credenciales de inicio de sesión, envíos de formularios, cookies de sesión, datos de tarjetas de crédito.
No se trata de un ataque teórico. Herramientas como sslstrip están disponibles públicamente desde 2009, y el SSL stripping sigue siendo uno de los ataques más prácticos en redes WiFi públicas. HSTS existe específicamente para cerrar esa brecha.
Cómo protege HSTS tu sitio WordPress
Cuando tu servidor envía la siguiente cabecera de respuesta:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadEl navegador almacena esta instrucción internamente. Durante los siguientes 31.536.000 segundos (un año), nunca intentará una conexión HTTP a tu dominio. Si algo intenta cargar un recurso por HTTP, el navegador lo reescribe a HTTPS localmente antes incluso de que la petición salga del dispositivo. No hay ninguna petición sin cifrar que un atacante pueda interceptar.
Esta protección funciona a nivel del navegador, lo que constituye la ventaja clave. No se necesita ninguna redirección. Nunca se envía una petición sin cifrar. El navegador simplemente se niega a usar HTTP para tu dominio.
Directivas de la cabecera HSTS explicadas
La cabecera HSTS acepta tres directivas, y cada una cumple un propósito específico:
max-age: el tiempo en segundos que el navegador debe recordar para forzar HTTPS. Valores comunes son86400(1 día, útil para pruebas iniciales),2592000(30 días, un buen punto de partida) y31536000(1 año, el valor recomendado para producción). Si lo estableces a cero, el navegador dejará de aplicar HSTS para tu dominio inmediatamente.includeSubDomains: extiende la política HSTS a todos los subdominios. Esto significa quecdn.tusitio.com,mail.tusitio.comy cualquier otro subdominio también serán forzados a HTTPS. Ten cuidado con esta directiva: si algún subdominio no admite HTTPS, quedará inaccesible una vez activada.preload: una señal de que quieres que tu dominio se añada a las listas de precarga de los navegadores. Más sobre esto a continuación.
El problema de la primera visita y las listas HSTS Preload
HSTS tiene una limitación fundamental: el navegador necesita recibir la cabecera al menos una vez antes de poder hacerla cumplir. En la primera visita, antes de que el navegador haya visto nunca tu cabecera HSTS, la petición HTTP inicial sigue siendo vulnerable a la interceptación. Esto se conoce como el "problema de la primera visita" o "problema de bootstrap".
La lista HSTS preload soluciona esto. Es una lista de dominios que está integrada directamente en el navegador (Chrome, Firefox, Safari y Edge comparten la misma lista). Si tu dominio está en la lista de precarga, el navegador fuerza HTTPS desde la primera conexión, incluso si el usuario nunca ha visitado tu sitio antes.
Para que tu dominio entre en la lista de precarga, debes cumplir todos los siguientes requisitos:
- Servir un certificado HTTPS válido en tu dominio raíz
- Redirigir todo el tráfico HTTP a HTTPS en el mismo host
- Servir la cabecera HSTS en el dominio raíz con un
max-agede al menos31536000(un año) - Incluir la directiva
includeSubDomains - Incluir la directiva
preload - Todos los subdominios deben admitir HTTPS
Puedes enviar tu dominio en hstspreload.org. Ten en cuenta que entrar en la lista lleva semanas o meses (se distribuye con las actualizaciones del navegador), y salir de ella es igual de lento. Asegúrate de que tu configuración HTTPS es sólida antes de enviarlo.
Valores comunes de max-age y estrategia de despliegue recomendada
Es tentador saltar directamente a un max-age de un año, pero un despliegue gradual es más seguro, especialmente para sitios con varios subdominios o configuraciones complejas:
max-age=300(5 minutos): úsalo durante las pruebas iniciales. Si algo va mal, los visitantes solo quedarán bloqueados en HTTPS durante cinco minutos.max-age=86400(1 día): un buen siguiente paso una vez confirmado que HTTPS funciona correctamente.max-age=2592000(30 días): pasa a este valor tras una o dos semanas de operación estable.max-age=31536000(1 año): el valor recomendado para producción. También es el mínimo requerido para la lista de precarga.
Configurar HSTS en un sitio WordPress
WordPress por sí solo no envía la cabecera HSTS por defecto. Tienes varias opciones para añadirla:
El enfoque más fiable es añadir la cabecera a nivel de servidor. En Apache, añade esto a tu archivo .htaccess o a la configuración del virtual host:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"Para Nginx, añade esto dentro de tu bloque server:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;Si no tienes acceso a la configuración del servidor (algo común en hosting compartido), puedes añadir la cabecera mediante PHP en el functions.php de tu tema o a través de un must-use plugin:
add_action('send_headers', function() {
header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
});El enfoque a nivel de servidor es preferible porque se aplica a todas las respuestas, incluidos los archivos estáticos y las páginas de error, no solo a las páginas generadas por PHP.
Varios plugins de seguridad para WordPress también ofrecen configuración de HSTS desde sus paneles de ajustes, lo que puede resultar cómodo si prefieres un enfoque con interfaz gráfica.
Errores comunes con HSTS en WordPress
Antes de habilitar HSTS, comprueba bien algunos puntos:
- Contenido mixto: asegúrate de que todos los recursos (imágenes, scripts, hojas de estilo, fuentes) se cargan por HTTPS. HSTS fuerza la conexión principal a HTTPS, pero si tu contenido sigue referenciando URLs HTTP, los navegadores bloquearán esos recursos.
- Renovación del certificado SSL: una vez activado HSTS, un certificado caducado hará que tu sitio sea completamente inaccesible (en lugar de mostrar un aviso que se pueda omitir). Configura la renovación automática del certificado con Let's Encrypt o tu proveedor de certificados.
- Preparación de los subdominios: si usas
includeSubDomains, cada subdominio necesita un certificado HTTPS válido. Un subdominio de staging en HTTP dejará de funcionar. - Configuración del CDN: si usas un CDN como Cloudflare, asegúrate de que HSTS está configurado de forma coherente. Cloudflare ofrece sus propios ajustes de HSTS que pueden anular las cabeceras de tu servidor.
Qué comprueba InspectWP
InspectWP analiza si tu sitio WordPress envía la cabecera de respuesta Strict-Transport-Security. El informe evalúa el valor de max-age, comprueba la presencia de la directiva includeSubDomains y marca la cabecera como ausente si no está presente. Una cabecera HSTS adecuada con un valor alto de max-age (al menos 6 meses o un año) y la directiva includeSubDomains es recomendable para todo sitio WordPress que funcione sobre HTTPS, lo cual debería ser hoy en día el caso de todos.