Cabeceras de seguridad de un sitio web: qué son y qué pedir
Seis cabeceras HTTP que indican al navegador cómo proteger a las personas en su sitio web. Qué hace cada una, cómo comprobar las suyas y un encargo listo para su desarrollador.
Cuando alguien abre su sitio web, el servidor envía a su navegador la página y, además, unas cuantas líneas de instrucciones que el visitante nunca ve. Son las cabeceras HTTP. Algunas indican al navegador cómo proteger a las personas en su sitio, por ejemplo que se conecte solo mediante una conexión cifrada o que no ejecute scripts de direcciones desconocidas.
Las cabeceras no cuestan nada y se configuran una vez. Aun así, muchos sitios no las tienen, porque la configuración predeterminada del servidor a menudo las omite. Si una revisión de seguridad le ha dicho que a su sitio «le faltan cabeceras de seguridad», este artículo explica qué significa y le da un texto listo para enviar a su desarrollador.
Cómo ver lo que envía su sitio
La forma más rápida es en su propio navegador. En Chrome, Edge o Firefox, abra su sitio web y pulse F12 (Cmd+Opción+I en un Mac). Se abre un panel de herramientas para desarrolladores. Elija la pestaña Red y recargue la página. Arriba de la lista verá una entrada con la dirección de su sitio. Haga clic en ella y busque la sección Encabezados de respuesta.
No haga caso del resto del panel. Solo busca los nombres que se describen a continuación.
La segunda forma es un comprobador gratuito de cabeceras, como nuestra comprobación de cabeceras de seguridad (en inglés) o el HTTP Observatory que Mozilla mantiene en su sitio MDN. Escribe su dirección y obtiene una lista de cabeceras con una nota. Tome la nota como una pista, no como un veredicto.
Strict-Transport-Security: siempre HTTPS
Esta cabecera, HSTS para abreviar, le dice al navegador: durante un periodo determinado, conéctate a este dominio solo por HTTPS. Protege a los visitantes en una red wifi pública, por ejemplo, donde alguien podría intentar interceptar esa primera conexión sin cifrar.
Strict-Transport-Security: max-age=31536000; includeSubDomains
max-age es un tiempo en segundos, aquí un año. Y aquí está la trampa. Cuando el navegador recuerda esta cabecera, un visitante que se encuentre con un problema de certificado ya no puede saltarse la advertencia. includeSubDomains abarca todos los subdominios, así que si tienda.sudominio.com o un test.sudominio.com olvidado no tienen HTTPS que funcione, dejarán de abrirse.
Por eso se empieza con un periodo corto, por ejemplo un día, y se amplía cuando todo funciona. No añada preload sin pensarlo bien, porque es muy difícil de deshacer.
Content-Security-Policy: una lista de orígenes de confianza
Es la cabecera más potente y la única que de verdad puede romper su sitio. CSP es una lista de los lugares desde los que sus páginas pueden cargar scripts, estilos, imágenes y fuentes. Si un atacante consigue inyectar un script malicioso, por ejemplo a través de un formulario vulnerable, el navegador se niega a ejecutar código de una dirección que no está en la lista.
El problema es que el sitio típico de una pequeña empresa depende de muchos servicios externos: Google Analytics o Tag Manager, el píxel de Facebook, una ventana de chat, un mapa, fuentes web, vídeos de YouTube, una pasarela de pago. Si deja uno fuera de la lista, esa parte del sitio deja de funcionar. El chat desaparece o los clientes no pueden pagar.
Por eso CSP debe empezar en un modo de prueba, con el nombre Content-Security-Policy-Report-Only. En este modo el navegador no bloquea nada y solo informa de lo que habría bloqueado. Su desarrollador reúne esos informes durante una o dos semanas de tráfico normal, completa la lista y solo entonces pasa la cabecera al modo de aplicación. Así puede quedar:
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://www.googletagmanager.com; img-src 'self' data: https:
Es solo un ejemplo. La lista real depende de lo que use su sitio. En sitios con muchos plugins, una CSP completa puede ser difícil de configurar. Aun así, una política parcial es mejor que ninguna.
Cuatro cabeceras más cortas
X-Content-Type-Options: nosniff indica al navegador que se fíe del tipo de archivo que declara el servidor en lugar de adivinarlo. Sin ella, un archivo subido como texto o imagen podría tratarse en algunas situaciones como un script. Rara vez rompe algo, siempre que el servidor declare bien los tipos de archivo.
X-Frame-Options: SAMEORIGIN impide que otros sitios web muestren el suyo dentro de un marco. Protege contra el clickjacking: alguien carga su página de forma invisible debajo de la suya y engaña al visitante para que haga clic en algo que no ve, como un botón de pedido. El equivalente moderno es frame-ancestors 'self' en CSP, y puede configurar ambos. Si su sitio debe aparecer en un marco en otro lugar, por ejemplo un calendario de reservas en el sitio de un socio, su desarrollador tiene que añadir la dirección de ese socio a frame-ancestors.
Referrer-Policy: strict-origin-when-cross-origin hace que, cuando alguien pulsa un enlace de su sitio a otro, ese sitio solo sepa de qué dominio viene, no de qué página. Importa cuando las direcciones de sus páginas contienen algo privado, como un número de pedido. Los navegadores modernos ya se comportan así por defecto, pero configurar la cabecera de forma explícita no cuesta nada.
Permissions-Policy: camera=(), microphone=(), geolocation=() declara que su sitio no usa la cámara, el micrófono ni la ubicación. Así, ni siquiera un script inyectado puede pedir al visitante acceso a ellos. Si su sitio tiene una herramienta de «encuentre su oficina más cercana» o consultas por vídeo, su desarrollador dejará activada la función que necesite.
Un encargo listo para su desarrollador
Puede copiar el texto siguiente y enviarlo tal cual, con su propia dirección.
Por favor, añade cabeceras de seguridad a sudominio.com,
en todas las páginas, incluidos el panel de administración y la tienda:
Strict-Transport-Security: max-age=86400; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy-Report-Only: una política que se ajuste
a los scripts y servicios que usamos realmente
Antes de activar includeSubDomains, comprueba que
todos los subdominios funcionan con HTTPS. Si no se rompe
nada en una semana, sube max-age a 31536000.
CSP primero en modo Report-Only, durante una o dos semanas.
Después envíame la lista de infracciones registradas
y decidimos juntos cuándo pasar al modo de aplicación.
Dime también dónde se han configurado las cabeceras
(configuración del servidor, .htaccess, Cloudflare o un plugin).
Esa última petición importa. Las cabeceras pueden configurarse en varios sitios a la vez, y dos ajustes distintos para la misma cabecera son una forma fácil de crear confusión la próxima vez que algo cambie. Cuando estén activas, vuelva a comprobar las cabeceras y recorra las partes que más importan: el formulario de contacto, el carrito, el pago, el chat, el mapa y el inicio de sesión en el panel de administración.
Lo que las cabeceras no arreglan
Las cabeceras son una segunda línea de defensa. No arreglan un plugin desactualizado ni una contraseña débil. Limitan el daño cuando otra cosa falla.
Tampoco persiga a cualquier precio la nota máxima en un comprobador. Un sitio con cinco cabeceras sencillas y pagos que funcionan está mucho mejor que uno con una CSP perfecta que impide a los clientes hacer pedidos.
Una última cosa: si una herramienta le dice que añada la cabecera X-XSS-Protection, no lo trate como algo urgente. La mayoría de los navegadores modernos la ignoran, y la recomendación actual es omitirla o ponerla en 0.