In this article
10 mejores prácticas de seguridad para Node.js
¿Qué es Node.js?
Node.js es una plataforma de desarrollo de aplicaciones web de código abierto y multiplataforma. Es un entorno de ejecución de JavaScript basado en el motor V8 de Chrome que permite a los desarrolladores crear aplicaciones web escalables de forma rápida y sencilla.
¿Qué es la seguridad de Node.js?
Node.js es una plataforma segura, pero muchos paquetes de código abierto de terceros de su ecosistema podrían no serlo. Estos paquetes se usan mediante Node Package Manager (NPM) y son susceptibles a distintos tipos de vulnerabilidades y otros riesgos de licencias y seguridad de Node.js. Algunas bases de código de Node.js usan miles de estos paquetes, lo que expone las aplicaciones que los contienen a numerosos riesgos.
¿Por qué debes proteger Node.js?
NPM (que suele usarse con el entorno de ejecución de Node.js) es uno de los ecosistemas de paquetes de código abierto más grandes. Las tecnologías de código abierto pueden ser motivo de gran preocupación en materia de ciberseguridad. De hecho, el informe de Snyk sobre el estado de la seguridad del código abierto muestra que un proyecto promedio tiene 49 vulnerabilidades en 79 dependencias directas. Además, un desarrollador de GitHub realizó un experimento de seguridad en el que logró acceder al 14 % de los paquetes de NPM, y otro 54 % podía ser accesible a través de cadenas de dependencias.
Esto demuestra que Node.js no es lo suficientemente seguro como para que los desarrolladores ignoren la posible exposición a los hackers. Además de estas diez mejores prácticas de seguridad para NPM, recomendamos las prácticas adicionales que se describen a continuación para proteger las aplicaciones creadas con Node.js.
10 mejores prácticas para mantener la seguridad de Node.js
Para combatir los riesgos más comunes de Node.js, debes implementar algunas prácticas importantes. Estas son las diez prácticas más valiosas que pueden ayudarte a evitar errores de seguridad comunes en Node.js.
1. Configura el registro y el monitoreo
El registro y el monitoreo son fundamentales para mantener la seguridad de Node.js. Monitorear los registros te permite saber qué sucede en tu aplicación para investigar cualquier actividad sospechosa. Algunos niveles importantes que debes registrar son info, error, warn y debug. Para reducir el trabajo manual, puedes usar módulos como Bunyan y toobusy-js para automatizar el registro y el monitoreo.
2. Asegúrate de tener políticas de autenticación sólidas
Quizá hayas notado que varios de los posibles ataques mencionados antes implican que un actor malicioso eluda o aproveche las debilidades de la autenticación de usuarios. Contar con políticas de autenticación sólidas es una medida de protección importante contra estos atacantes. Estas son algunas pautas de autenticación:
Exige autenticación multifactor (MFA) e inicio de sesión único (SSO).
Usa las bibliotecas Scrypt o Bcrypt en lugar de la biblioteca crypto de Node.js.
Implementa políticas coherentes para la gestión de sesiones.
Exige contraseñas seguras a los usuarios.
Restringe la cantidad de intentos fallidos de inicio de sesión.
3. Evita bloquear el bucle de eventos
En el bucle de eventos y los subprocesos del grupo de trabajadores, ejecutar tareas pesadas en cualquiera de ellos puede detener las solicitudes de respuesta de otros clientes y afectar negativamente tu rendimiento. Estas son algunas formas de mantener abiertos los subprocesos:
Asegúrate de que las funciones de devolución de llamada de JavaScript se ejecuten rápidamente.
Reduce la complejidad de tus funciones de devolución de llamada manteniendo constante la cantidad de pasos, sin importar el argumento. Así, todos los clientes en la cola tendrán las mismas oportunidades.
Si tienes una tarea compleja, limita la entrada y rechaza las entradas demasiado largas. Las entradas limitadas solo se ejecutarán durante el tiempo que requiera el peor caso, lo que evitará que el subproceso se bloquee. (Por supuesto, primero debes asegurarte de que el tiempo del peor caso sea lo suficientemente corto para evitar que el subproceso se bloquee).
Evita usar API síncronas de los módulos de cifrado, compresión, sistema de archivos o procesos secundarios. Pueden tardar mucho en completarse y bloquear el bucle de eventos.
4. Maneja los errores de forma segura
Puedes mitigar muchos problemas de rendimiento y seguridad de las aplicaciones preparando el código para manejar errores. Estas son algunas prácticas recomendadas para evitar errores en tus programas:
En lugar de manejar los errores asíncronos con funciones de devolución de llamada, usa una biblioteca de promesas confiable o async-await.
El manejo personalizado de errores o basado en cadenas agrega complejidad. Simplifica los errores usando siempre el objeto de error integrado.
Manejar errores en el middleware puede duplicar el código. Lo mejor es gestionar la lógica de manejo de errores de forma centralizada.
Prueba regularmente los flujos de manejo de errores para asegurarte de que no generen falsos positivos ni pasen por alto errores.
Usa una herramienta de gestión de procesos para reiniciar la aplicación cuando aparezca un error desconocido. Pm2 y forever son dos ejemplos de herramientas de gestión de procesos de Node.js.
5. No envíes información innecesaria
Cuando envíes información al front-end, asegúrate de enviar solo los datos esenciales. Aunque en teoría puedes filtrar la información que quieras para que no se muestre, los atacantes aún pueden acceder a los datos ocultos a través del back-end. La única forma de garantizar que no puedan acceder a datos confidenciales es no enviarlos, a menos que sea absolutamente necesario.
6. Limita el tamaño de las solicitudes
El límite predeterminado para las solicitudes en Node.js es de 5 MB. Para evitar un ataque DDoS en el que un hacker satura tus servidores, puedes limitar aún más el tamaño de las solicitudes que Node.js permite.
Estas son dos formas sencillas de hacerlo:
Configura la opción ‘limit’ en el paquete body-parser para aceptar solo cargas útiles pequeñas.
Usa proxies inversos o middleware de Express para establecer límites de tamaño en determinados tipos de contenido.
7. Valida las entradas del usuario
Una de las razones por las que los actores maliciosos pueden llevar a cabo ataques XSS es que no se validan las entradas del usuario. Lo primero que debes hacer en este caso es sanitizar las entradas del usuario con un paquete de NPM como DOMPurify. Después, usa una biblioteca de validación de formularios como express-validator o XSS-filters. Las bibliotecas de validación de formularios automatizan la tediosa tarea de validar cada entrada en cada solicitud. Los filtros de salida según el contexto, como XSS-filters, son fáciles de usar para los desarrolladores y codifican la menor cantidad de caracteres necesaria para impedir un ataque XSS.
8. Asegura la deserialización
Node.js no ofrece métodos avanzados para serializar objetos. Por eso, los atacantes pueden usar objetos serializados para transferir cargas útiles. Implementa verificaciones de integridad y autenticación de usuarios, y sanitiza los datos deserializados para evitar esta situación. En un nivel más específico, usa tokens anti-CSRF, encabezados de solicitud personalizados, el atributo SameSite en las sesiones de cookies y protecciones basadas en la interacción del usuario.
9. Usa linters de seguridad y herramientas SAST
Para corregir las vulnerabilidades que podrían provocar un ataque, primero debes saber dónde están. El uso de herramientas como complementos de linter y pruebas estáticas de seguridad de aplicaciones (SAST) puede automatizar este proceso y ayudarte a no pasar nada por alto.
Los linters como eslint-plugin-node-security analizan el código fuente para identificar y señalar prácticas inseguras. Las herramientas SAST como Snyk Code monitorean tu código de Node.js mientras escribes y te alertan sobre posibles vulnerabilidades.
Comienza con Capture the Flag
Aprende a resolver desafíos de Capture the Flag con nuestro taller virtual 101 a pedido.
10. Ejecuta Node.js como usuario sin privilegios de root
Esta es una buena práctica en general, pero es especialmente importante no ejecutar Node.js como usuario root. Al ejecutarlo como un usuario sin privilegios de root, limitas la superficie de ataque que los actores maliciosos pueden aprovechar.
Esta recomendación sigue el principio de privilegio mínimo: dar a los usuarios solo el nivel de acceso exacto que necesitan para hacer su trabajo. El acceso root solo debe concederse en situaciones muy específicas.
Snyk contribuye a la seguridad de Node.js
Desde mayo de 2021, Snyk ha contribuido a la seguridad del ecosistema de Node.js al hacerse cargo del programa de divulgación de vulnerabilidades del ecosistema de Node.js. El equipo especializado de analistas e investigadores de seguridad de Snyk clasifica y verifica los informes de divulgación de Node.js, y se comunica con los responsables de los paquetes reportados para iniciar el proceso de divulgación responsable conforme a la política de divulgación de Snyk.
Además, los productos de Snyk te permiten encontrar y corregir vulnerabilidades en cinco minutos. Así es como Snyk mejora la seguridad de Node.js:
Snyk Open Source ayuda a identificar vulnerabilidades en las dependencias de una aplicación de Node.js y a alertar a los desarrolladores. Así, te ayuda a proteger tu código frente a los principales riesgos de seguridad que vimos hoy.
Snyk Code es una herramienta SAST que ayuda a identificar vulnerabilidades en el código de las aplicaciones y a alertar a los desarrolladores.
Snyk Container ayuda a los desarrolladores a encontrar vulnerabilidades en contenedores y cargas de trabajo de Kubernetes durante todo el ciclo de vida del desarrollo de software (SDLC).
Ten en cuenta que, si usas Node.js en contenedores, tenemos otras prácticas recomendadas para contenerizar aplicaciones de Node.js con Docker.
Snyk para la seguridad de JavaScript
Desde la primera línea de código hasta la última dependencia de npm, Snyk protege tus aplicaciones de JavaScript directamente desde tu IDE, CLI y flujos de trabajo de Git.
Preguntas frecuentes sobre la seguridad de Node.js
¿Node.js es seguro?
La plataforma Node.js es segura por naturaleza, pero como utiliza paquetes de código abierto de terceros a través de su sistema de gestión de paquetes (npm), es vulnerable a los ciberataques. Para mantener la seguridad de Node.js, las empresas deben implementar las mejores prácticas, como las que se describen en este artículo.
¿Cómo puedes proteger Node.js?
Establecer prácticas como validar las entradas de usuario, implementar la autenticación, limitar el tamaño de las solicitudes y configurar el registro y el monitoreo son buenos primeros pasos para proteger Node.js. Si te preocupan específicamente los ataques de inyección de código, aquí tienes cinco formas de prevenir la inyección de código en Node.js.
¿Se puede hackear Node.js?
Los hackers pueden vulnerar aplicaciones de Node.js al saturar los servidores de producción, inyectar JavaScript malicioso o enviar entradas que consuman mucho tiempo en tus programas. La naturaleza de código abierto de NPM también expone Node.js a vulnerabilidades.