Maison > interface Web > js tutoriel > Sécuriser votre application Node.js : un guide complet

Sécuriser votre application Node.js : un guide complet

Patricia Arquette
Libérer: 2024-12-08 14:27:10
original
350 Les gens l'ont consulté

Securing Your Node.js Application: A Comprehensive Guide

Dans le paysage numérique actuel, la sécurisation de votre application Node.js est primordiale. Des leaders mondiaux comme Netflix et Uber aux startups qui créent la prochaine grande nouveauté, Node.js alimente certaines des applications les plus exigeantes et les plus performantes. Cependant, les vulnérabilités de votre application peuvent entraîner un accès non autorisé, des violations de données et une perte de confiance des utilisateurs.

Ce guide combine des pratiques de sécurité pratiques avec les concepts clés du OWASP Web Security Testing Guide (WSTG) pour vous aider à renforcer votre application Node.js. Que vous gériez des opérations en temps réel ou que vous évoluiez vers des millions d'utilisateurs, cette ressource complète garantira que votre application reste sécurisée, fiable et résiliente.


Collecte d'informations (WSTG-INFO)

La

Collecte d'informations est souvent la première étape franchie par un attaquant pour en savoir plus sur votre application. Plus ils peuvent collecter d’informations, plus il leur devient facile d’identifier et d’exploiter les vulnérabilités.

Configuration typique du serveur Express.js et empreintes digitales

Par défaut, Express.js inclut des paramètres qui peuvent révéler par inadvertance des informations sur votre serveur. Un exemple courant est l'en-tête HTTP X-Powered-By, qui indique que votre application utilise Express.

Exemple de code vulnérable :

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans cette configuration, chaque réponse HTTP inclut l'en-tête X-Powered-By: Express.

Problème :

  • Empreintes digitales : Les attaquants peuvent utiliser cet en-tête pour déterminer les technologies que vous utilisez. Savoir que vous utilisez Express leur permet d'adapter les attaques aux vulnérabilités connues dans des versions spécifiques d'Express ou de Node.js.

Atténuation :

Désactivez cet en-tête pour rendre plus difficile aux attaquants l'empreinte digitale de votre serveur.

Code amélioré :

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Atténuation améliorée avec un casque :

Une meilleure approche consiste à utiliser le middleware du casque, qui définit divers en-têtes HTTP pour améliorer la sécurité de votre application.

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Pourquoi utiliser un casque ?

  • En-têtes de sécurité complets : Casque définit plusieurs en-têtes HTTP qui aident à protéger votre application contre les vulnérabilités Web bien connues.
  • Facilité d'utilisation : Avec une seule ligne, vous améliorez considérablement la sécurité de votre application.

Tests de gestion de configuration et de déploiement (WSTG-CONF)

La

Gestion de la configuration et du déploiement sont des aspects critiques de la sécurité des applications. Les mauvaises configurations peuvent servir de portes ouvertes aux attaquants.

Exécution en mode développement en production

L'exécution de votre application en mode développement sur un serveur de production peut exposer des messages d'erreur détaillés et des traces de pile.

Exemple de code vulnérable :

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Dans cette configuration, des messages d'erreur détaillés sont envoyés au client.

Problème :

  • Fuite d'informations : Des messages d'erreur détaillés et des traces de pile peuvent révéler des informations sensibles sur la structure, les dépendances et les chemins de fichiers de votre application.
  • Facilite l'exploitation : Les attaquants peuvent utiliser ces informations pour identifier des vulnérabilités potentielles et élaborer des attaques ciblées.

Atténuation :

Définissez NODE_ENV sur « production » et utilisez des messages d'erreur génériques en production.

Code amélioré :

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Bonnes pratiques :

  • Définissez correctement les variables d'environnement : Assurez-vous que NODE_ENV est défini sur « production » dans votre environnement de production.
  • Journalisation interne : Consigne les erreurs en interne à des fins de débogage sans exposer les détails à l'utilisateur final.

Utilisation d'informations d'identification par défaut ou faibles

L'utilisation d'informations d'identification par défaut ou faibles, telles qu'une simple clé secrète pour signer les jetons Web JSON (JWT), est une erreur de sécurité courante.

Exemple de code vulnérable :

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Clé secrète faible : L'utilisation d'une chaîne simple ou courante telle que « secret » permet aux attaquants de deviner ou de forcer facilement la clé.
  • Secrets codés en dur : Le stockage de secrets directement dans votre code augmente le risque d'exposition si votre base de code est compromise.
  • Faux de jetons : Les attaquants qui connaissent votre clé secrète peuvent falsifier des JWT valides et obtenir un accès non autorisé.

Atténuation :

Utilisez une clé secrète solide et sécurisée et stockez-la en toute sécurité.

Code amélioré :

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Bonnes pratiques :

  • Variables d'environnement : Ne confiez pas de secrets au contrôle de version. Utilisez des variables d'environnement ou des fichiers de configuration qui ne sont pas archivés dans le contrôle de code source.
  • Rotation des secrets : Mettez en œuvre un processus pour effectuer une rotation périodique des secrets.
  • Valider la configuration : Assurez-vous que toutes les variables d'environnement requises sont définies lors du démarrage de l'application.

Tests de gestion des identités (WSTG-IDNT)

La gestion des identités est cruciale pour protéger les comptes d'utilisateurs et empêcher tout accès non autorisé.

Politiques de nom d'utilisateur et énumération de compte faibles

Autoriser les noms d'utilisateur faibles et fournir des messages d'erreur spécifiques peut conduire à des attaques par énumération de comptes.

Exemple de code vulnérable :

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Noms d'utilisateur faibles : Autoriser les noms d'utilisateur courts ou simples augmente le risque de compromission du compte.
  • Énumération des comptes : Des messages d'erreur spécifiques peuvent aider les attaquants à déterminer des noms d'utilisateur valides.

Atténuation :

Implémentez la validation du nom d'utilisateur et utilisez des messages d'erreur génériques.

Code amélioré :

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Validation du nom d'utilisateur : Garantit que les noms d'utilisateur répondent à des critères spécifiques, réduisant ainsi les entrées faibles.
  • Messages d'erreur génériques : Empêchez les attaquants d'identifier des noms d'utilisateur valides via des réponses d'erreur.

Tests d'authentification (WSTG-ATHN)

Les mécanismes d'

Authentification sont essentiels pour vérifier l'identité des utilisateurs et empêcher tout accès non autorisé.

Attaques par force brute sur les mots de passe et 2FA

Le manque de protection permet aux attaquants de deviner des mots de passe ou des codes 2FA grâce à des tentatives répétées.

Exemple de code vulnérable :

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Tentatives de connexion illimitées : Les attaquants peuvent essayer à plusieurs reprises différents mots de passe ou codes 2FA.
  • Faible mise en œuvre de la 2FA : Les codes 2FA statiques ou prévisibles sont vulnérables.

Atténuation :

Mettre en œuvre une limitation du débit et améliorer la sécurité 2FA.

Code amélioré :

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Mesures supplémentaires :

  • Utilisez CAPTCHA après des tentatives infructueuses : Introduisez CAPTCHA après plusieurs tentatives de connexion infructueuses pour vérifier les utilisateurs humains.
  • Utilisez TOTP pour 2FA : Utilisez des mots de passe à usage unique basés sur le temps pour des codes 2FA dynamiques et sécurisés.

Explication :

  • Limitation du taux : Réduit les risques d'attaques automatisées en limitant les tentatives de connexion.
  • 2FA amélioré : Les codes basés sur le temps améliorent la sécurité par rapport aux codes statiques.

Tests d'autorisation (WSTG-ATHZ)

Autorisation garantit que les utilisateurs accèdent uniquement aux ressources qu'ils sont autorisés à utiliser, empêchant ainsi les actions non autorisées.

Références d'objets directs non sécurisés (IDOR)

Les utilisateurs peuvent accéder à des ressources non autorisées en manipulant les identifiants dans les requêtes.

Exemple de code vulnérable :

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Accès non autorisé : Les utilisateurs peuvent accéder aux données qu'ils ne devraient pas accéder en modifiant le paramètre orderId.

Atténuation :

Validez la propriété de la ressource avant de fournir l'accès.

Code amélioré :

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Vérification de propriété : Garantit que la ressource demandée appartient à l'utilisateur authentifié.
  • Contrôle d'accès : Empêche les utilisateurs d'accéder aux données des autres en manipulant les paramètres de la demande.

Tests de gestion de session (WSTG-SESS)

La

La gestion des sessions est essentielle pour maintenir l'état des utilisateurs et garantir des interactions sécurisées.

Jetons sans délai d'expiration

Les jetons qui n'expirent jamais présentent un risque de sécurité s'ils sont compromis.

Exemple de code vulnérable :

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Jetons persistants : Les jetons sans expiration restent valables indéfiniment, augmentant ainsi la fenêtre d'opportunité d'une utilisation abusive.

Atténuation :

Définissez un délai d'expiration sur les jetons.

Code amélioré :

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Expiration du jeton : Limite la période de validité, réduisant ainsi le risque si un jeton est compromis.
  • Meilleures pratiques de sécurité : Le renouvellement régulier des jetons améliore la sécurité globale.

Stockage de jetons non sécurisé

Le stockage des jetons dans localStorage les expose aux attaques de script intersite (XSS).

Exemple de code vulnérable :

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Exposition côté client : Des scripts malveillants peuvent accéder à localStorage, voler des jetons et détourner des sessions.

Atténuation :

Utilisez des cookies HTTP uniquement pour stocker les jetons en toute sécurité.

Code amélioré :

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Cookies HTTP uniquement : Inaccessibles à JavaScript, atténuant les risques XSS.
  • Drapeaux sécurisés et SameSite : Améliorez la protection contre les attaques de type man-in-the-middle et de falsification de requêtes intersites.

Tests de validation des entrées (WSTG-INPV)

La validation des entrées garantit que les données fournies par l'utilisateur sont sûres et attendues, empêchant ainsi les attaques par injection.

Manque de validation des entrées

Accepter et traiter les entrées des utilisateurs sans validation peut entraîner des vulnérabilités.

Exemple de code vulnérable :

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

// Weak secret key
const SECRET_KEY = 'secret';

app.post('/login', (req, res) => {
  // Authenticate user (authentication logic not shown)
  const userId = req.body.userId;

  // Sign the JWT with a weak secret
  const token = jwt.sign({ userId }, SECRET_KEY);
  res.json({ token });
});

app.get('/protected', (req, res) => {
  const token = req.headers['authorization'];

  try {
    // Verify the token using the weak secret
    const decoded = jwt.verify(token, SECRET_KEY);
    res.send('Access granted to protected data');
  } catch (err) {
    res.status(401).send('Unauthorized');
  }
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

Copier après la connexion
Copier après la connexion

Problème :

  • Attaques par injection : Une entrée non validée peut conduire à une injection SQL, une injection NoSQL ou à d'autres attaques par injection de code.

Atténuation :

Validez et désinfectez toutes les entrées utilisateur.

Code amélioré :

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Validation de l'entrée : Vérifie que l'entrée répond aux critères attendus.
  • Nettoyage des entrées : Supprime ou échappe les caractères potentiellement dangereux.
  • Requêtes de base de données sécurisées : L'utilisation de requêtes paramétrées empêche les attaques par injection.

Test de gestion des erreurs (WSTG-ERRH)

Une gestion appropriée des erreurs évite de divulguer des informations sensibles et améliore l'expérience utilisateur.

Exposer des informations d'erreur sensibles

Des messages d'erreur détaillés peuvent révéler les composants internes du système aux attaquants.

Exemple de code vulnérable :

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Divulgation d'informations : Les attaquants peuvent obtenir des informations sur la structure de votre application et les vulnérabilités potentielles.

Atténuation :

Utilisez des messages d'erreur génériques et enregistrez les erreurs détaillées en interne.

Code amélioré :

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Journalisation interne : Conserve les informations détaillées sur les erreurs en toute sécurité.
  • Messages conviviaux : Fournit un message générique sans révéler de détails sensibles.

Test de cryptographie faible (WSTG-CRYP)

La

Cryptographie protège les données sensibles ; l'utilisation de pratiques cryptographiques faibles compromet la sécurité.

Utilisation d'algorithmes de hachage non sécurisés

Le hachage de mots de passe avec des algorithmes obsolètes n'est pas sécurisé.

Exemple de code vulnérable :

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Hachage faible : Les algorithmes comme MD5 et SHA-1 sont vulnérables aux attaques par collision et ne doivent pas être utilisés pour le hachage de mot de passe.

Atténuation :

Utilisez un algorithme de hachage puissant conçu pour les mots de passe.

Code amélioré :

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Bcrypt : Une fonction de hachage robuste qui intègre le salage et plusieurs cycles de hachage.
  • Sécurité des mots de passe : rend impossible aux attaquants l'ingénierie inverse des mots de passe.

Clés secrètes codées en dur

Le stockage des secrets directement dans le code augmente le risque d'exposition.

Exemple de code vulnérable :

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

// Weak secret key
const SECRET_KEY = 'secret';

app.post('/login', (req, res) => {
  // Authenticate user (authentication logic not shown)
  const userId = req.body.userId;

  // Sign the JWT with a weak secret
  const token = jwt.sign({ userId }, SECRET_KEY);
  res.json({ token });
});

app.get('/protected', (req, res) => {
  const token = req.headers['authorization'];

  try {
    // Verify the token using the weak secret
    const decoded = jwt.verify(token, SECRET_KEY);
    res.send('Access granted to protected data');
  } catch (err) {
    res.status(401).send('Unauthorized');
  }
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

Copier après la connexion
Copier après la connexion

Problème :

  • Exposition secrète : Si la base de code est compromise, les secrets codés en dur peuvent être facilement extraits.

Atténuation :

Stockez les secrets dans des variables d'environnement ou des fichiers de configuration sécurisés.

Code amélioré :

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Variables d'environnement : Gardez les secrets hors de la base de code et des systèmes de contrôle de version.
  • Pratiques de sécurité : Réduit le risque d'exposition accidentelle.

Tests de logique métier (WSTG-BUSL)

Des vulnérabilités

Logique métier se produisent lorsque les flux d'applications peuvent être manipulés de manière involontaire.

Abus d'opérations groupées

Les opérations de données sans restriction peuvent entraîner des problèmes de performances ou des fuites de données.

Exemple de code vulnérable :

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Déni de service (DoS) : Les exportations de données volumineuses peuvent épuiser les ressources du serveur.
  • Fuite de données : Un accès illimité peut exposer des informations sensibles.

Atténuation :

Mettre en œuvre des contrôles de pagination et d'accès.

Code amélioré :

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Pagination : Contrôle la quantité de données renvoyées, évitant ainsi l'épuisement des ressources.
  • Contrôle d'accès : garantit que les utilisateurs ne peuvent accéder qu'à leurs propres données.

Tests côté client (WSTG-CLNT)

La protection contre les vulnérabilités côté client est essentielle pour protéger les utilisateurs contre les attaques telles que le Cross-Site Scripting (XSS).

Échapper aux entrées utilisateur à l'aide de la bibliothèque XSS

Une mauvaise gestion des entrées utilisateur dans les scripts côté client peut conduire à des attaques XSS.

Exemple de code vulnérable :

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Manipulation DOM dangereuse : L'insertion d'entrées utilisateur non nettoyées dans innerHTML permet l'exécution de scripts malveillants.

Atténuation :

Utilisez la bibliothèque XSS pour nettoyer les entrées de l'utilisateur avant le rendu.

Code amélioré :

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Nettoyage des entrées : La bibliothèque XSS nettoie les entrées en échappant ou en supprimant le contenu potentiellement dangereux.
  • Prévention de l'exécution des scripts : Neutralise les scripts malveillants, les empêchant de s'exécuter dans le navigateur.

Bonnes pratiques :

  • Utilisez textContent lorsque cela est possible : L'attribution d'une entrée utilisateur à textContent la traite comme du texte brut.
const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
  • Combinez la validation côté client et côté serveur : Une approche de défense en profondeur améliore la sécurité.

Tests API (WSTG-APIT)

La sécurisation des points de terminaison de l'API est cruciale pour éviter les fuites de données et les accès non autorisés.

Exposition d'introspection GraphQL

Quitter l'introspection GraphQL activée en production révèle votre schéma API.

Exemple de code vulnérable :

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Divulgation du schéma : Les attaquants peuvent explorer le schéma de votre API, ce qui facilite la création d'attaques ciblées.

Atténuation :

Désactivez l'introspection dans les environnements de production.

Code amélioré :

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Introspection conditionnelle : Permet l'introspection pendant le développement mais la désactive en production.
  • Amélioration de la sécurité : Réduit la surface d'attaque en masquant les détails du schéma.

Complexité des requêtes sans restriction

Les requêtes profondément imbriquées ou complexes peuvent épuiser les ressources du serveur.

Exemple de code vulnérable :

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Problème :

  • Déni de service (DoS) : Les requêtes complexes peuvent entraîner une utilisation élevée du processeur et de la mémoire.

Atténuation :

Limiter la profondeur et la complexité des requêtes.

Code amélioré :

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Explication :

  • Limitation de la profondeur : restreint la profondeur des requêtes pour éviter l'épuisement des ressources.
  • Protection des performances : Garantit que l'API reste réactive et disponible.

Conclusion

Sécuriser votre application Node.js implique une approche à plusieurs niveaux :

  • Prévenir les fuites d'informations : Nettoyer le code et les configurations du serveur pour éviter d'exposer les données sensibles.
  • Gérer les configurations en toute sécurité : Supprimez les informations d'identification par défaut et sécurisez les fichiers de configuration.
  • Valider et nettoyer les entrées : Ne faites jamais confiance aux entrées des utilisateurs.
  • Mettez en œuvre une authentification et une autorisation appropriées : Assurez-vous que les utilisateurs disposent d'un accès approprié.
  • Utilisez une cryptographie forte : Protégez les données avec des algorithmes sécurisés et une gestion des clés.
  • Gérez les erreurs avec élégance : Évitez de révéler des informations sensibles.
  • Protégez les interactions côté client : Atténuez les attaques XSS et autres attaques basées sur le navigateur.
  • API sécurisées : Contrôlez l'exposition des données et appliquez une limitation de débit.

En intégrant ces pratiques, vous améliorez la sécurité de votre application, protégez les données des utilisateurs et maintenez la confiance.


Lectures complémentaires

  • Guide de test de sécurité Web OWASP (WSTG) : OWASP WSTG
  • Guide de sécurité Node.js : Sécurité Node.js
  • Conseils de sécurité Express.js : Meilleures pratiques de sécurité Express.
  • Meilleures pratiques de sécurité GraphQL : Sécurité Apollo GraphQL
  • Top dix OWASP : Top dix OWASP
  • MDN Web Docs - Sécurité Web : MDN Web Security

Remarque : ce guide fournit des recommandations générales. Pour des problèmes de sécurité spécifiques, consultez un professionnel.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal