Leçon 2/14 8 min

Modèle de menace et défense en profondeur

Cartographier la surface d'attaque, 4 bonnes questions, empiler les défenses : aucune faille isolée ne doit être fatale.

On ne défend bien que ce qu'on a cartographié

Imaginez qu'on vous confie la garde d'un immeuble. Avant de poster le moindre vigile, vous feriez le tour du bâtiment : combien de portes ? de fenêtres ? un toit accessible, un parking, une porte de livraison ? Personne ne verrouille l'entrée principale en laissant douze fenêtres ouvertes au rez-de-chaussée.

Dans la leçon précédente, vous avez appris à penser comme un attaquant : chercher les failles avant qu'on vous les exploite. La première mise en pratique de ce réflexe, c'est de dresser la carte de ce qu'il vise. En sécurité, c'est l'erreur classique du débutant : foncer ajouter « de la sécurité » sur un bout de code, sans avoir regardé l'ensemble. On colmate une fuite pendant que trois autres tuyaux débordent. La sécurité commence par une carte, pas par du code. Cette carte, on l'appelle un modèle de menace, et elle se dessine avant d'écrire la moindre défense.

La surface d'attaque : compter les portes

La surface d'attaque, c'est l'ensemble des points par lesquels une donnée venue de l'extérieur peut entrer dans votre système. Chaque point est une porte qu'un attaquant peut pousser. Sur une application web classique, on y trouve :

  • Chaque formulaire : connexion, inscription, contact, recherche, commentaire…
  • Chaque paramètre d'URL : ?id=42, /produit/42, un filtre, une page.
  • Chaque endpoint d'API que le front (ou n'importe qui) peut appeler.
  • Les cookies et les en-têtes HTTP. Oui : un attaquant peut forger un User-Agent, un Referer ou un cookie. Ce ne sont pas des données de confiance.
  • Les uploads de fichiers (une image peut cacher autre chose qu'une image).
  • Les données venant de services tiers : webhooks, scripts externes, API partenaires.

Plus la surface est large, plus il y a de portes à surveiller. D'où une première défense, gratuite : réduire la surface. Une route d'admin qui ne sert plus, un paramètre de debug oublié, une API exposée pour rien… tout ce qu'on désactive est une porte de moins à garder.

À savoir : la surface d'attaque ne se limite pas à « ce que l'utilisateur voit ». Les champs cachés d'un formulaire, les paramètres non documentés d'une API, les vieux endpoints non supprimés en font partie. L'attaquant, lui, ne se limite pas à votre interface.

Le modèle de menace en 4 questions

Modéliser les menaces, ça a l'air d'un truc d'expert avec des diagrammes compliqués. En réalité, ça tient en quatre questions qu'on se pose avant de coder (c'est la base du Threat Modeling Manifesto, adopté par toute la profession) :

  1. Qu'est-ce qu'on construit ? Cartographiez les données sensibles, les flux et toutes les portes d'entrée (la surface ci-dessus).
  2. Qu'est-ce qui peut mal tourner ? Pour chaque porte : qui voudrait entrer, et pour faire quoi ?
  3. Qu'est-ce qu'on fait pour s'en protéger ? Les défenses, une par menace identifiée.
  4. A-t-on fait du bon boulot ? On relit, on teste, on vérifie qu'on n'a pas oublié une porte.

Pour ne rien oublier à la question 2, les pros s'appuient sur un aide-mémoire appelé STRIDE (de Microsoft) : six familles de menaces, une lettre chacune.

  • Spoofing : usurpation d'identité, se faire passer pour un autre utilisateur ou service.
  • Tampering : falsification de données, modifier un prix, un rôle ou un identifiant en transit.
  • Repudiation : déni d'action, nier avoir passé une commande ou supprimé un fichier, faute de trace.
  • Information disclosure : fuite d'information, lire le compte bancaire d'un autre via une URL devinée.
  • Denial of service : mise hors service, saturer le serveur pour le rendre inaccessible.
  • Elevation of privilege : élévation de droits, devenir admin sans en avoir le droit.

Prenez le plus petit bout de votre app, un simple formulaire de commentaire, et passez-le aux 4 questions. « Et si quelqu'un poste 5 000 commentaires en une minute ? Et s'il met du HTML dedans ? Et s'il se fait passer pour un autre auteur ? » Vous venez de faire du threat modeling. Pas besoin d'outil, juste l'habitude de poser les questions.

La défense en profondeur : le gruyère

Une fois les menaces listées, comment se défendre ? Surtout pas avec une seule barrière. Le principe clé s'appelle la défense en profondeur : empiler plusieurs protections indépendantes, pour qu'une faille unique ne soit jamais fatale.

Prenons un exemple concret : un attaquant qui glisse un prix négatif dans son panier pour que la boutique lui doive de l'argent. Une appli bien pensée empile :

  1. Validation côté navigateur : confort pour l'utilisateur honnête (message immédiat). Ne protège de rien, mais c'est gratuit.
  2. Validation côté serveur : la vraie barrière. Le serveur refuse tout prix < 0, quoi qu'il reçoive.
  3. Contrainte en base de données : une règle CHECK (prix >= 0) qui bloque même si le code serveur a un trou.
  4. Compte base de données à privilèges minimaux : si malgré tout une injection passe, l'attaquant ne peut pas faire grand-chose avec un compte qui n'a le droit que de lire et écrire deux tables.

On appelle ça le modèle du gruyère (ou du fromage suisse) : chaque tranche a des trous, mais empilées, leurs trous ne s'alignent pas. Pour qu'une attaque réussisse, il faudrait qu'elle passe à travers toutes les couches d'un coup.

Défense en profondeur : les trous des couches ne s'alignent pas, l'attaque est bloquée Attaque 1. Navigateur (UX) 2. Serveur Bloquée 3. Contrainte SQL 4. Compte minimal
Chaque couche a ses trous ; empilées, ils ne s'alignent pas. L'attaque passe la couche 1 mais bute sur la couche 2.

Certaines failles ne sont pas des bugs de code, mais des erreurs de conception (c'est l'A06 : Insecure Design de l'OWASP). Exemple classique : une fonction « mot de passe oublié » qui vous renvoie votre ancien mot de passe par email. Ça prouve qu'il est stocké en clair, et aucun code « propre » ne corrigera cette mauvaise idée. La seule parade, c'est de penser la sécurité dès la conception, avec le modèle de menace, pas de la rajouter après.

Règle d'or : faites le modèle de menace au moment de concevoir une fonctionnalité, sur un coin de table s'il le faut, pas une fois le code écrit. Une porte oubliée sur le plan coûte une ligne à corriger ; la même porte découverte en production coûte un incident.

You only defend well what you've mapped

Imagine you're put in charge of guarding a building. Before posting a single guard, you'd walk around it: how many doors, how many windows, is the roof reachable, is there a parking lot, a delivery entrance? Nobody starts by locking the front door while ignoring the twelve open ground-floor windows.

In the previous lesson, you learned to think like an attacker: spot the weaknesses before they get exploited. The first concrete application of that reflex is mapping what the attacker is after. Security is the same, and it's the classic beginner's mistake: rushing to bolt "some security" onto a piece of code without looking at the whole. You patch one leak while three other pipes overflow. Security starts with a map, not with code. That map is called a threat model, and you draw it before writing a single defense.

The attack surface: count the doors

The attack surface is the set of points through which data from the outside can enter your system. Each point is a door an attacker can push on. For a typical web app, that includes:

  • Every form: login, signup, contact, search, comment…
  • Every URL parameter: ?id=42, /product/42, a filter, a page.
  • Every API endpoint the front end (or anyone) can call.
  • Cookies and HTTP headers. Yes: an attacker can forge a User-Agent, a Referer or a cookie. These are not trusted data.
  • File uploads (an image can hide something other than an image).
  • Data coming from third-party services: webhooks, external scripts, partner APIs.

The wider the surface, the more doors to watch. Hence a first, free defense: reduce the surface. An admin route nobody uses anymore, a forgotten debug parameter, an API exposed for nothing… everything you turn off is one less door to guard.

Good to know: the attack surface isn't limited to "what the user sees". Hidden form fields, undocumented API parameters, old endpoints never deleted are all part of it. The attacker, unlike you, isn't limited to your interface.

The threat model in 4 questions

Threat modeling sounds like expert stuff with complicated diagrams. In reality it comes down to four questions you ask before coding (this is the core of the Threat Modeling Manifesto, adopted across the profession):

  1. What are we building? Map the sensitive data, the flows and every entry point (the surface above).
  2. What can go wrong? For each door: who would want in, and to do what?
  3. What are we doing about it? The defenses, one per identified threat.
  4. Did we do a good enough job? Re-read, test, check you didn't forget a door.

To miss nothing on question 2, pros lean on a memory aid called STRIDE (from Microsoft): six threat families, one letter each.

  • Spoofing: impersonation — pretending to be another user or service.
  • Tampering: data alteration — changing a price, a role, or an id in transit.
  • Repudiation: deniability — denying you placed an order or deleted a file, because no trace exists.
  • Information disclosure: data leak — reading another user's bank account by guessing a URL.
  • Denial of service: taking it down — flooding the server until it's unreachable.
  • Elevation of privilege: privilege escalation — becoming admin without having the right to.

Take the smallest piece of your app, a plain comment form, and run it through the 4 questions. "What if someone posts 5,000 comments in a minute? What if they put HTML in it? What if they impersonate another author?" You just did threat modeling. No tool needed, just the habit of asking.

Defense in depth: the Swiss cheese

Once the threats are listed, how do you defend? Definitely not with a single barrier. The key principle is defense in depth: stacking several independent protections, so that one flaw is never fatal.

Take a concrete example: an attacker slipping a negative price into their cart so the shop owes them money. A well-designed app stacks:

  1. Browser-side validation: comfort for the honest user (instant feedback). Protects nothing, but it's free.
  2. Server-side validation: the real barrier. The server refuses any price < 0, whatever it receives.
  3. Database constraint: a CHECK (price >= 0) rule that blocks even if the server code has a hole.
  4. Least-privilege database account: if an injection still gets through, an attacker can't do much with an account allowed only to read and write two tables.

This is called the Swiss cheese model: each slice has holes, but stacked up, their holes don't line up. For an attack to succeed, it would have to pass through every layer at once.

Defense in depth: the layers' holes don't line up, the attack is blocked Attack 1. Browser (UX) 2. Server Blocked 3. SQL constraint 4. Min. privileges
Each layer has its holes; stacked up, they don't line up. The attack clears layer 1 but hits layer 2.

Some flaws aren't code bugs, they're design mistakes (this is OWASP's A06: Insecure Design). Classic example: a "forgot password" feature that emails you your old password. That proves it's stored in clear text, and no amount of "clean" code will fix that bad idea. The only cure is to think about security from the design stage, with the threat model, not bolt it on afterwards.

Golden rule: do the threat model when you design a feature, on the back of a napkin if needed, not once the code is written. A door forgotten on the blueprint costs one line to fix; the same door found in production costs an incident.

Prédisez avant de lire

On vous demande de sécuriser un petit blog : les visiteurs peuvent se connecter, poster des commentaires et uploader une photo de profil. Avant de dérouler : listez au moins quatre « portes » (points d'entrée) qu'un attaquant pourrait pousser, et pour l'une d'elles, dites ce qui pourrait mal tourner.

Voir des pistes

Quelques portes évidentes (il y en a d'autres) :

  • Le formulaire de connexion : essais de mots de passe en masse (force brute), injection dans le champ email.
  • Le champ commentaire : y glisser du HTML/JavaScript pour piéger les autres lecteurs (XSS), ou du SQL.
  • L'upload de photo : envoyer un fichier qui n'est pas une image (un script déguisé en .jpg), ou une image de 2 Go pour saturer le disque.
  • Les paramètres d'URL : changer /profil/12 en /profil/13 pour voir le profil d'un autre, ou /admin au cas où.
  • Les cookies : modifier le cookie de session pour se faire passer pour quelqu'un d'autre.

Vous venez de dresser la surface d'attaque. C'est exactement la question 1 du modèle de menace, et déjà la moitié du travail de défense.

Predict before reading on

You're asked to secure a small blog: visitors can log in, post comments and upload a profile picture. Before you expand: list at least four "doors" (entry points) an attacker could push on, and for one of them, say what could go wrong.

Show some leads

A few obvious doors (there are more):

  • The login form: mass password guessing (brute force), injection in the email field.
  • The comment field: slipping in HTML/JavaScript to trap other readers (XSS), or SQL.
  • The photo upload: sending a file that isn't an image (a script disguised as .jpg), or a 2 GB image to fill the disk.
  • URL parameters: changing /profile/12 to /profile/13 to view someone else's profile, or /admin just in case.
  • Cookies: tampering with the session cookie to impersonate someone else.

You just drew the attack surface. That's exactly question 1 of the threat model, and already half the defense work.

🎯 Pratique

S'entraîner (clique pour ouvrir) :

💬 Ré-explique sans regarder
Ré-explique sans regarder

Avec tes mots et l'image du gruyère : qu'est-ce que la défense en profondeur, et pourquoi une seule barrière (même excellente) ne suffit jamais ?

Une bonne explication dit : la défense en profondeur, c'est empiler plusieurs protections indépendantes (validation serveur, contrainte en base, compte à privilèges minimaux…) au lieu de tout miser sur une seule. Comme les tranches de gruyère : chacune a des trous, mais empilées, les trous ne s'alignent pas. Une seule barrière ne suffit jamais parce qu'aucune n'est parfaite : le jour où elle a un trou (un bug, un oubli, un cas non prévu), s'il n'y a rien derrière, l'attaque passe directement. Les couches suivantes sont le filet de sécurité.
🧠 Rappel libre
Rappel libre

Sans remonter dans la leçon : quelles sont les 4 questions du modèle de menace, et que veut dire « réduire la surface d'attaque » ?

Les 4 questions : 1) Qu'est-ce qu'on construit ? 2) Qu'est-ce qui peut mal tourner ? 3) Qu'est-ce qu'on fait pour s'en protéger ? 4) A-t-on fait du bon boulot ? « Réduire la surface d'attaque » veut dire supprimer ou désactiver tout point d'entrée inutile (route d'admin abandonnée, paramètre de debug, API exposée pour rien) : chaque porte en moins est une porte qu'on n'a plus à défendre.
⚖️ Juge le code de l'IA
Accepter ou rejeter la décision

Un coéquipier annonce : « On a installé un WAF (pare-feu applicatif) devant le site. Il bloque les attaques connues, donc on peut arrêter de valider les entrées dans notre code, ça nous fera gagner du temps. » Tu acceptes, ou tu rejettes ? Justifie avec la défense en profondeur.

À rejeter. Un WAF est une couche utile, mais une seule couche : il se contourne (encodage exotique, attaque inédite qu'il ne connaît pas, faille dans sa propre config), et il ne comprend pas la logique métier de ton app (lui ne sait pas qu'un prix doit être positif). Supprimer la validation dans le code, c'est retirer toutes les autres tranches de gruyère et ne garder que celle-là : le jour où le WAF a un trou, plus rien derrière. La défense en profondeur dit l'inverse : le WAF s'ajoute à la validation serveur, il ne la remplace pas.
Parmi ces éléments, lequel NE fait PAS partie de la surface d'attaque ?
Laquelle de ces affirmations sur la défense en profondeur est correcte ?
La fonction « mot de passe oublié » renvoie l'ancien mot de passe par email. Quelle analyse est la bonne ?
Une API renvoie /api/user/42 avec les infos de l'utilisateur 42. Le front n'affiche le bouton « voir mon profil » que pour son propre identifiant. Un dev conclut : « comme le bouton n'apparaît que pour soi, l'API est protégée ». Qu'est-ce qui cloche ?
Prochaine étape

Vous savez cartographier les menaces et empiler les défenses. Place à la plus célèbre des portes mal gardées : la leçon 3 décortique l'injection SQL, l'attaque qui a vidé d'innombrables bases, et la parade en une ligne qui l'arrête net.

Leçon 3 : Injection SQL →
Besoin d'un développeur pour votre projet ?

Réponse sous 24h · Sans engagement