Seguridad en la administración de sesiones: prácticas recomendadas para proteger las sesiones de los usuarios
11 de julio de 2023
0 minutos de lecturaLa seguridad en la administración de sesiones es un componente esencial del desarrollo de aplicaciones web. Protege las sesiones de los usuarios y evita el acceso no autorizado. Administrar las sesiones protege la confidencialidad, integridad y disponibilidad de los datos confidenciales de los usuarios. También protege la privacidad de los usuarios en general, algo esencial para mantener su confianza en una aplicación.
Cuando administramos las sesiones de forma segura, establecemos procesos para destruir los tokens de sesión cuando los usuarios cierran sesión o esta termina. Este enfoque evita el acceso no autorizado de cualquier persona que haya estado interceptando la conexión de red o quiera suplantar la identidad del usuario.
En este artículo práctico, veremos cómo implementar una administración segura de sesiones y cuáles son las prácticas recomendadas para hacerlo.
Comprender la seguridad en la administración de sesiones
Para conocer la importancia de administrar las sesiones a nivel de dominio, desarrollaremos una aplicación sencilla de Node.js que implementa funciones básicas de inicio y cierre de sesión, así como de administración de sesiones.
Requisitos previos
Para seguir este tutorial, necesitarás:
Tener instalado Node.js y npm localmente en tu equipo
Visual Studio Code como editor de código fuente
La extensión de Snyk para Visual Studio Code (llamada Snyk Security — Code, Open Source Dependencies en Visual Studio Code).
Ten en cuenta que esta demostración usa el sistema operativo Windows y los comandos correspondientes.
Para ver un resumen del proyecto completo, consulta el código completo.
Implementar sesiones en Node.js
Para comenzar, abre el símbolo del sistema (CMD) y usa el código siguiente para crear una carpeta llamada sessions, entrar en ella e inicializar la aplicación:
Al ejecutar los comandos anteriores, se genera automáticamente un archivo package.json que contiene todas las dependencias instaladas en el proyecto.
A continuación, debemos instalar algunos paquetes que permitirán cumplir los objetivos específicos. Estos paquetes son express, un framework para crear servidores web, y express-session, un framework HTTP del lado del servidor necesario para crear middleware de sesión. Usa el código siguiente para instalar ambos paquetes:
Ahora, abre el proyecto en Visual Studio Code.
Para incluir la lógica de nuestra aplicación, debemos crear un archivo index.js. En el CMD, usa el comando touch index.js para crear un archivo index.js. Luego, actualiza el archivo index.js con el código siguiente:
El fragmento de código anterior contiene el código inicial de una aplicación de Node.js. Configura el middleware de sesión para la aplicación Express en el cuerpo del proyecto.
El middleware de URL codificada se encarga de las solicitudes entrantes con datos de formulario codificados en la URL en cualquier aplicación Express.js.
A continuación, agrega el código siguiente después de los middlewares en el archivo index.js para gestionar las funciones de inicio y cierre de sesión de un usuario:
Antes de continuar, repasemos rápidamente lo que sucede en el código anterior:
La primera ruta,
app.get('/'), gestiona las solicitudes a la URL raíz de la aplicación. Da la bienvenida a los usuarios que tienen un nombre de usuario guardado en su sesión y les ofrece un enlace para cerrar sesión. De lo contrario, les pide que inicien sesión.La segunda ruta,
app.get('/login'), gestiona las solicitudes a la URL de inicio de sesión.La tercera ruta,
app.post('/login'), procesa el envío del formulario de inicio de sesión.La cuarta ruta,
app.get('/logout'), gestiona las solicitudesGETa la URL de cierre de sesión. Destruye la sesión del usuario y lo redirige a la URL raíz.
Guarda todos los cambios y luego ve a la terminal y ejecuta la aplicación con este comando:
Como estamos escuchando en el puerto 3001, abre http://localhost:3001/ en un navegador. Al navegar a la URL, verás este sencillo enlace para iniciar sesión:

Haz clic en el enlace para iniciar sesión e ingresa tu nombre. Esto te llevará a la siguiente página de inicio:

Ahora, revisa la terminal. Verás el objeto de sesión, que se ve así:

La primera propiedad es la ruta. Representa la ruta válida de la cookie de sesión. A continuación, aparece la hora de expiración de la sesión, es decir, cuánto tarda en vencer una cookie, y el atributo httpOnly establecido en true para prevenir ataques del lado del cliente, como el cross-site scripting (XSS). El objeto de sesión también muestra el nombre de usuario actual.
La administración de sesiones y su función en las aplicaciones web
Ahora que preparamos una aplicación de ejemplo, veamos cómo funciona la administración de sesiones y por qué es tan importante para gestionarlas de forma segura.
En las aplicaciones web, las interacciones entre un usuario y la aplicación suelen incluir información confidencial; en este caso, una contraseña. La administración de sesiones garantiza que estas interacciones sean seguras para los usuarios autenticados y que la información proporcionada durante sus sesiones esté siempre protegida. Si no se hace, pueden surgir vulnerabilidades en la administración de sesiones.
Algunas vulnerabilidades comunes son:
Secuestro de sesión: ocurre cuando un atacante compromete un token de sesión al robarlo o predecirlo para obtener acceso no autorizado al servidor en nombre de su titular. Hay varias maneras de lograrlo. Una de ellas es mediante XSS. Si la aplicación web a la que accede el usuario tiene el atributo httpOnly establecido en false, el riesgo de secuestro de sesión desde el lado del cliente es muy alto, lo que abre la posibilidad de ataques XSS.
Ataques de intermediario (MITM) : son otro tipo de secuestro de sesión. Un actor malicioso puede acceder a una sesión interceptando el ID de sesión cuando el usuario y el servidor se comunican. Esto ocurre cuando el ID de sesión está en texto sin formato y un interceptor puede leerlo fácilmente en el canal de datos.
Fijación de sesión: ocurre cuando un atacante engaña al usuario para que use un ID de sesión existente y así acceder al servidor mediante el secuestro de una sesión de usuario válida. Suele ocurrir cuando el usuario que accede a la sesión no se valida correctamente mediante el ID de sesión. También puede ocurrir cuando un atacante envía a la víctima un ID de sesión vulnerable dentro de una URL.
Los riesgos asociados a los procesos inseguros de administración de sesiones pueden ser considerables. Con los datos confidenciales obtenidos, los actores maliciosos pueden cometer fraudes y robos, y acceder a información privilegiada. Estas brechas de seguridad perjudican mucho a los usuarios y pueden dañar gravemente su confianza en una aplicación.
Por suerte, podemos implementar varias estrategias para proteger los procesos de administración de sesiones. En las siguientes secciones, destacamos algunos métodos y mostramos cómo implementarlos.
Implementar cookies seguras
El uso de cookies puede ayudar a administrar las sesiones de forma segura. En la administración de sesiones, las cookies pueden vincular a los usuarios con un objeto de sesión en el servidor. Gracias a su identificador único, una cookie contiene todas las actividades relacionadas con el usuario en las distintas instancias que visitó.
Por ejemplo, cuando un usuario accede a una aplicación para iniciar sesión, esta acción crea un objeto de sesión y le asigna un ID de sesión. La cookie almacena el ID de sesión y lo envía al navegador como respuesta. Cuando el usuario realiza una solicitud, el navegador envía la cookie, que verifica el ID de sesión y recupera el objeto asociado. Esto permite que el servidor valide al usuario y mantenga sus sesiones en distintas páginas y solicitudes.
Por eso, los desarrolladores de sistemas, arquitectos de aplicaciones y administradores deben asegurarse de que las cookies se usen de la manera más segura posible.
Una forma de proteger las cookies es usar el indicador secure, que permite solicitudes únicamente a través de HTTPS. Protege al usuario en la red de un ataque MITM en la ruta de datos, ya que el paquete enviado no está en texto sin formato y, por lo tanto, no se puede leer.
Además de los ataques MITM, las cookies también son vulnerables a ataques XSS porque transmiten paquetes de datos a través de la red. Para prevenirlos, podemos usar el indicador HttpOnly, que impide que JavaScript lea la cookie de sesión.
Para implementar este indicador, debemos comprobar que el objeto de sesión HttpOnly esté asignado al valor booleano true.
Ve a la terminal e instala cookie-parser, el middleware para guardar las cookies, y bcrypt, la versión vulnerable del paquete, con el siguiente comando:
Luego, actualiza el código en el archivo index.js de la siguiente manera:
Para ver las vulnerabilidades detectadas en tu código en Visual Studio Code, debes asegurarte de que Snyk Code esté habilitado en tu cuenta. Puedes hacerlo desde la extensión de Visual Studio Code o el sitio web de Snyk. Si observas la pestaña PROBLEMAS en la terminal de Visual Studio Code, verás que Snyk resaltó varias vulnerabilidades en el código:

El análisis muestra que hay un secreto codificado directamente en el código, la protección contra la falsificación de solicitudes entre sitios (CSRF) está deshabilitada, el indicador secure está deshabilitado y hay un paquete vulnerable.
Snyk sugiere varias formas de corregir estos problemas siguiendo las indicaciones. Vamos a resolver un par de ellos.
Primero, Snyk recomienda usar variables de entorno para evitar codificar datos directamente. Para implementar este cambio, ve a la terminal y ejecuta los siguientes comandos:
El primer comando instala el paquete dotenv para leer las variables de entorno configuradas y el segundo crea un archivo de entorno para almacenar esa información confidencial.
Ahora, agrega esta configuración al archivo .env:
Luego, actualiza el middleware de sesión en el archivo index.js con este código:
Con estas actualizaciones, el secreto se leerá de la variable de entorno.
A continuación, cambia el indicador secure a true.
Como habilitar CSRF agregaría bastante código a nuestra aplicación, lo omitiremos en esta demostración. Pero recuerda abordarlo en tus propias aplicaciones con el paquete csrf.
Para resolver el problema del paquete vulnerable, consulta la documentación oficial de npm e instala una versión actualizada o el paquete bcryptjs, que ha sido probado más exhaustivamente y es más seguro.
Una vez que la extensión de Snyk haya analizado la aplicación después de estas actualizaciones, verás que la mayoría de los errores desaparecieron. Si ejecutas la aplicación en este punto, localhost no funcionará si no se usa HTTPS y seguirá redirigiéndote a la URL raíz.
Además de usar el almacenamiento local para guardar datos de las solicitudes del cliente, puedes almacenar los datos de sesión de tu aplicación en una base de datos. Esto permite reiniciar el servidor sin perder los datos de sesión, que se conservan mediante un ID de sesión único, y facilita que los usuarios inicien sesión sin ingresar sus credenciales cada vez. Como alternativa, puedes usar cachés en memoria, como Redis.
Implementar tiempos de espera de sesión
Los tiempos de espera de sesión se producen cuando vence la sesión de un usuario, lo que cierra su sesión automáticamente. Esto reduce el período durante el cual puede ocurrir un ataque a la sesión y garantiza que esta se destruya después de un tiempo determinado.
Al definir la duración de los tiempos de espera de sesión, hay varios factores que debes considerar:
El tipo de aplicación: determina la duración adecuada de los tiempos de espera según los datos que maneja tu aplicación.
El comportamiento de los usuarios: asegúrate de que los tiempos de espera no afecten su experiencia.
Implementamos los tiempos de espera de sesión en el middleware de sesión. Actualiza el código con el siguiente fragmento para establecer el tiempo de espera de la sesión en una hora:
Implementar una función de cierre de sesión adecuada
La función de cierre de sesión garantiza que los usuarios puedan finalizar sus sesiones explícitamente cuando terminan de interactuar con una aplicación. Al implementarla, los usuarios pueden terminar sus sesiones de cookies y tener mayor control sobre su seguridad.
Sin embargo, la funcionalidad de cierre de sesión todavía requiere la atención de los desarrolladores. Cuando un usuario inicia el cierre de sesión, es posible que la sesión del lado del cliente termine, pero que la cookie de sesión no se haya invalidado por completo en el servidor. Un impostor puede usar estos tokens de sesión y realizar acciones como si fuera el usuario original.
Para prevenir esta brecha de seguridad, debemos asegurarnos de que el token y el ID de sesión del usuario se destruyan en el servidor. Implementa esta función en la aplicación usando el siguiente código como la última ruta del archivo index.js:
Este código llama a destroy() con una función de devolución de llamada para eliminar una sesión en el servidor cuando un usuario cierra sesión. También llama a clearCookie() y elimina connection.sid, que es una clave asignada al valor del usuario que inició sesión.
Si inspeccionas las cookies del usuario que inició sesión en el navegador mediante la opción de inspección, deberías ver connection.sid, como se muestra a continuación:

Al implementar los pasos anteriores, podemos asegurarnos de que los usuarios del sistema cierren sesión sin preocuparse por su seguridad en línea. La extensión Snyk Code permite ver todos los análisis de vulnerabilidades realizados en nuestro proyecto y el estado de cada uno, lo que nos ayuda a garantizar que la aplicación no esté expuesta a riesgos antes de ponerla a disposición de los usuarios.
A lo largo de este artículo, usamos Snyk para analizar nuestro proyecto y vimos cómo abordar problemas de vulnerabilidad, como los secretos codificados de forma rígida, los problemas relacionados con las sesiones y el uso de un paquete vulnerable. Ahora que mitigamos las vulnerabilidades detectadas por Snyk, nuestro sistema no tiene ninguna, como se muestra en el informe a continuación:

Más prácticas recomendadas para una administración segura de sesiones
Además de los procesos que revisamos a lo largo de este artículo, aquí tienes algunas prácticas recomendadas más para administrar las sesiones de forma más segura:
Usa identificadores de sesión seguros — Los identificadores de sesión seguros son cadenas largas de caracteres únicos que se usan para autenticar sesiones de usuario. Podemos generar estos identificadores automáticamente. La aleatoriedad y la imprevisibilidad dificultan que incluso los atacantes meticulosos los adivinen mediante técnicas de análisis estadístico, y la longitud de la cadena permite resistir ataques de fuerza bruta.
Usa la administración de sesiones del lado del servidor — Capturar identificadores de sesión en el lado del cliente puede generar una vulnerabilidad, aunque se hayan generado de forma única. Podemos usar la administración de sesiones del lado del servidor para almacenar estos identificadores y asociarlos con los usuarios de la aplicación. Con este tipo de almacenamiento de sesiones, las credenciales confidenciales de los usuarios están mucho más seguras y pueden usar el sistema con libertad, sin temor a que alguien se haga pasar por ellos.
Valida correctamente los cierres de sesión — Cuando un usuario inicia sesión en una instancia y luego cierra sesión, el sistema debe invalidar correctamente la sesión en todas las instancias que visitó. Lograrlo sin sincronizar los datos de sesión entre las instancias puede ser complicado. Aun así, es esencial hacerlo, ya que las instancias pueden convertirse en un punto de entrada para que los impostores roben información de los usuarios.
Conclusión
En este artículo, exploramos varias estrategias para mejorar la seguridad de la administración de sesiones, maximizar la seguridad de los visitantes y reducir la cantidad de ataques. Una administración segura de sesiones garantiza que la información personal, los datos y las cuentas estén protegidos, a pesar de las huellas digitales que los usuarios puedan dejar.
También protege a los usuarios mientras interactúan con nuestros sitios web y aplicaciones web. Al implementar las prácticas recomendadas y las estrategias de seguridad que se describen aquí, podemos ayudar a que nuestros usuarios confíen en que sus credenciales y su información confidencial están seguras.
Comienza con Capture the Flag
Aprende a resolver desafíos de Capture the Flag con nuestro taller virtual 101 a pedido.


