Guides Cloud & Infra

Sécurité applicative : le top 10 OWASP appliqué à votre code (avec exemples)

Le top 10 OWASP expliqué concrètement avec des exemples de code vulnérable et corrigé. Guide pratique de sécurité applicative pour développeurs et architectes.

8 min de lecture mars 2026
sécuritéowaspapplicationvulnérabilitécodearchitecturedevops

La sécurité n’est pas un audit annuel — c’est une discipline quotidienne

Votre application tourne en production. Les utilisateurs sont contents. Le business croît. Et quelque part, un script automatisé teste méthodiquement chaque endpoint de votre API à la recherche d’une faille.

La question n’est pas si votre application sera attaquée. C’est quand. Et quand ça arrivera, la différence entre un incident mineur et une catastrophe tiendra à la qualité de votre code.

Le Top 10 OWASP est la référence mondiale des vulnérabilités applicatives. Mais entre la documentation théorique et la réalité du code, il y a un gouffre. Voici comment ces vulnérabilités se manifestent concrètement — et comment les éliminer.

A01 : Broken Access Control — la faille numéro 1

La vulnérabilité la plus fréquente et la plus dangereuse. Un utilisateur accède à des ressources qui ne lui appartiennent pas.

L’exemple classique — l’IDOR (Insecure Direct Object Reference) :

// VULNÉRABLE — l'utilisateur change l'ID dans l'URL
app.get('/api/orders/:orderId', async (req, res) => {
  const order = await db.orders.findById(req.params.orderId);
  res.json(order); // N'importe qui peut voir n'importe quelle commande
});

// CORRIGÉ — vérification que la commande appartient à l'utilisateur
app.get('/api/orders/:orderId', async (req, res) => {
  const order = await db.orders.findOne({
    _id: req.params.orderId,
    userId: req.user.id // Filtre par utilisateur authentifié
  });
  if (!order) return res.status(404).json({ error: 'Not found' });
  res.json(order);
});

Règle : chaque requête qui accède à une ressource doit vérifier que l’utilisateur authentifié a le droit d’y accéder. Pas de raccourci, pas d’exception.

A02 : Cryptographic Failures — les données exposées

Données sensibles stockées en clair, transmises sans chiffrement, ou chiffrées avec des algorithmes obsolètes.

Les erreurs que nous voyons régulièrement :

  • Mots de passe hashés en MD5 ou SHA-1 (utilisez bcrypt ou Argon2)
  • Tokens API stockés en clair dans la base de données
  • Communications inter-services en HTTP au lieu de HTTPS, même en réseau interne
  • Clés de chiffrement codées en dur dans le code source
// VULNÉRABLE — hash MD5, sans sel
const passwordHash = md5(password);

// CORRIGÉ — bcrypt avec coût adaptatif
const passwordHash = await bcrypt.hash(password, 12);

Règle : tout ce qui est sensible doit être chiffré au repos et en transit. Les clés et secrets vivent dans un gestionnaire de secrets (Vault, AWS Secrets Manager, GCP Secret Manager), jamais dans le code.

A03 : Injection — le classique qui persiste

Les injections SQL ont 25 ans et restent dans le top 3. Pourquoi ? Parce que la concaténation de chaînes est plus rapide que les requêtes paramétrées.

// VULNÉRABLE — injection SQL directe
const query = `SELECT * FROM users WHERE email = '${email}'`;

// CORRIGÉ — requête paramétrée
const query = 'SELECT * FROM users WHERE email = $1';
const result = await db.query(query, [email]);

Au-delà du SQL, les injections touchent aussi :

  • NoSQL : les requêtes MongoDB avec des objets non validés
  • LDAP : les authentifications via annuaire
  • OS command : les appels système avec des paramètres utilisateur
  • Template : les moteurs de template qui évaluent du code

Règle : ne faites jamais confiance aux données venant de l’extérieur. Validez, assainissez, paramétrez.

A04 : Insecure Design — le défaut d’architecture

Nouvelle entrée dans le Top 10, et probablement la plus importante. Ce n’est pas un bug de code — c’est un défaut de conception.

Exemples concrets :

  • Un système de récupération de mot de passe qui pose des “questions secrètes” facilement devinables
  • Un panier e-commerce qui fait confiance au prix envoyé par le front-end
  • Un système de vote qui ne limite pas le nombre de votes par utilisateur
  • Une API de réinitialisation de mot de passe qui ne rate-limite pas les tentatives

La solution : intégrer la sécurité dès la phase de conception. Chez Les Artisans du Digital, chaque architecture passe par une revue de menaces (threat modeling) avant le premier commit. On identifie les surfaces d’attaque, les données sensibles, les flux critiques — et on conçoit les protections en amont, pas en rustine.

A05 : Security Misconfiguration — la porte ouverte

La configuration par défaut est rarement sécurisée :

  • Headers HTTP de sécurité absents (CSP, X-Frame-Options, HSTS)
  • Stack traces visibles en production
  • Comptes admin par défaut actifs
  • Services cloud avec accès public non intentionnel
  • CORS configuré en * sur une API authentifiée
// Configuration express sécurisée minimale
app.use(helmet()); // Headers de sécurité
app.use(cors({
  origin: ['https://monsite.fr'],
  credentials: true
}));
app.disable('x-powered-by');

// En production, JAMAIS de stack trace
app.use((err, req, res, next) => {
  console.error(err); // Log interne
  res.status(500).json({ error: 'Internal server error' }); // Réponse client
});

Règle : maintenez une checklist de sécurité pour chaque déploiement. Automatisez les vérifications avec des outils comme tfsec, Checkov ou ScoutSuite.

A06 : Vulnerable Components — la supply chain attack

Votre application utilise des centaines de dépendances. Chacune est un vecteur d’attaque potentiel.

Les actions concrètes :

  • npm audit / yarn audit dans votre CI/CD — bloquant en cas de vulnérabilité critique
  • Dependabot ou Renovate pour les mises à jour automatiques
  • Snyk ou Socket pour l’analyse approfondie des dépendances
  • Auditez les nouvelles dépendances avant de les ajouter (popularité, maintenance, contributeurs)

Règle : chaque dépendance est un engagement de maintenance. Minimisez le nombre de dépendances. Préférez les bibliothèques bien maintenues avec une communauté active.

A07 : Authentication Failures — le maillon faible

L’authentification est souvent le premier point d’entrée d’une attaque :

  • Brute force : pas de rate limiting sur le login
  • Credential stuffing : réutilisation de mots de passe fuités
  • Session fixation : identifiant de session prévisible ou non régénéré après login

Les protections essentielles :

  • Rate limiting sur tous les endpoints d’authentification (5 tentatives/minute)
  • MFA (authentification multi-facteurs) pour les comptes à privilèges
  • Rotation des tokens de session après chaque changement de privilège
  • Invalidation serveur-side des sessions (pas seulement côté client)

A08 : Software and Data Integrity Failures

Votre pipeline CI/CD est-elle sécurisée ? Vos mises à jour sont-elles signées ? Vos données sérialisées sont-elles validées ?

Le risque concret : un attaquant qui compromet votre pipeline de déploiement peut injecter du code malveillant dans votre application. C’est la supply chain attack appliquée à votre propre infrastructure.

Les protections :

  • Signez vos artifacts de build
  • Vérifiez l’intégrité des images Docker (digest, pas tag)
  • Protégez vos secrets CI/CD (pas dans les variables d’environnement en clair)
  • Revoyez les accès aux pipelines de déploiement

A09 et A10 : Logging et SSRF

A09 — Security Logging and Monitoring Failures : si vous ne loggez pas les tentatives d’attaque, vous ne les détectez pas. Loggez les échecs d’authentification, les accès refusés, les erreurs de validation. Alertez sur les anomalies.

A10 — Server-Side Request Forgery (SSRF) : votre application fait des requêtes HTTP vers des URLs fournies par l’utilisateur ? Un attaquant peut l’utiliser pour scanner votre réseau interne ou accéder à vos métadonnées cloud.

// VULNÉRABLE — l'utilisateur contrôle l'URL
app.get('/proxy', async (req, res) => {
  const response = await fetch(req.query.url);
  res.send(await response.text());
});

// CORRIGÉ — whitelist de domaines autorisés
const ALLOWED_DOMAINS = ['api.partenaire.com', 'cdn.monsite.fr'];
app.get('/proxy', async (req, res) => {
  const url = new URL(req.query.url);
  if (!ALLOWED_DOMAINS.includes(url.hostname)) {
    return res.status(403).json({ error: 'Domain not allowed' });
  }
  const response = await fetch(url.toString());
  res.send(await response.text());
});

La sécurité comme culture, pas comme checklist

La sécurité applicative ne se résout pas avec un audit annuel ou un scan automatisé. C’est une discipline d’équipe qui s’intègre dans chaque phase du développement :

  • Conception : threat modeling, revue d’architecture
  • Développement : code review orienté sécurité, linting sécurité (eslint-plugin-security)
  • Test : tests de sécurité automatisés (DAST, SAST) dans la CI
  • Production : monitoring des anomalies, plan de réponse aux incidents

FAQ

Par où commencer si notre application n’a jamais été auditée ?

Commencez par trois actions immédiates : lancez un scan automatisé (OWASP ZAP est gratuit), vérifiez vos dépendances avec npm audit, et auditez manuellement votre système d’authentification et de gestion des accès (A01 et A07). Ces trois actions couvrent les risques les plus critiques. Ensuite, planifiez un audit de sécurité complet avec un prestataire spécialisé.

Les scans automatisés suffisent-ils ?

Non. Les scanners automatisés (SAST, DAST) détectent les vulnérabilités connues et les patterns de code dangereux. Ils ne détectent pas les défauts de logique métier (A04), les problèmes de contrôle d’accès complexes (A01), ni les failles de conception. Un audit manuel par un expert en sécurité reste indispensable au moins une fois par an.

Comment convaincre le management d’investir dans la sécurité ?

Parlez en termes de risque business, pas de risque technique. Le coût moyen d’une fuite de données en Europe dépasse les 4 millions d’euros (sanctions RGPD incluses). Comparez avec le coût de la prévention. Et rappelez que la sécurité est un avantage compétitif : les clients enterprise exigent des certifications (SOC 2, ISO 27001) avant de signer.

Faut-il faire un pentest ou un audit de code ?

Les deux sont complémentaires. Le pentest simule une attaque réelle de l’extérieur — il trouve ce qu’un attaquant trouverait. L’audit de code analyse la qualité du code de l’intérieur — il trouve les vulnérabilités qui ne sont pas encore exploitables mais le deviendront. Pour un premier passage, le pentest est prioritaire car il révèle les risques immédiats.

Ce guide vous a été utile ? Partagez-le avec votre réseau.

Un projet en lien avec ce sujet ?

Nos experts seniors vous accompagnent du cadrage au delivery. Parlons de votre contexte.