Meilleures pratiques de production : Sécurité
Le terme “production” désigne l’étape du cycle de vie du logiciel quand une application ou une API est généralement disponible pour ses utilisateurs finaux ou ses consommateurs. Par contre, dans l’étape “développement”, vous êtes toujours en train d’écrire et de tester du code, et l’application n’est pas ouverte à un accès externe. Les environnements système correspondants sont respectivement les environnements production et development.
Les environnements de développement et de production sont généralement mis en place différemment et ont des exigences très différentes. Ce qui est bon dans le développement peut ne pas être acceptable dans la production. Par exemple, dans un environnement de développement, vous pouvez vouloir une journalisation détaillée des erreurs pour le débogage, alors que le même comportement peut devenir une préoccupation de sécurité dans un environnement de production. Et en matière de développement, vous n’avez pas à vous soucier de l’évolutivité, de la fiabilité et de la performance, alors que ces préoccupations deviennent cruciales dans la production.
Si vous pensez avoir découvert une faille de sécurité dans Express, veuillez consulter [Politiques et procédures de sécurité de sécurité [/en/resources/contributing#security-policies-and-procedures).
Les meilleures pratiques de sécurité pour les applications Express en production comprennent:
- Meilleures pratiques de production : Sécurité
- Overview
- [Ne pas utiliser de versions obsolètes ou vulnérables d’Express] (#dont-use-deprecated-or-vulnerable-versions-of-express)
- Utiliser TLS
- Ne pas faire confiance à la saisie de l’utilisateur
- Utiliser le casque
- Réduire l’empreinte digitale
- (#use-cookies-securely)
- Ne pas utiliser le nom du cookie de session par défaut
- (#set-cookie-security-options)
- [Empêcher les attaques par force brute contre l’autorisation] (#prevent-brute-force-attacks-against-authorization)
- Assurez-vous que vos dépendances sont sécurisées
- [Éviter les autres vulnérabilités connues] (#avoid-other-known-vulnerabilities)
- Considérations supplémentaires
Ne pas utiliser les versions obsolètes ou vulnérables de Express
Express 2.x et 3.x ne sont plus maintenus. Les problèmes de sécurité et de performance dans ces versions ne seront pas résolus. Ne les utilisez pas ! Si vous n’avez pas déménagé vers la version 4, suivez le [guide de migration] (/en/guide/migrating-4) ou envisagez [Options de support commercial] (/en/support#commercial-support-options).
Assurez-vous également que vous n’utilisez aucune des versions vulnérables Express listées sur la page [Mise à jour de sécurité] (/en/advanced/security-updates). Si vous l’êtes, mettez à jour vers l’une des versions stables, de préférence la plus récente.
Utiliser TLS
Si votre application traite ou transmet des données sensibles, utilisez Transport Layer Security (TLS) pour sécuriser la connexion et les données. Cette technologie crypte les données avant qu’elles ne soient envoyées du client au serveur, empêchant ainsi certains hacks courants (et faciles). Bien que les requêtes Ajax et POST puissent ne pas être visiblement évidentes et semblent “cachées” dans les navigateurs, leur trafic réseau est vulnérable à [sniffing de paquets] (https://en.wikipedia.org/wiki/Packet_analyzer) et aux [attaques de l’homme au milieu] (https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
Il se peut que vous soyez familier avec le cryptage Secure Socket Layer (SSL) . TLS est simplement la prochaine progression de SSL. En d’autres termes, si vous utilisiez SSL auparavant, envisagez la mise à niveau vers TLS. En général, nous recommandons à Nginx de gérer les TLS. Pour une bonne référence pour configurer TLS sur Nginx (et d’autres serveurs), voir [Configurations de serveur recommandées (Mozilla Wiki)] (https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Server_Configurations).
De plus, un outil pratique pour obtenir un certificat TLS gratuit est Let’s Encrypt, un outil gratuit, automatisé, et l’autorité de certification ouverte (CA) fournie par le Internet Security Research Group (ISRG).
Ne pas faire confiance à la saisie de l’utilisateur
Pour les applications Web, l’une des exigences de sécurité les plus importantes est la validation et la gestion des entrées des utilisateurs. Cela se présente sous de nombreuses formes et nous ne les couvrirons pas tous. En fin de compte, la responsabilité de valider et de gérer correctement les types de saisie que votre application accepte est la vôtre.
Empêcher les redirections ouvertes
Un exemple de saisie potentiellement dangereuse de l’utilisateur est une redirection _ouverte, où une application accepte une URL comme entrée utilisateur (souvent dans la requête URL, par exemple ? rl=https://exemple. ) et utilise res.redirectpour définir l'en-têtelocation` et
retourne un statut 3xx.
Une application doit valider qu’elle prend en charge la redirection vers l’URL entrante pour éviter d’envoyer des utilisateurs à des liens malveillants tels que des sites Web d’hameçonnage, entre autres risques.
Voici un exemple de vérification des URLs avant d’utiliser res.redirect ou res.location:
app.use((req, res) => { try { if (new Url(req.query.url).host !== 'example.com') { return res.status(400).end(`Unsupported redirect to host: ${req.query.url}`); } } catch (e) { return res.status(400).end(`Invalid url: ${req.query.url}`); } res.redirect(req.query.url);});Utiliser le Casque
Helmet peut aider à protéger votre application contre certaines vulnérabilités Web bien connues en définissant correctement les en-têtes HTTP.
Helmet est une fonction middleware qui définit les en-têtes de réponse HTTP liés à la sécurité. Le casque définit par défaut les en-têtes suivants :
Content-Security-Policy: Une puissante liste de ce qui peut se passer sur votre page qui atténue de nombreuses attaquesCross-Origin-Opener-Policy: Aide à isoler votre pageCross-Origin-Resource-Policy: empêche les autres de charger vos ressources cross-originOrigin-Agent-Cluster: Modifie l’isolement du processus pour qu’il soit basé sur l’origineReferrer-Policy: contrôle l’en-têteRefererStrict-Transport-Security: dit aux navigateurs de préférer HTTPSX-Content-Type-Options: évite sniffing MIMEX-DNS-Prefetch-Control: contrôle le préchargement DNSX-Download-Options: force les téléchargements à être sauvegardés (Internet Explorer uniquement)X-Frame-Options: En-tête hérité qui atténue les attaques ClickjackingX-Permitted-Cross-Domain-Policies: Contrôle le comportement inter-domaine pour les produits Adobe, comme AcrobatX-Powered-By: Informations sur le serveur web. Supprimé parce qu’il peut être utilisé dans des attaques simplesX-XSS-Protection: L’en-tête hérité qui tente d’atténuer les attaques XSS, mais rend les choses pires, alors le casque le désactive
Chaque en-tête peut être configuré ou désactivé. Pour en savoir plus à ce sujet, veuillez vous rendre sur son site de documentation.
Installer le casque comme n’importe quel autre module :
$ npm install helmetEnsuite, pour l’utiliser dans votre code:
// ...
const helmet = require('helmet');app.use(helmet());
// ...Réduire la prise d’empreintes digitales
It can help to provide an extra layer of security to reduce the ability of attackers to determine the software that a server uses, known as “fingerprinting.” Bien que ce ne soit pas un problème de sécurité en soi, réduisant la capacité d’empreinte digitale d’une application améliore sa position globale de sécurité. Le logiciel serveur peut être imprimé par des empreintes digitales dans la manière dont il répond à des requêtes spécifiques, par exemple dans les en-têtes de réponse HTTP.
By default, Express sends the X-Powered-By response header that you can
disable using the app.disable() method:
app.disable('x-powered-by');Désactiver l’en-tête `X-Powered-By n’empêche pas un attaquant sophistiqué de déterminer qu’une application exécute Express. Cela peut décourager une exploitation occasionnelle, mais il existe d’autres moyens pour de déterminer si une application exécute Express.
Express envoie également ses propres messages formatés “404 Not Found” et les messages d’erreur de formatteur de réponse. Celles-ci peuvent être modifiées par ajouter votre propre gestionnaire non trouvé et écrire votre propre gestionnaire d’erreur :
// last app.use calls right before app.listen():
// custom 404app.use((req, res, next) => { res.status(404).send("Sorry can't find that!");});
// custom error handlerapp.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('Something broke!');});Utiliser les cookies en toute sécurité
Pour vous assurer que les cookies n’ouvrent pas votre application aux exploitations, n’utilisez pas le nom des cookies de session par défaut et définissez les options de sécurité des cookies de manière appropriée.
Il y a deux principaux modules de session de cookies du middleware :
- express-session qui remplace le middleware
express.sessionintégré à Express 3.x. - cookie-session qui remplace le middleware
express.cookieSessionintégré à Express 3.x.
La principale différence entre ces deux modules est la façon dont ils enregistrent les données de session des cookies. Le middleware express-session stocke les données de session sur le serveur ; il n’enregistre que l’ID de session dans le cookie lui-même, pas les données de session. Par défaut, il utilise du stockage en mémoire et n’est pas conçu pour un environnement de production. En production, vous devrez configurer un magasin de session évolutif ; voir la liste des [magasins de sessions compatibles] (https://github.com/expressjs/session#compatible-session-stores).
En revanche, cookie-session middleware implémente un stockage soutenu par des cookies : il sérialise la session entière au cookie, plutôt qu’une simple clé de session. Ne l’utilisez que lorsque les données de session sont relativement petites et facilement encodées en tant que valeurs primitives (plutôt que d’objets). Bien que les navigateurs soient supposés supporter au moins 4096 octets par cookie, pour vous assurer de ne pas dépasser la limite, ne pas dépasser une taille de 4093 octets par domaine. Sachez également que les données des cookies seront visibles par le client, donc s’il y a une raison de le garder sécurisé ou obscur, alors express-session pourrait être un meilleur choix.
Ne pas utiliser le nom du cookie de session par défaut
Utiliser le nom par défaut des cookies de session peut ouvrir votre application à des attaques. Le problème de sécurité posé est similaire à X-Powered-By: un attaquant potentiel peut l’utiliser pour empreinte digitale le serveur et les attaques ciblées en conséquence.
Pour éviter ce problème, utilisez des noms génériques de cookies; par exemple en utilisant express-session middleware:
const session = require('express-session');app.set('trust proxy', 1); // trust first proxyapp.use( session({ secret: 's3Cur3', name: 'sessionId', }));Définir les options de sécurité des cookies
Définissez les options suivantes des cookies pour améliorer la sécurité :
secure- Permet au navigateur d’envoyer le cookie uniquement via HTTPS.httpOnly- Assure que le cookie est envoyé uniquement sur HTTP(S), et non sur le JavaScript du client, aidant à se protéger contre les attaques de scripts intersites.domain- indique le domaine du cookie; utilisez-le pour comparer avec le domaine du serveur dans lequel l’URL est demandée. S’ils correspondent alors vérifiez l’attribut path suivant.path- indique le chemin du cookie; utilisez-le pour comparer le chemin de la requête. Si cela et le domaine correspondent, alors envoyez le cookie dans la requête.expires- utiliser pour définir la date d’expiration des cookies persistants.
Voici un exemple utilisant cookie-session middleware:
const session = require('cookie-session');const express = require('express');const app = express();
const expiryDate = new Date(Date.now() + 60 * 60 * 1000); // 1 hourapp.use( session({ name: 'session', keys: ['key1', 'key2'], cookie: { secure: true, httpOnly: true, domain: 'example.com', path: 'foo/bar', expires: expiryDate, }, }));Empêcher les attaques par force brute contre l’autorisation
Assurez-vous que les terminaux de connexion sont protégés pour rendre les données privées plus sécurisées.
Une technique simple et puissante est de bloquer les tentatives d’autorisation à l’aide de deux mesures :
- Le nombre de tentatives échouées consécutives par le même nom d’utilisateur et adresse IP.
- Le nombre de tentatives échouées depuis une adresse IP sur une longue période. Par exemple, bloquer une adresse IP si elle fait 100 tentatives échouées en un jour.
rate-limiter-flexible package provides tools to make this technique easy and fast. Vous pouvez trouver [un exemple de protection brute dans la documentation] (https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#login-endpoint-protection)
Assurez-vous que vos dépendances sont sécurisées
Utiliser npm pour gérer les dépendances de votre application est puissant et pratique. Mais les paquets que vous utilisez peuvent contenir des vulnérabilités de sécurité critiques qui pourraient également affecter votre application. La sécurité de votre application est aussi forte que le « lien le plus faible » dans vos dépendances.
Depuis npm@6, npm vérifie automatiquement chaque demande d’installation. Vous pouvez également utiliser npm audit pour analyser votre arborescence des dépendances.
$ npm auditSi vous voulez être plus sécurisé, considérez Snyk.
Snyk offre à la fois un [outil de ligne de commande] (https://www.npmjs.com/package/snyk) et une intégration Github qui vérifie votre application contre [la base de données de vulnérabilité open source] (https://snyk.io/vuln/) pour toutes les vulnérabilités connues dans vos dépendances. Installez le CLI comme suit:
$ npm install -g snyk$ cd your-appUtilisez cette commande pour tester les vulnérabilités de votre application :
$ snyk testÉviter les autres vulnérabilités connues
Gardez un œil sur Node Security Project ou Snyk qui peuvent affecter Express ou d’autres modules que votre application utilise. En général, ces bases de données sont d’excellentes ressources pour la connaissance et les outils sur la sécurité des nœuds.
Enfin, les applications Express—comme toutes les autres applications web—peuvent être vulnérables à diverses attaques sur le Web. Familiarisez-vous avec les [vulnérabilités web connues] (https://www.owasp.org/www-project-top-ten/) et prenez des précautions pour les éviter.
Considérations supplémentaires
Voici quelques autres recommandations de l’excellent Liste de contrôle de sécurité Node.js. Reportez-vous à cet article de blog pour tous les détails sur ces recommandations :
- Filtrer et nettoyer toujours les entrées de l’utilisateur pour se protéger contre les attaques de script intersite (XSS) et d’injection de commandes.
- Protégez contre les attaques d’injection SQL en utilisant des requêtes paramétrées ou des requêtes préparées.
- Utilisez l’outil sqlmap pour détecter les vulnérabilités d’injection SQL dans votre application.
- Utilisez les outils nmap et sslyze pour tester la configuration de vos codes SSL, , et renégociation ainsi que la validité de votre certificat.
- Utilisez safe-regex pour vous assurer que vos expressions régulières ne sont pas susceptibles d’attaques déni de service d’expression régulière.