In this article
Les 10 meilleures pratiques de sécurité pour Node.js
Qu’est-ce que Node.js ?
Node.js est une plateforme open source et multiplateforme de développement d’applications web. Il s’agit d’un environnement d’exécution JavaScript basé sur le moteur V8 de Chrome, qui permet aux développeurs de créer rapidement et facilement des applications web évolutives.
Qu’est-ce que la sécurité de Node.js ?
Node.js est une plateforme sécurisée en elle-même, mais de nombreux packages open source tiers de son écosystème ne le sont pas forcément. Utilisés via Node Package Manager (NPM), ces packages sont exposés à de nombreux types de vulnérabilités et à d’autres risques liés aux licences et à la sécurité de Node.js. Certaines bases de code Node.js comptent des milliers de packages de ce type, ce qui expose les applications qui les intègrent à de nombreux risques.
Pourquoi sécuriser Node.js ?
NPM, généralement utilisé avec l’environnement d’exécution Node.js, est l’un des plus grands écosystèmes de packages open source. Les technologies open source peuvent représenter un enjeu majeur en matière de cybersécurité. En effet, le rapport Snyk sur l’état de la sécurité open source indique qu’un projet compte en moyenne 49 vulnérabilités réparties sur 79 dépendances directes. Par ailleurs, un développeur sur GitHub a mené une expérience de sécurité qui lui a permis d’accéder à 14 % des packages NPM, tandis que 54 % supplémentaires étaient potentiellement accessibles via des chaînes de dépendances.
Cela montre que Node.js n’est pas suffisamment sécurisé pour que les développeurs puissent écarter tout risque d’exposition aux pirates. En complément de ces dix bonnes pratiques de sécurité NPM, nous recommandons les pratiques supplémentaires ci-dessous pour sécuriser les applications conçues avec Node.js.
Les 10 meilleures pratiques pour sécuriser Node.js
Pour contrer les risques les plus courants liés à Node.js, vous devez mettre en place certaines bonnes pratiques essentielles. Voici les dix pratiques les plus efficaces pour éviter les pièges de sécurité courants dans Node.js.
1. Mettre en place la journalisation et la surveillance
La journalisation et la surveillance sont essentielles pour assurer la sécurité de Node.js dans la durée. Surveiller vos journaux vous permet de comprendre ce qui se passe dans votre application et d’enquêter sur toute activité suspecte. Parmi les niveaux importants à consigner figurent info, error, warn et debug. Pour réduire le travail manuel, vous pouvez utiliser des modules comme Bunyan et toobusy-js afin d’automatiser la journalisation et la surveillance.
2. Veiller à mettre en place des politiques d’authentification robustes
Vous avez peut-être remarqué que plusieurs des attaques potentielles mentionnées plus haut reposent sur un acteur malveillant qui contourne ou exploite l’authentification des utilisateurs. Mettre en place des politiques d’authentification robustes constitue une protection essentielle contre ces attaques. Voici quelques recommandations en matière d’authentification :
Exigez l’authentification multifacteur (MFA) et l’authentification unique (SSO).
Utilisez les bibliothèques Scrypt ou Bcrypt plutôt que la bibliothèque crypto de Node.js.
Appliquez des politiques cohérentes de gestion des sessions.
Exigez des mots de passe robustes pour les utilisateurs.
Limitez le nombre de tentatives de connexion infructueuses.
3. Éviter de bloquer la boucle d’événements
Si vous effectuez des tâches lourdes dans la boucle d’événements ou dans les threads du pool de workers, les requêtes d’autres clients peuvent être bloquées, ce qui réduit votre débit. Voici quelques moyens de veiller à ce que vos threads restent disponibles :
Veillez à ce que vos callbacks JavaScript s’exécutent rapidement.
Réduisez la complexité de vos callbacks en conservant un nombre d’étapes constant, quel que soit l’argument. Ainsi, chaque client dans la file d’attente aura les mêmes chances.
Si vous devez effectuer une tâche complexe, bornez les entrées et rejetez celles qui sont trop longues. Avec des entrées bornées, l’exécution ne dépassera pas la durée de votre pire cas, ce qui évitera le blocage du thread. (Veillez bien sûr à ce que la durée d’exécution dans le pire cas soit suffisamment courte pour ne pas bloquer le thread.)
Évitez les API synchrones des modules de chiffrement, de compression, du système de fichiers ou des processus enfants. Leur exécution peut être très longue et bloquer votre boucle d’événements.
4. Gérer les erreurs de façon sécurisée
Préparer votre code à gérer les erreurs permet d’atténuer de nombreux problèmes de performances et de sécurité des applications. Voici quelques bonnes pratiques pour éviter les bugs dans vos programmes :
Au lieu de gérer les erreurs asynchrones avec des callbacks, utilisez une bibliothèque de promesses reconnue ou async-await.
La gestion personnalisée des erreurs ou leur traitement sous forme de chaînes ajoute de la complexité. Simplifiez leur gestion en utilisant systématiquement l’objet Error intégré.
La gestion des erreurs dans les middlewares peut entraîner une duplication du code. Il est préférable de centraliser la logique de gestion des erreurs.
Testez régulièrement vos flux de gestion des erreurs pour vérifier qu’ils ne produisent ni faux positifs ni erreurs non détectées.
Utilisez un outil de gestion des processus pour redémarrer l’application lorsqu’une erreur inconnue survient. Pm2 et forever sont deux exemples d’outils de gestion des processus Node.js.
5. Ne pas envoyer d’informations inutiles
Lorsque vous envoyez des informations au front-end, veillez à ne transmettre que les données essentielles. En théorie, vous pouvez filtrer les informations que vous souhaitez afficher, mais les attaquants peuvent toujours accéder aux données masquées depuis le back-end. Le seul moyen de garantir qu’ils ne pourront pas accéder aux données sensibles est de ne pas les envoyer, sauf si c’est absolument nécessaire.
6. Limiter la taille des requêtes
Dans Node.js, la limite de taille par défaut des requêtes est de 5 Mo. Pour éviter les attaques DDoS qui consistent à inonder vos serveurs, vous pouvez réduire davantage la taille des requêtes autorisées par Node.js.
Voici deux moyens simples d’y parvenir :
Configurez l’option « limit » du package body-parser pour n’accepter que les petits payloads.
Utilisez des proxys inverses ou un middleware Express pour définir des limites de taille pour certains types de contenu.
7. Valider les entrées utilisateur
L’une des raisons pour lesquelles les acteurs malveillants parviennent à mener des attaques XSS est l’absence de validation des entrées utilisateur. Commencez par assainir les entrées utilisateur à l’aide d’un package NPM comme DOMPurify. Utilisez ensuite une bibliothèque de validation des formulaires telle que express-validator ou XSS-filters. Ces bibliothèques automatisent la tâche fastidieuse qui consiste à valider chaque entrée de chaque requête. Les filtres de sortie sensibles au contexte, comme XSS-filters, sont faciles à utiliser pour les développeurs et encodent le nombre minimal de caractères nécessaire pour empêcher une attaque XSS.
8. Assurer une désérialisation sécurisée
Node.js ne propose pas de méthodes avancées de sérialisation des objets. Les attaquants peuvent donc utiliser des objets sérialisés pour transférer des payloads. Mettez en place des contrôles d’intégrité et d’authentification des utilisateurs, et assainissez les données désérialisées pour éviter ce type de risque. Plus précisément, utilisez des jetons anti-CSRF, des en-têtes de requête personnalisés, l’attribut SameSite pour les cookies de session et une protection reposant sur les interactions utilisateur.
9. Utiliser des linters de sécurité et des outils SAST
Pour corriger les vulnérabilités susceptibles de provoquer une attaque, vous devez d’abord savoir où elles se trouvent. Des outils tels que les plugins de linting et les outils de test statique de sécurité des applications (SAST) peuvent automatiser ce processus et vous éviter d’en manquer.
Des linters comme eslint-plugin-node-security analysent le code source pour repérer et signaler les pratiques non sécurisées. Des outils SAST comme Snyk Code surveillent votre code Node.js au fur et à mesure que vous l’écrivez et vous alertent en cas de vulnérabilité potentielle.
Lancez-vous dans les compétitions Capture The Flag
Apprenez à résoudre des défis Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.
10. Exécuter Node.js avec un utilisateur non root
C’est une bonne pratique à appliquer partout, mais il est particulièrement important de ne pas exécuter Node.js en tant qu’utilisateur root. En exécutant Node.js avec un utilisateur non root, vous réduisez la surface d’attaque dont les acteurs malveillants pourraient tirer parti.
Cette recommandation applique le principe du moindre privilège : accordez aux utilisateurs uniquement les accès dont ils ont besoin pour effectuer leur travail. L’accès root ne doit être accordé que dans des situations très spécifiques.
Snyk contribue à la sécurité de Node.js
Depuis mai 2021, Snyk contribue à la sécurité de l’écosystème Node.js en prenant en charge le programme de signalement des vulnérabilités de l’écosystème Node.js. L’équipe dédiée d’analystes et de chercheurs en sécurité de Snyk examine les signalements, les vérifie et contacte les responsables des packages concernés pour lancer le processus de divulgation responsable conformément à la politique de divulgation de Snyk.
De plus, les produits Snyk vous permettent de détecter et de corriger des vulnérabilités en cinq minutes. Voici comment Snyk renforce la sécurité de Node.js :
Snyk Open Source aide à détecter les vulnérabilités dans les dépendances d’une application Node.js et à en avertir les développeurs. Votre code est ainsi protégé contre les principaux risques de sécurité abordés dans cet article.
Snyk Code est un outil SAST qui aide à détecter les vulnérabilités dans le code de vos applications et à en avertir les développeurs.
Snyk Container aide les développeurs à détecter les vulnérabilités dans les conteneurs et les charges de travail Kubernetes tout au long du cycle de développement logiciel (SDLC).
Si vous utilisez Node.js dans des conteneurs, découvrez également nos bonnes pratiques pour conteneuriser des applications Node.js avec Docker.
Snyk pour sécuriser JavaScript
De votre première ligne de code à votre dernière dépendance npm, Snyk sécurise vos applications JavaScript directement depuis votre IDE, votre CLI et vos workflows Git.
FAQ sur la sécurité de Node.js
Node.js est-il sécurisé ?
La plateforme Node.js est sécurisée par nature. Toutefois, comme elle utilise des packages open source tiers via son système de gestion de packages (npm), elle est vulnérable aux cyberattaques. Pour garantir la sécurité de Node.js, les entreprises doivent appliquer les bonnes pratiques, comme celles présentées dans cet article.
Comment sécuriser Node.js ?
Adopter des pratiques telles que la validation des données saisies par les utilisateurs, la mise en place de l’authentification, la limitation de la taille des requêtes et la configuration de la journalisation et de la surveillance constitue un bon point de départ pour sécuriser Node.js. Pour répondre aux préoccupations spécifiques liées aux attaques par injection de code, découvrez cinq façons de prévenir les injections de code dans Node.js.
Node.js peut-il être piraté ?
Les pirates peuvent compromettre des applications Node.js en inondant les serveurs de production, en injectant du JavaScript malveillant ou en soumettant des entrées qui ralentissent vos programmes. La nature open source de NPM expose également Node.js à des vulnérabilités.