Skip to Content
SécuritéPartie 1 — Comprendre la sécurité1.2 — CIA, surface d'attaque, defense-in-depth

Chapitre 1.2 — CIA, surface d’attaque, defense-in-depth

⏱️ TL;DR — On ne « sécurise » pas dans le vide : on protège trois propriétésConfidentialité (personne ne lit ce qu’il ne doit pas), Intégrité (personne ne modifie ce qu’il ne doit pas), Disponibilité (le service reste debout). Pour savoir attaquer, on cartographie la surface d’attaque (tous les points d’entrée). Pour résister, on empile des couches (defense in depth) : si une tombe, la suivante tient. Et on applique quelques principes qui reviennent partout : moindre privilège, fail secure, secure by default.

🎯 Objectifs

  • Analyser un risque avec le triangle CIA et savoir quelle propriété est menacée.
  • Cartographier la surface d’attaque d’une appli (points d’entrée, frontières).
  • Comprendre et appliquer defense in depth (sécurité en couches).
  • Appliquer les principes moindre privilège, fail secure, secure by default.

Les trois propriétés : CIA

Toute la sécurité de l’information se ramène à protéger trois propriétés. Les nommer permet de dire précisément ce qu’une attaque menace — et donc quelle défense choisir.

PropriétéCe qu’on protègeExemple de violation
ConfidentialitéSeuls les autorisés lisent la donnée.Une fuite de base d’utilisateurs ; un apprenant lit les notes d’un autre (IDOR).
IntégritéSeuls les autorisés modifient la donnée, et elle reste exacte.Un attaquant change le montant d’une commande ; falsification d’un JWT ; injection qui altère la base.
DisponibilitéLe service reste accessible aux utilisateurs légitimes.Un déni de service (DoS) ; un ransomware qui chiffre les données ; une base saturée.

Ces trois propriétés se complètent — et parfois se tendent. Chiffrer une sauvegarde renforce la confidentialité mais, si on perd la clé, on perd la disponibilité de la sauvegarde. La sécurité est un équilibre, pas un maximalisme.

💡 Réflexe — Face à un risque, demande-toi : « quelle(s) propriété(s) du triangle est menacée ? ». Un mot de passe volé menace la confidentialité ; une injection qui écrit dans la base menace l’intégrité ; un flood qui met le site à genoux menace la disponibilité. Nommer la propriété oriente vers la bonne parade.

La surface d’attaque

La surface d’attaque, c’est l’ensemble des points par lesquels une entrée non fiable peut atteindre ton système. Plus elle est grande, plus il y a de portes à surveiller. La cartographier, c’est le premier geste concret de sécurité.

Pour une appli web typique, la surface inclut :

  • Toutes les entrées HTTP : paramètres d’URL, corps de requête (JSON, formulaires), en-têtes (Cookie, User-Agent, Referer, X-Forwarded-For…), fichiers uploadés.
  • Les points d’authentification : login, reset de mot de passe, inscription, OAuth.
  • Les endpoints d’API, y compris ceux « internes » ou non documentés.
  • Les dépendances : chaque paquet npm/composer est du code tiers qui s’exécute chez toi.
  • Les intégrations tierces : webhooks entrants, réponses d’API externes, contenu importé.
  • L’infra : ports ouverts, panneaux d’admin, services exposés (voir Serveur Linux).

🎯 Côté attaquant — Un attaquant commence toujours par énumérer la surface : il liste les routes, teste les paramètres, regarde les en-têtes acceptés, inspecte le JS côté client pour trouver des endpoints, cherche les fichiers oubliés (.env, .git, sauvegardes). Chaque point que tu n’as pas listé est un point qu’il trouvera peut-être avant toi. On ne défend bien que ce qu’on a d’abord cartographié.

Réduire la surface est en soi une défense : désactiver un endpoint inutilisé, ne pas exposer un service, retirer une dépendance superflue — autant de portes qu’on n’a plus à garder.

Defense in depth : plusieurs couches

Aucune défense n’est parfaite. Un jour, une validation est contournée, une dépendance se révèle vulnérable, un dev oublie un contrôle. Le principe de defense in depth (défense en profondeur) répond à ça : empiler plusieurs couches indépendantes, pour qu’une faille dans l’une soit rattrapée par la suivante.

Exemple contre le XSS : on valide l’entrée (couche 1), on encode en sortie (couche 2, la principale), et on ajoute une CSP (couche 3, le filet si les deux premières échouent). Si un jour un encodage est oublié quelque part, la CSP peut encore bloquer l’exécution du script injecté. Aucune couche n’est censée être « la » protection — c’est leur superposition qui rend l’exploitation difficile.

⚠️ Piège — L’inverse de la défense en profondeur, c’est le point unique de défaillance : « on a un WAF, donc on est protégés » ou « React échappe tout, donc pas besoin de CSP ». Une seule couche, aussi bonne soit-elle, finit par être contournée. Ne mise jamais toute ta sécurité sur un seul mécanisme.

Les principes qui reviennent partout

Trois principes guident d’innombrables décisions dans le reste du cours. Les avoir en tête évite de réfléchir à zéro à chaque fois.

Moindre privilège

Chaque composant, utilisateur ou service ne reçoit que les droits strictement nécessaires à sa tâche, rien de plus. L’utilisateur de base de données de ton appli n’a pas besoin des droits d’administration du serveur SQL ; un token de CI n’a pas besoin d’un accès en écriture sur tous les dépôts ; un utilisateur normal n’a pas besoin d’atteindre les routes d’admin. Ainsi, si un composant est compromis, les dégâts sont bornés à ses maigres droits.

Fail secure (échouer fermé)

Quand quelque chose tourne mal — une exception, un service indisponible, un cas non prévu — le système doit basculer dans l’état le plus sûr, c’est-à-dire refuser, pas autoriser. Un contrôle d’accès qui, en cas d’erreur, laisse passer est une catastrophe ; il doit bloquer par défaut.

// ❌ fail open : en cas d'erreur, on laisse passer function peutAcceder(user, ressource) { try { return verifierDroit(user, ressource) } catch (e) { return true // desastre : une panne de verif = acces libre } } // ✅ fail secure : en cas de doute, on refuse function peutAcceder(user, ressource) { try { return verifierDroit(user, ressource) } catch (e) { return false // une panne de verif = acces refuse } }

Secure by default

La configuration par défaut doit être la plus sûre. Un nouvel endpoint devrait exiger une auth par défaut (et non l’inverse) ; un cookie devrait être Secure et HttpOnly par défaut ; un compte devrait n’avoir aucun droit avant qu’on lui en accorde. La sécurité ne doit pas dépendre du fait que chaque dev pense à « activer l’option ». On veut que l’oubli mène au sûr, pas au vulnérable.

💡 Réflexe — Ces trois principes forment un test rapide pour toute décision de conception : « Est-ce que je donne le minimum de droits ? En cas d’erreur, est-ce que ça refuse ? Le défaut est-il le choix sûr ? ». Si tu réponds non à l’un des trois, il y a probablement un problème à corriger.

🧭 Sur FormaCampus — Sur FormaCampus, on applique CIA et les principes dès la conception : les notes des apprenants sont confidentielles (accès vérifié côté serveur), leur exactitude est un enjeu d’intégrité (une note falsifiée est grave), et la plateforme doit rester disponible en période d’examen. La surface d’attaque est cartographiée (front Next.js, API Symfony, Moodle, webhooks LTI…), on empile les couches (validation + autorisation + requêtes paramétrées + en-têtes), et l’API Symfony est secure by default : chaque route est protégée par le firewall sauf celles explicitement rendues publiques.

✏️ Exercices

Exercice 1 — Nomme la propriété. Pour chaque scénario, dis quelle propriété du triangle CIA est principalement menacée : (a) un attaquant lit la table des utilisateurs ; (b) un attaquant modifie le solde d’un compte ; (c) un flood rend le site inaccessible ; (d) un JWT est falsifié pour changer le rôle en « admin ».

✅ Solution

(a) Confidentialité (lecture non autorisée). (b) Intégrité (modification non autorisée). (c) Disponibilité (service rendu inaccessible). (d) Intégrité (altération d’une donnée — le rôle — qui doit être infalsifiable ; on peut aussi y voir une élévation de privilège, mais la propriété violée est l’intégrité du jeton).

Exercice 2 — Corrige le fail open. Ce middleware décide si une requête est autorisée. Quel est le problème, et comment le corriger dans l’esprit fail secure ?

async function authorize(req) { const user = await getUser(req) // peut throw si le service auth est down if (user && user.role === 'admin') return true return false }

✅ Solution

Le problème n’est pas dans la logique visible mais dans le comportement en cas d’erreur : si getUser lève une exception (service d’auth indisponible, token malformé), et que l’appelant enveloppe l’appel dans un try/catch qui laisse passer, on est en fail open. Pour être fail secure, il faut garantir qu’une erreur mène au refus : entourer l’appel d’un try { ... } catch { return false } ici (ne pas laisser l’appelant décider), et ne renvoyer true que sur le chemin explicitement vérifié. Toute branche non prévue doit retourner false.

Exercice 3 — Réduis la surface. Cite trois actions concrètes qui réduisent la surface d’attaque d’une appli web, sans ajouter de nouvelle défense (juste en enlevant).

✅ Solution

Par exemple : (1) désactiver / supprimer les endpoints inutilisés (anciennes routes de debug, API non utilisées) ; (2) retirer les dépendances superflues (chaque paquet est du code tiers exécuté chez toi) ; (3) ne pas exposer ce qui n’a pas à l’être (panneau d’admin sur un réseau restreint, port de base de données fermé au public, fichiers .env/.git non servis). Réduire la surface, c’est enlever des portes à garder.

🧠 Quiz de révision

1. Que signifient les trois lettres de CIA ?

Confidentialité (seuls les autorisés lisent), Intégrité (seuls les autorisés modifient, la donnée reste exacte), Disponibilité (le service reste accessible aux légitimes). Ce sont les trois propriétés qu’on protège.

2. Qu’est-ce que la surface d’attaque, et pourquoi la cartographier ?

L’ensemble des points par lesquels une entrée non fiable peut atteindre le système (entrées HTTP, en-têtes, uploads, endpoints, dépendances, intégrations, infra). On la cartographie parce qu’on ne défend bien que ce qu’on a listé — et la réduire (enlever des points) est en soi une défense.

3. Qu’est-ce que la defense in depth, avec un exemple ?

Empiler plusieurs couches de défense indépendantes pour qu’une faille dans l’une soit rattrapée par la suivante. Exemple contre le XSS : validation d’entrée + encodage de sortie + CSP en filet. On ne mise jamais tout sur une seule couche.

4. Explique « fail secure » et pourquoi c’est crucial pour un contrôle d’accès.

En cas d’erreur ou de cas non prévu, le système doit basculer dans l’état le plus sûr : refuser. Un contrôle d’accès qui laisse passer en cas d’erreur (fail open) transforme une simple panne en trou de sécurité. On refuse par défaut, on n’autorise que sur un chemin explicitement vérifié.

5. Qu’est-ce que le « secure by default » ?

La configuration par défaut est la plus sûre : un endpoint exige l’auth par défaut, un cookie est Secure/HttpOnly par défaut, un compte n’a aucun droit tant qu’on ne lui en accorde pas. Objectif : que l’oubli d’un dev mène au sûr, pas au vulnérable.


Chapitre suivant : Modéliser la menace (STRIDE) — passer de « je sécurise au hasard » à une méthode structurée pour trouver les menaces avant les attaquants.

Last updated on