Prévenir les problèmes de contrôle d’accès dans les applications Node.js avec Express
Ben Smitthimedhin
22 mai 2024
0 minutes de lectureLe contrôle d’accès dans les applications backend Node.js est fondamental pour les applications web créées avec le framework Express. Il garantit que les utilisateurs peuvent uniquement accéder aux données et aux fonctionnalités qu’ils sont autorisés à utiliser. Cependant, lorsqu’il est compromis, les utilisateurs peuvent accéder à des données qui devraient leur être interdites. Cela pose particulièrement problème si des pirates tentent de manipuler ou de dérober des données privées.
Il est essentiel de comprendre les vulnérabilités du contrôle d’accès et de les prévenir, car la fuite de données privées peut avoir des conséquences désastreuses pour de nombreuses entreprises. Dans cet article, découvrez le contrôle d’accès défaillant dans les applications Node.js et les stratégies permettant de prévenir ces vulnérabilités lors de la création d’applications web avec le framework Express.
Qu’est-ce qu’un contrôle d’accès défaillant ?
Le contrôle d’accès consiste à limiter ce qu’un utilisateur peut faire et voir dans une application. Un contrôle d’accès est défaillant lorsque l’implémentation des règles de contrôle d’accès de l’application présente des failles, permettant à des utilisateurs non autorisés d’accéder à des informations sensibles ou d’effectuer des actions restreintes.
Par exemple, si un utilisateur ordinaire peut consulter les données privées d’un autre utilisateur, modifier son mot de passe ou même élever ses privilèges au niveau administrateur en raison d’un contrôle d’accès défectueux, les conséquences peuvent être catastrophiques : fuites de données, modifications non autorisées du système, etc.
Dans la section suivante, vous découvrirez des exemples de code illustrant différents types de vulnérabilités du contrôle d’accès.
Contrôle d’accès vertical défaillant dans les intergiciels Express
Un type de vulnérabilité du contrôle d’accès concerne les défaillances ou les faiblesses du contrôle d’accès vertical. Il s’agit de situations dans lesquelles un utilisateur ordinaire accède à des fonctionnalités réservées aux administrateurs ou à d’autres privilèges auxquels il ne devrait pas avoir accès. Cet utilisateur franchit ainsi les niveaux de privilèges et peut effectuer des modifications, des suppressions ou d’autres opérations réservées aux administrateurs.
Voici quelques vulnérabilités de code spécifiques susceptibles d’entraîner un contrôle d’accès vertical défaillant :
Panneau d’administration non protégé dans les routes Express
Un panneau d’administration est non protégé lorsque les routes donnant accès aux fonctionnalités d’administration d’une page web ou d’un serveur ne sont protégées par aucun mécanisme d’autorisation :
Dans ce scénario, toute personne qui envoie une requête GET à la route /admin accède automatiquement au message Welcome to the Admin Panel!, qu’elle se soit préalablement connectée ou qu’elle dispose ou non des autorisations nécessaires. Le panneau /admin n’est pas lié à la route /login alors qu’il devrait l’être : il s’agit donc d’une forme de contrôle d’accès défaillant.
Panneau d’administration Express basé sur des paramètres de requête
Un panneau d’administration basé sur des paramètres d’URL est simple à implémenter. Toutefois, sans aucune validation, il peut être assez facile à manipuler :
Dans cet exemple, un utilisateur qui envoie directement une requête GET à la route /admin reçoit la réponse Access denied. Pour contourner ce refus, il suffit d’ajouter ?isAdmin=true à l’URL. Puisque ces paramètres peuvent être ajoutés par n’importe quelle personne accédant au panneau d’administration, la même vulnérabilité que dans le premier exemple persiste : un utilisateur ordinaire peut bénéficier de privilèges d’administrateur.
Contrôle d’accès aux routes Express par l’obscurité
En théorie, on pourrait masquer la route du panneau d’administration en la rendant difficile à deviner, comme dans l’intergiciel de route Express suivant :
Cette méthode semble rendre le panneau d’administration plus sûr, mais elle n’est pas sécurisée et constitue une mauvaise façon de protéger une application. Les pirates peuvent trouver un moyen d’accéder au plan du site pour découvrir tous les points de terminaison d’un site web. Ils peuvent également recourir à des techniques de fuzzing pour tester tous les points de terminaison possibles et observer les réponses, ou tenter d’accéder aux fichiers journaux pour y trouver l’URL permettant d’ouvrir le panneau d’administration. Cette méthode, malgré son apparente ingéniosité, n’apporte aucune sécurité réelle et perpétue une vulnérabilité de contrôle d’accès défaillant.
Journalisation en clair dans les applications Express
Les développeurs doivent également faire preuve de prudence avec les mécanismes de journalisation afin d’éviter de divulguer accidentellement des informations critiques aux utilisateurs de l’application. Par exemple, une application peut consigner une connexion avec des informations sensibles sans supprimer le mot de passe des données du journal :
Remarquez l’instruction console.log en bas. Toute personne ayant accès aux fichiers journaux aurait également accès aux données des utilisateurs et pourrait se connecter en usurpant l’identité de n’importe quel utilisateur disposant de droits d’administration. Il est donc important de ne consigner que les informations nécessaires dans un contexte donné. En outre, il est généralement préférable de s’assurer que personne ne consigne d’informations critiques susceptibles d’aider des pirates à exploiter des données en cas de fuite.
Contrôle d’accès horizontal défaillant dans les intergiciels Express
Alors que les problèmes de contrôle d’accès vertical concernent les situations permettant aux utilisateurs d’élever leurs privilèges, les problèmes de contrôle d’accès horizontal surviennent lorsqu’un utilisateur accède à des ressources ou à des données appartenant à d’autres utilisateurs de même niveau.
Examinons quelques exemples de code illustrant des vulnérabilités du contrôle d’accès horizontal avec le framework web Express pour Node.js.
ID utilisateur transmis dans un paramètre de requête à une route Express
Une application qui affiche l’ID utilisateur dans un paramètre de requête peut poser problème, surtout si les données d’un utilisateur sont accessibles à l’aide de ce même ID dans les paramètres de requête. Il suffit alors de connaître les ID d’autres personnes pour accéder à leurs données.
Par exemple, si votre ID est 123, pour consulter les informations de votre compte sur un site web, vous devez vous rendre à l’adresse www.[website name].com/account?userId=123 :
Dans cet exemple, en envoyant une requête GET à /account avec le paramètre userId=1, vous pouvez facilement récupérer l’objet accountData de logan@test.com, même si vous êtes connecté sous une autre identité. La même requête GET avec le paramètre userId=2 vous donne accès à l’objet accountData de megan@test.com. Il suffit d’utiliser l’ID associé à un utilisateur dans le paramètre de requête pour obtenir l’objet accountData.
Cette vulnérabilité est communément appelée référence directe non sécurisée à un objet (IDOR). Elle est présente en Java, en Ruby et dans d’autres langages de programmation.
ID utilisateur imprévisible transmis dans un paramètre de requête à un intergiciel de route Express
À la lumière de l’exemple précédent, on pourrait penser qu’un contrôle d’accès bien conçu consiste simplement à masquer l’ID utilisateur. Par exemple, l’ID 1 pourrait être modifié, notamment par hachage et encodage, pour devenir 8a76dh3t dans la requête, afin de rendre plus difficile l’accès aux données des autres utilisateurs :
Dans cet exemple, une fonction obfuscateUserId récupère l’ID utilisateur dans la liste des utilisateurs existants et le masque. Pour envoyer une requête GET à la route /account et consulter les informations du compte, il faut donc connaître l’ID masqué et l’inclure dans le paramètre de requête (par exemple, userId=8a76dh3t).
Cette méthode ne repose pas sur des contrôles de sécurité efficaces et ne fait que perpétuer le problème de contrôle d’accès défaillant. Avec suffisamment de temps et de détermination, les pirates peuvent toujours utiliser le fuzzing pour deviner l’ID utilisateur masqué et obtenir l’accès. Vous vous retrouvez alors une nouvelle fois avec un contrôle d’accès défaillant.
Exploitation de l’absence de protection contre les attaques CSRF dans les applications Express
Enfin, les acteurs malveillants peuvent tenter d’exploiter le contrôle d’accès défaillant de votre application Express au moyen d’attaques par falsification de requête intersite (CSRF). En bref, ces attaques créent de fausses pages web ou de faux liens qui vous incitent à transmettre vos informations. Celles-ci sont ensuite intégrées à une fonction qui envoie une requête légitime au site web concerné, où vos données deviennent accessibles.
Sans protection contre les attaques CSRF, toutes les applications serveur présentées en exemple peuvent être intégrées à un faux formulaire sur une page web. L’utilisateur y saisit des données et les envoie, permettant ainsi à un acteur malveillant de les exploiter.
Comment prévenir les vulnérabilités du contrôle d’accès défaillant dans Node.js
Maintenant que vous avez découvert des exemples de vulnérabilités du contrôle d’accès vertical et horizontal, examinons les stratégies générales permettant de les prévenir.
Utilisez les dernières versions des bibliothèques
Pour garantir un contrôle d’accès conforme aux normes les plus strictes, vous pouvez utiliser des packages npm fiables, maintenus et sécurisés. Toutefois, Node.js et son écosystème de packages reçoivent régulièrement des mises à jour qui corrigent des vulnérabilités de sécurité : il est donc essentiel de les maintenir également à jour.
Il est essentiel de maintenir votre environnement d’exécution Node.js et vos packages à jour afin de réduire le risque lié aux problèmes de sécurité connus. Pour cela, vous pouvez vérifier l’état de votre fichier package.json avec Snyk Advisor, qui vous indique quelles bibliothèques présentent des vulnérabilités à corriger, ou si un package npm est obsolète ou n’est plus maintenu.
En glissant-déposant un fichier package.json d’exemple dans Snyk Advisor, vous verrez que ce projet contient plusieurs packages npm potentiellement problématiques :

En y regardant de plus près, Snyk Advisor vous indique que loader n’a pas fait l’objet d’une nouvelle version depuis huit ans et qu’il est peu populaire auprès des utilisateurs npm par rapport à d’autres packages. Vérifier régulièrement les mises à jour et les appliquer rapidement, voire remplacer les bibliothèques obsolètes de votre projet, sont de bonnes premières étapes pour garantir la sécurité de votre contrôle d’accès.
Ne vous fiez pas uniquement à l’obfuscation
Comme vous l’avez vu dans certains exemples d’applications, la sécurité par l’obscurité n’est pas une stratégie fiable. Si un attaquant peut finir par deviner comment obtenir l’accès (ou y parvenir par fuzzing), votre application n’est pas sécurisée. Vous devez mettre en place des mécanismes de contrôle d’accès et des vérifications d’authentification appropriés afin que seuls les utilisateurs autorisés puissent accéder aux fonctionnalités et aux données sensibles.
Dans l’exemple précédent, vous aviez une route dont le point de terminaison utilisait des chiffres difficiles à deviner :
En pratique, il est généralement plus sûr de s’en tenir à la méthode éprouvée qui consiste à protéger les données à l’aide de mécanismes d’authentification adaptés avant d’accorder l’accès. Il est recommandé d’utiliser des bibliothèques de connexion plus sécurisées comme Passport.js ou AWS Cognito. À des fins pédagogiques, voici néanmoins une ébauche de page de connexion sans bibliothèques externes :
Au lieu de masquer la route du panneau d’administration, les utilisateurs peuvent accéder directement à /login, mais ils doivent fournir la bonne adresse e-mail et le bon mot de passe dans le corps de la requête avant d’obtenir l’accès au panneau. Vous ne dépendez ainsi pas de méthodes d’obfuscation risquées et pouvez mieux contrôler les informations et les réponses auxquelles chaque utilisateur a accès.
Refusez l’accès par défaut et accordez des autorisations précises
Lorsque vous déterminez quels utilisateurs doivent accéder aux différents types de données de votre application, il est souvent judicieux de partir de zéro. Adoptez le principe du moindre privilège : refusez d’abord tout accès aux utilisateurs, puis autorisez-les à accéder uniquement aux ressources et aux actions nécessaires.
Vous devez également mettre en place un contrôle d’accès précis, accordé progressivement, afin que les utilisateurs puissent uniquement effectuer les actions qu’ils sont explicitement autorisés à effectuer. Dans l’exemple précédent, l’ajout de rôles peut vous aider à mettre en place un contrôle plus précis :
Ici, les privilèges les plus élevés sont réservés au “Level 3 panel”, accessible uniquement aux utilisateurs ayant le rôle admin. Les autres utilisateurs ayant le rôle manager auront accès au “Level 2 panel” après connexion. Celui-ci peut, par exemple, contenir des informations sur chaque utilisateur, mais ne comporte pas de bouton de suppression.
Toute personne à qui aucun rôle n’a été explicitement attribué recevra automatiquement la réponse “Unauthorized access”. Attribuer des autorisations précises aux utilisateurs et les élargir progressivement si nécessaire vous permet d’éviter d’accorder des privilèges supplémentaires à des utilisateurs qui ne devraient pas y avoir accès.
Effectuez des audits et des tests approfondis
Auditez régulièrement votre base de code et effectuez des tests de sécurité, comme l’analyse statique du code, l’analyse des dépendances et les revues de code sécurisé, afin de repérer les vulnérabilités liées au contrôle d’accès et d’autres problèmes de sécurité. Il peut être utile d’ajouter cette liste (ou une autre) de vulnérabilités potentielles liées au contrôle d’accès à vos favoris et de vous en servir pour vérifier que votre application n’en contient aucune. En outre, ajouter des tests unitaires dans toute votre application est un moyen courant de vérifier que chaque ligne de code fonctionne comme prévu.
Les outils d’analyse automatisée, comme les outils de tests de sécurité des applications statiques (SAST), sont toujours à envisager pour vous aider à repérer les problèmes de sécurité courants. Avec l’extension Snyk pour VS Code, vous bénéficiez rapidement de résultats d’analyse de sécurité lorsque vous enregistrez vos fichiers JavaScript, ainsi que de recommandations de correction automatisées.
Utilisez l’extension Snyk pour Visual Studio Code
Un outil puissant mérite d’être mis en avant : Snyk. Snyk propose plusieurs outils pour sécuriser votre application, et son extension pour Visual Studio (VS) Code peut notamment vous aider à détecter et à corriger les vulnérabilités liées à un contrôle d’accès défaillant dans votre code Node.js, au fil de son écriture.
Voici comment configurer l’extension Snyk et l’utiliser efficacement :
Dans VS Code, accédez à l’onglet Extensions et recherchez « Snyk » pour trouver l’extension Snyk Security - Code, Open Source Dependencies, IaC Configurations. Cliquez sur Install :

Une fois l’extension installée, Snyk vous demandera d’authentifier votre compte en le connectant à votre IDE. Cliquez sur Connect VS Code with Snyk : une page Web externe de Snyk s’ouvrira pour vous demander l’autorisation de vous connecter. Cliquez ensuite sur Authenticate.
Une fois l’authentification effectuée, cliquez sur Scan pour analyser votre code à la recherche de vulnérabilités. Vous pouvez également configurer l’extension selon vos besoins.
À l’aide des exemples précédents de routes /admin, /login et /account, Snyk a détecté douze vulnérabilités de sécurité. De plus, Snyk analyse aussi votre code pour repérer d’éventuels problèmes de qualité, de configuration et de sécurité liés à l’open source, présents dans votre application ou dans les bibliothèques qu’elle utilise :


L’extension Snyk analyse votre code à la recherche de vulnérabilités de sécurité connues, notamment celles liées au contrôle d’accès. Elle fournit des retours en temps réel et suggère des correctifs pour les problèmes détectés. Grâce à cette extension, vous pouvez repérer et corriger les vulnérabilités liées à un contrôle d’accès défaillant avant leur mise en production.
Snyk propose également divers outils d’analyse de code. Comme l’extension VS Code, ces outils sont conçus pour détecter les problèmes de sécurité dans votre code au fil de son écriture. Ils sont donc indispensables pour identifier et corriger les problèmes de contrôle d’accès en temps réel.
Conclusion
Dans cet article, vous avez découvert les défaillances du contrôle d’accès dans Node.js, un problème de sécurité majeur susceptible d’entraîner un accès non autorisé aux données et aux privilèges des applications créées avec le framework Web Express. Des routes Express non protégées vers les panneaux d’administration aux identifiants utilisateur imprévisibles dans les paramètres de requête, les exemples présentés illustrent les risques potentiels liés à un contrôle d’accès défaillant.
Pour prévenir les vulnérabilités liées à un contrôle d’accès défaillant dans vos applications Node.js, vous pouvez mettre en œuvre plusieurs stratégies clés : utiliser les dernières versions des bibliothèques, éviter les méthodes fondées sur la sécurité par l’obscurité, appliquer le principe du moindre privilège, effectuer des audits et des tests approfondis, et tirer parti d’outils tels que l’extension Snyk pour Visual Studio Code. Ensemble, ces méthodes peuvent considérablement renforcer la sécurité de votre application. N’oubliez pas que créer et maintenir une application sécurisée est un processus continu. La vigilance est essentielle pour préserver l’intégrité de vos applications et de vos données.
Utilisez Snyk pour commencer à renforcer votre sécurité dès aujourd’hui !
