Qu'est-ce que l'OWASP Top 10

L'OWASP (Open Worldwide Application Security Project) publie depuis 2003 une liste des 10 risques de sécurité les plus critiques pour les applications web. Cette liste est mise ? jour tous les 3 : 4 ans sur la base de données réelles de compromission. En 2026, la version 2021 reste la référence.

Ce n'est pas une liste exhaustive de toutes les vulnérabilités possibles ? c'est une sélection des risques les plus répandus et les plus impactants, ceux que chaque développeur devrait connaêtre et savoir éviter.

A01 : Broken Access Control

A01:2021
Contr?le d'accès défaillant
● Critique

Le contrôle d'accès d?finit ce que les utilisateurs peuvent et ne peuvent pas faire. Quand il est défaillant, des utilisateurs non autorisés peuvent accéder ? des données ou fonctions réservées ? d'autres.

Exemple vulnérable ? IDOR (Insecure Direct Object Reference)

// ❌ Dangereux : n'importe qui peut voir la commande de n'importe qui
app.get('/api/orders/:id', async (req, res) => {
  const order = await Order.findById(req.params.id);
  res.json(order);
});

Correction

// ✅ Correct : on vérifie que la commande appartient ? l'utilisateur connecté
app.get('/api/orders/:id', authenticate, async (req, res) => {
  const order = await Order.findOne({
    _id: req.params.id,
    userId: req.user.id  // l'utilisateur ne peut voir que SES commandes
  });
  if (!order) return res.status(404).json({ error: 'Non trouv?' });
  res.json(order);
});

A02 : Cryptographic Failures

A02:2021
D?faillances cryptographiques
● Critique

Les données sensibles mal chiffrées (ou pas chiffrées du tout) exposent vos utilisateurs ? des fuites catastrophiques. Les erreurs les plus courantes : stocker des mots de passe en MD5 ou SHA1, utiliser HTTP au lieu de HTTPS, transmettre des données sensibles en clair.

// ❌ Dangereux : MD5 est cassé, ne jamais l'utiliser pour les mots de passe
const hashedPassword = crypto.createHash('md5').update(password).digest('hex');

// ✅ Correct : bcrypt avec un coût suffisant (min 12)
const bcrypt = require('bcrypt');
const hashedPassword = await bcrypt.hash(password, 12);

// Vérification
const isValid = await bcrypt.compare(inputPassword, hashedPassword);

A03 : Injection

A03:2021
Injection (SQL, NoSQL, commande)
● Critique

L'injection consiste ? insérer du code malveillant dans une requête interprétée par le système. L'injection SQL est la plus connue, mais les injections NoSQL, de commandes shell, et LDAP sont tout aussi dangereuses.

// ❌ Dangereux : concaténation directe de l'input utilisateur
const query = `SELECT * FROM users WHERE email = '${req.body.email}'`;
// Input malveillant : ' OR '1'='1 : expose tous les utilisateurs

// ✅ Correct : requêtes paramétrées
const query = 'SELECT * FROM users WHERE email = ';
const [rows] = await db.execute(query, [req.body.email]);

// ✅ Correct avec un ORM
const user = await User.findOne({ where: { email: req.body.email } });

A04 : Insecure Design

A04:2021
Conception non sécurisée
● Élev?

Certaines vulnérabilités ne viennent pas d'un bug de code mais d'une mauvaise conception. Exemple classique : une fonctionnalité de reset de mot de passe qui utilise une question secrète (facilement devinable) au lieu d'un lien ? usage unique.

Principe : Pensez ? la sécurité dès la conception, pas après. La question ? poser : "Que se passe-t-il si un utilisateur malveillant utilise cette fonctionnalité de façon inattendue "

A05 : Security Misconfiguration

A05:2021
Mauvaise configuration de sécurité
● Élev?

Les mauvaises configurations sont les vulnérabilités les plus fréquentes et les plus évitables : mots de passe par défaut, ports ouverts inutilement, messages d'erreur qui exposent la stack trace, headers de sécurité HTTP absents.

// ✅ Headers de sécurité essentiels (avec Helmet.js en Node)
const helmet = require('helmet');
app.use(helmet());

// Ce que Helmet configure automatiquement :
// Content-Security-Policy
// X-Frame-Options: DENY
// X-Content-Type-Options: nosniff
// Strict-Transport-Security (HSTS)
// Referrer-Policy

// ✅ Ne jamais exposer les détails d'erreur en production
app.use((err, req, res, next) => {
  console.error(err); // logger en interne
  res.status(500).json({
    error: process.env.NODE_ENV === 'production'
       'Erreur interne'
      : err.message  // détails seulement en dev
  });
});

A06 : Vulnerable Components

A06:2021
Composants vulnérables et obsolètes
● Élev?

Vos dépendances npm, pip, ou Maven peuvent contenir des vulnérabilités connues. L'attaque Log4Shell en 2021 (CVE-2021-44228) a compromis des millions de serveurs via une bibliothèque Java utilisée par presque tout le monde.

# Vérifier les vulnérabilités connues dans vos dépendances
npm audit
npm audit fix  # corriger automatiquement les moins risquées

# Python
pip install safety
safety check

# Automatiser avec GitHub Dependabot ou Snyk dans votre CI/CD

A07 : Authentication Failures

A07:2021
Échecs d'identification et d'authentification
● Critique

Mots de passe trop simples acceptés, pas de protection contre le brute force, tokens de session prévisibles, pas de MFA sur les comptes sensibles : les failles d'authentification donnent accès direct aux données de vos utilisateurs.

// ✅ Politique de mot de passe robuste
function validatePassword(password) {
  if (password.length < 12) throw new Error('Minimum 12 caract?res');
  if (!/[A-Z]/.test(password)) throw new Error('Au moins une majuscule');
  if (!/[0-9]/.test(password)) throw new Error('Au moins un chiffre');
  // Vérifier contre les listes de mots de passe courants
  if (commonPasswords.includes(password.toLowerCase()))
    throw new Error('Mot de passe trop courant');
}

// ✅ Verrouillage progressif anti-brute force
const loginAttempts = new Map();
async function handleLogin(email, password) {
  const key = email;
  const attempts = loginAttempts.get(key) || { count: 0, lastAttempt: 0 };
  const delay = Math.pow(2, attempts.count) * 1000; // délai exponentiel
  if (Date.now() - attempts.lastAttempt < delay)
    throw new Error('Trop de tentatives, réessayez plus tard');
  // ... v?rification du mot de passe
}

A08 : Software Integrity Failures

A08:2021
D?faillances d'intégrité logicielle
● Élev?

Désérialisation de données non vérifiées, mise ? jour automatique sans v?rification de signature, pipeline CI/CD non sécurisé : si votre code ou vos mises ? jour peuvent être altérés par un tiers, vous êtes vulnérable aux attaques supply chain.

Exemple réel : L'attaque SolarWinds (2020) a compromis des milliers d'organisations via une mise ? jour logicielle légitime contenant du code malveillant. Vérifiez toujours les signatures de vos dépendances.

A09 : Logging Failures

A09:2021
D?faillances de journalisation et de surveillance
● Élev?

Sans logs, vous ne saurez jamais qu'une attaque est en cours ou qu'elle a eu lieu. La durée moyenne de détection d'une intrusion est de 206 jours. De bons logs permettent de détecter les attaques, d'analyser les incidents, et de prouver la conformité.

// ✅ Logger les événements de sécurité essentiels
const securityLogger = {
  loginSuccess: (userId, ip) =>
    logger.info('AUTH_SUCCESS', { userId, ip, timestamp: new Date() }),
  loginFailure: (email, ip) =>
    logger.warn('AUTH_FAILURE', { email, ip, timestamp: new Date() }),
  accessDenied: (userId, resource) =>
    logger.warn('ACCESS_DENIED', { userId, resource, timestamp: new Date() }),
  suspiciousActivity: (details) =>
    logger.error('SUSPICIOUS', { ...details, timestamp: new Date() })
};

// ?️ Ne jamais logger : mots de passe, tokens, données personnelles sensibles

A10 : SSRF

A10:2021
Server-Side Request Forgery (SSRF)
● Élev?

La SSRF permet ? un attaquant de forcer votre serveur ? faire des requêtes vers des ressources internes normalement inaccessibles depuis l'extérieur (m?tadonnées AWS, services internes, etc.).

// ❌ Dangereux : votre serveur fait des requêtes vers n'importe quelle URL
app.get('/preview', async (req, res) => {
  const response = await fetch(req.query.url);  // l'attaquant peut mettre http://169.254.169.254/
  res.send(await response.text());
});

// ✅ Correct : valider et filtrer les URLs autorisées
const ALLOWED_HOSTS = ['api.exemple.com', 'cdn.exemple.com'];
app.get('/preview', async (req, res) => {
  const url = new URL(req.query.url);
  if (!ALLOWED_HOSTS.includes(url.hostname))
    return res.status(403).json({ error: 'Host non autoris?' });
  const response = await fetch(url.toString());
  res.send(await response.text());
});

CyberGuard détecte les tentatives d'exploitation en temps réel

Injection SQL, XSS, IDOR, SSRF : CyberGuard analyse le trafic de vos applications et bloque les tentatives d'exploitation avant qu'elles n'atteignent votre code ? même les zero-days.

Essayer gratuitement 15 jours

Synthèse

L'OWASP Top 10 couvre les risques les plus répandus, mais la sécurité web est un domaine vaste. La bonne nouvelle : en appliquant les corrections présentées dans ce guide, vous éliminez la grande majorité des vecteurs d'attaque que les attaquants opportunistes utilisent. Chaque ligne de code sécurisée réduit la surface d'attaque de votre application.