HSTS y cabeceras de seguridad para su sitio web
Con cada página, su servidor web envía headers: líneas breves con instrucciones para el navegador. En parte determinan con qué nivel de seguridad trata el navegador su sitio. Aquí puede leer qué es HSTS, qué otros headers de seguridad existen y cómo configurarlos y probarlos.
Primero, su sitio debe tener un certificado que funcione y redirigir a los visitantes a https. Puede consultarlo en Activar y renovar un certificado SSL y resolver problemas y Redirigir obligatoriamente a los visitantes a https.
¿Qué hace HSTS?
La redirección a https tiene un punto débil: la primera solicitud por http todavía se envía sin cifrar. Alguien en la misma red, por ejemplo en una wifi pública, puede interceptar esa solicitud. HSTS (HTTP Strict Transport Security) lo soluciona. Su sitio envía a través de https este header:
Strict-Transport-Security: max-age=31536000
El navegador recuerda entonces que solo puede abrir su sitio a través de https. Si más adelante un visitante escribe http://, el navegador lo convierte por sí mismo en https, antes de que se envíe nada por la red. El navegador ignora un header HSTS que llegue por http normal.
| Elemento | Significado |
|---|---|
max-age | Durante cuánto tiempo lo recuerda el navegador, en segundos. La prueba de internet.nl considera suficiente un mínimo de un año (31536000). |
includeSubDomains | Se aplica también a todos los subdominios, como shop.sudominio.nl y mail.sudominio.nl. |
preload | Solicita la inclusión en la lista integrada en los navegadores (hstspreload.org). Así, incluso la primerísima visita queda protegida. Para ello se necesitan, entre otras cosas, un año, includeSubDomains y https en todos los subdominios. Salir de la lista tarda mucho tiempo. |
max-age=0 | Borra de nuevo la instrucción recordada, en la siguiente visita a través de https. |
includeSubDomains, esto se aplica también a cada subdominio, como una antigua página de una cámara o impresora sin certificado. Por eso, hágalo de forma progresiva: empiece con un max-age corto, por ejemplo un día (86400), compruebe que todo funciona y auméntelo por etapas hasta un año.HSTS en WebOké
En la mayoría de nuestros servidores, el servidor web envía HSTS de forma predeterminada para cada sitio web que se abre a través de https: Strict-Transport-Security: max-age=31536000. Es decir, un año, sin includeSubDomains y sin preload. No tiene que hacer nada para ello. En unos pocos servidores no está activado de forma predeterminada; allí debe activarlo usted mismo. Puede ver si su sitio ya envía HSTS y con qué max-age en las herramientas para desarrolladores de su navegador o en la prueba de internet.nl (consulte más abajo).
El interruptor de HSTS en DirectAdmin
En DirectAdmin, vaya a Domain Setup y haga clic en su nombre de dominio. Si Secure SSL está activado, verá en HSTS el interruptor Enable HTTP Strict Transport Security. A continuación, haga clic en Save para guardar. Puede consultar el procedimiento paso a paso en Redirigir siempre a los visitantes a https.
Si su sitio ya envía HSTS, no necesita el interruptor. Actívelo solo si su sitio todavía no envía HSTS. Configure HSTS en un único lugar: en DirectAdmin o en .htaccess, no en ambos. Si el navegador recibe dos headers HSTS, solo utiliza el primero.
Los demás headers de seguridad
| Header | Contra qué protege | Valor para empezar |
|---|---|---|
X-Content-Type-Options | El navegador intenta adivinar por sí mismo qué es un archivo, de modo que una "imagen" subida puede ejecutarse como script. | nosniff (el único valor válido) |
Content-Security-Policy: frame-ancestors o X-Frame-Options | Clickjacking: otro sitio carga su página de forma invisible en un marco, de modo que los visitantes hacen clic en sus botones sin darse cuenta. | frame-ancestors 'self', o el header más antiguo X-Frame-Options: SAMEORIGIN |
Referrer-Policy | Al hacer clic hacia otro sitio, el navegador envía la dirección de la página anterior, a veces con un término de búsqueda o un número de pedido incluido. | strict-origin-when-cross-origin, o de forma más estricta same-origin o no-referrer. Internet.nl solo considera correctos los valores estrictos. |
Permissions-Policy | Determina qué funciones del navegador pueden utilizar su página y los marcos incrustados, como la cámara, el micrófono y la ubicación. | camera=(), microphone=(), geolocation=() desactiva esas tres. Si su sitio utiliza alguna de esas funciones, omítala. |
Content-Security-Policy (completa) | Limita desde qué ubicaciones pueden cargarse scripts, estilos e imágenes. Esto dificulta mucho la inserción de scripts maliciosos (XSS). | Configuración a medida para cada sitio. Evite unsafe-inline, unsafe-eval y los comodines. |
Configuración en .htaccess
Coloque estas líneas al principio del archivo .htaccess en la carpeta public_html de su dominio. Haga primero una copia del archivo.
<IfModule mod_headers.c> Header always set X-Content-Type-Options "nosniff" Header always set Content-Security-Policy "frame-ancestors 'self'" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()" # Alleen als je site nog geen HSTS meestuurt (zie hierboven): # Header always set Strict-Transport-Security "max-age=31536000" </IfModule>
Añada includeSubDomains solo cuando esté seguro de que todos los subdominios tienen https. Si utiliza WordPress, también puede configurar los headers con un plugin. Elija un plugin conocido que siga actualizándose y configure cada header en un único lugar: en el plugin o en .htaccess.
Content-Security-Policy-Report-Only. Este no bloquea nada, pero muestra en la consola del navegador lo que se bloquearía. En caso de duda, deje esto en manos de su desarrollador web o empiece solo con frame-ancestors.En un VPS con nginx o Caddy
En un VPS no utiliza DirectAdmin y a menudo tampoco .htaccess. En ese caso, configure los headers en los ajustes de su servidor web. Ninguno de los dos envía HSTS ni estos headers de forma automática.
nginx: en el bloque server del puerto 443:
add_header Strict-Transport-Security "max-age=31536000" always; add_header X-Content-Type-Options "nosniff" always; add_header Content-Security-Policy "frame-ancestors 'self'" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always;
Con always, los headers se envían también en las páginas de error. Atención: si un bloque location contiene su propio add_header, las reglas del bloque server dejan de aplicarse a esa location. En ese caso, repítalas allí o colóquelas en un archivo aparte que inserte en todas partes con include. Pruebe la configuración con nginx -t y cárguela con systemctl reload nginx.
Caddy: en el bloque de su sitio en el Caddyfile:
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
Content-Security-Policy "frame-ancestors 'self'"
Referrer-Policy "strict-origin-when-cross-origin"
}
Cargue el cambio con systemctl reload caddy. Para crear un sitio con nginx o Caddy, consulte nginx con un certificado de Let's Encrypt y Caddy: un sitio web con https automático en la guía de VPS.
Pruebas
- Internet.nl: introduzca su dominio en la prueba de sitios web de internet.nl.
- Su navegador: abra su sitio, pulse F12 (o elija Inspeccionar), vaya a la pestaña Red, vuelva a cargar la página y haga clic en la primera solicitud. En Encabezados de respuesta (Response Headers) verá todo lo que envía su servidor.
- La línea de comandos:
curl -sI https://sudominio.es/muestra los headers.
Después de cada cambio, compruebe que su sitio, sus formularios y su página de pago siguen funcionando. Además, mantenga actualizados su CMS, sus plugins y sus temas. Consulte Proteger wp-login.php de WordPress.
Más información
- MDN: Strict-Transport-Security (en inglés)
- MDN: Content-Security-Policy (en inglés)
- MDN: Permissions-Policy (en inglés)
- Lista de precarga HSTS (en inglés)
¿Quiere aprender más? Siga el curso gratuito Seguridad en línea para empresarios, lección 4.2 Su sitio web: https, HSTS y headers de seguridad, o el curso gratuito de WordPress, lección 7.4 Reforzar el sitio: permisos, headers y plugins de seguridad.
