Deberías usar encabezados HTTP Strict Transport Security (HSTS) en tu servidor Node.js
Raphael Mun
29 de diciembre de 2022
0 minutos de lecturaEn la mayoría de los sitios web y las aplicaciones, el uso de encabezados HTTP relacionados con la seguridad ya es una práctica estándar. Los sitios web usan encabezados en las solicitudes y respuestas HTTP para transmitir información sobre una página o los datos enviados mediante el protocolo HTTP. Por ejemplo, pueden incluir un encabezado Content-Encoding para indicar que el contenido es un archivo ZIP comprimido, o un encabezado Location para especificar una URL de redireccionamiento.
Entre los muchos encabezados de seguridad disponibles que los navegadores web modernos usan para proteger a los usuarios, uno de los más importantes es el encabezado HTTP Strict Transport Security (HSTS). El encabezado HSTS que proporciona un sitio web le indica al navegador que use el protocolo HTTPS en cada visita posterior.
Sin embargo, pese a su utilidad, su fácil implementación y la compatibilidad con prácticamente todos los navegadores, solo alrededor del 25 % de las respuestas HTTP móviles y el 28 % de las de escritorio incluyen encabezados HSTS.
Veamos a fondo los encabezados HSTS para descubrir cómo afectan la seguridad web y por qué deberíamos usarlos en Node.js. Después, aprenderemos a habilitar HSTS en un servidor Node.js.
¿Por qué habilitar HSTS?
Las conexiones HTTPS son seguras porque cifran y descifran los paquetes de datos transmitidos mediante certificados SSL/TLS, que pueden verificar autoridades de certificación (CA) reconocidas. Por lo tanto, solo la computadora del usuario y el servidor pueden leer los paquetes de datos transmitidos, sin importar quién intercepte el tráfico de red.
Las conexiones HTTP habituales no están cifradas, por lo que cualquiera que acceda a los datos puede leerlos. Entre esos destinatarios no previstos pueden estar los servidores que enrutan y reenvían los datos del usuario al servidor de destino, o un hacker que accede al tráfico de red a través de un router Wi-Fi público.
Considera estos hallazgos del informe Web Almanac 2022, que Snyk también ayudó a redactar.

Actualmente, solo el 34 % de las respuestas a solicitudes móviles y el 37 % de las de escritorio incluyen la directiva includeSubdomain.
La mayoría restante sigue siendo más vulnerable a los ataques de intermediario (MITM), que pueden provocar desde el robo de tarjetas de crédito o de identidad hasta la exposición de las credenciales web de nuestra aplicación Node.js. Cabe destacar que los actores maliciosos no necesitan interceptar los datos justo cuando ingresamos nuestras credenciales. Las cookies del navegador suelen almacenar y enviar nuestros tokens de sesión o acceso, lo que permite que estos actores maliciosos los obtengan mediante el secuestro de sesión.
¿Cómo funciona HSTS?
Cuando la respuesta HTTP incluye un encabezado HSTS, los navegadores web saben que siempre deben usar una conexión HTTPS con el servidor y redirigen automáticamente a los usuarios que se conectaron primero mediante HTTP. A partir de ese momento, las conexiones con la aplicación o el sitio web permanecen cifradas y seguras, lo que permite que la aplicación use cookies seguras y ayuda a prevenir ataques de seguridad MITM.
El encabezado HSTS tiene tres parámetros diferentes. Veámoslos.
max - age = <expire-time>
Este parámetro obligatorio especifica durante cuánto tiempo, en segundos, el navegador debe recordar que tiene que conectarse al sitio mediante HTTPS. Una vez que vence este plazo, el navegador cargará el sitio normalmente en la siguiente visita. El tiempo de vencimiento se actualiza en el navegador del usuario cada vez que este recibe el encabezado HSTS. Por eso, el parámetro puede permanecer activo indefinidamente. También es posible deshabilitar HSTS de inmediato en ciertos sitios al establecer este valor en 0.
Al probar la configuración de HSTS, puedes establecer un plazo corto, como 300 segundos (cinco minutos). Luego, una vez que hayas verificado que el sitio funciona correctamente, puedes establecer un plazo más largo, como 31,536,000 segundos (un año).
includeSubDomains
El parámetro includeSubDomains es una marca opcional que le indica al navegador que habilite HSTS para el sitio web y todos sus subdominios. Como esta configuración se aplica de forma general, asegúrate de que todos tus subdominios sean compatibles con HTTPS antes de implementar el parámetro.
preload
La conexión inicial podría usar una conexión HTTP comprometida. Para responder a este riesgo, Google mantiene el parámetro no oficial preload. La mayoría de los principales navegadores son compatibles con este encabezado de seguridad, que reduce considerablemente el riesgo. Un sitio web puede agregar el parámetro preload al encabezado HSTS y luego registrar el dominio en el servicio de precarga. Así, los navegadores pueden consultar esta lista de referencia para determinar si sus conexiones iniciales pueden usar HTTPS. Ten en cuenta que debes establecer el parámetro max-age en al menos 31,536,000 segundos y habilitar el parámetro includeSubDomains para que funcione el parámetro preload.
Ten en cuenta que, una vez que el servicio de precarga agregue tu dominio, una solicitud para eliminarlo puede tardar varios meses en procesarse. Si quieres registrar tu dominio para la precarga, familiarízate con los requisitos de envío y las recomendaciones de implementación.
Refuerza la seguridad con HSTS
Veamos un ejemplo de código de un servidor Node.js que responde con un encabezado HSTS. Ten en cuenta que todos los ejemplos de código de este artículo son públicos y están disponibles en el siguiente repositorio de código abierto en GitHub.
Requisitos previos
Para ejecutar este proyecto, necesitarás lo siguiente:
Un nombre de dominio registrado
Un servidor con Node.js y los puertos de red 80 y 433 disponibles
Un registro DNS válido para el dominio que apunte al servidor
Obtén un certificado SSL/TLS
Antes de habilitar HTTPS, primero necesitaremos un certificado y una clave privada para el dominio. Si aún no tienes uno, puedes obtenerlo mediante Let's Encrypt siguiendo estos pasos:
Primero, instala certbot siguiendo estas instrucciones. Selecciona other en el menú desplegable Software y elige el sistema operativo de tu servidor en el menú desplegable System. Luego, sigue las instrucciones que aparecen.

Después, asegúrate de que los puertos 80 y 443 estén abiertos en el servidor y ejecuta el siguiente comando con el dominio de tu servidor:
Es posible que tengas que anteponer sudo al comando y ejecutarlo como usuario con privilegios.

Ahora, ejecuta certbot certificates (con sudo, si es necesario) para obtener las rutas de los archivos del certificado y la clave privada.

Configura el código del servidor
Empieza por crear una carpeta de proyecto en el servidor con el comando: mkdir snyk-demo.
Después, entra en la carpeta con: cd snyk-demo.
Luego, inicializa la carpeta como un proyecto de Node.js con: npm init -y.

Ahora instalaremos algunas dependencias para el servidor. Asegúrate de seguir las instrucciones correspondientes para Express o Fastify.
Express:
Fastify:
Ahora podemos crear un servidor Node.js básico con Express que funcione con HTTP y HTTPS.
Crea un archivo index.js en esta carpeta y agrega los siguientes módulos de Node al inicio del código.
Express:
Fastify:
Agrega el siguiente código para cargar los archivos del certificado y reemplaza el valor de certificatePath por la ruta del certificado de tu dominio. Si usaste certbot de Let's Encrypt, puedes ejecutar certbot certificates para obtener las rutas de los archivos.
Express:
Fastify:
Ahora es momento de inicializar la aplicación Express o Fastify y crear una ruta básica.
El siguiente código muestra los tres parámetros de HSTS, pero quizás quieras empezar usando solo el parámetro max-age.
Opción 1: Usa el middleware Helmet
La primera forma de configurar HSTS es mediante el middleware Helmet al inicializar la aplicación:
Express:
Fastify:
Opción 2: Configura el encabezado manualmente
Como alternativa, podemos configurar manualmente el encabezado HSTS mediante un middleware que se aplique a todas las respuestas:
Express:
Fastify:
Podemos completar el código creando los servidores HTTP y HTTPS con el siguiente código:
Express:
Fastify:
Como referencia, aquí tienes los enlaces a los repositorios del código de los proyectos Express y Fastify.
Por último, ejecuta el código del servidor con node index.js y abre tu dominio en un navegador web.
Abre DevTools en tu navegador e inspecciona los encabezados de respuesta en la pestaña Network. Verás que se especifica el encabezado HSTS.

¿Qué sigue?
Ahora que aprendiste por qué los encabezados HTTP Strict Transport Security son importantes para proteger las aplicaciones Node.js, cómo ayudan a prevenir los ataques MITM y cómo implementarlos en tu código Node.js, tienes las herramientas para proteger las aplicaciones web que ofreces a tus usuarios.
Hay otro punto fundamental que debes recordar. En un entorno de producción, no debes configurar HSTS ni servir SSL desde la aplicación Node.js. En su lugar, debes delegar estos procesos a servidores HTTP de archivos estáticos, como NGINX o Apache.



