C1 — FondationsDans le dialogue d’impression, choisissez « Enregistrer au format PDF » comme destination.
Retour

Licence 3 · Cybersécurité

Cours 1Fondations

Poser le vocabulaire et la méthode d'analyse, puis employer correctement les primitives cryptographiques sans les réimplémenter.

2 chapitres · 10 h de travail estimé

  1. 1. Concepts et menaces4 h
  2. 2. Cryptographie appliquée6 h

Chapitre 1 · 4 h

Concepts et menaces

Confidentialité, intégrité, disponibilité, traçabilité ; actif, vulnérabilité, menace, risque ; profils d'attaquants, surface d'attaque, chaîne d'attaque ; cadre légal et éthique du test d'intrusion.

Le 2 novembre 1988, un étudiant de Cornell libère sur ARPANET un programme de quatre-vingt-dix lignes. Il ne détruit rien, ne vole rien, ne chiffre rien : il se copie. Une erreur de paramètre le fait se recopier bien plus vite que prévu, et en une nuit il immobilise environ 10 % des machines connectées au réseau. Robert Morris sera le premier condamné au titre du Computer Fraud and Abuse Act, et son ver donnera naissance au premier CERT.

Trois choses de ce cours tiennent déjà dans cette histoire. Une attaque n'a pas besoin de voler quoi que ce soit pour faire des dégâts — c'est la disponibilité qui est tombée. L'écart entre l'intention et l'effet ne relève pas de la technique mais du droit. Et la défense organisée est née après l'incident, ce qui reste vrai aujourd'hui de la plupart des organisations.

Ce premier chapitre n'exploite rien. Il installe le vocabulaire et la méthode sans lesquels les neuf suivants seraient une collection de recettes : ce qu'on protège, contre qui, par où, et dans quel cadre on a le droit de le vérifier.

Ce qu'on protège : quatre propriétés, pas une

La sécurité ne se mesure jamais « en général ». Elle se décompose en propriétés nommées, dont chacune se perd indépendamment des autres.

PropriétéQuestionCe qui la casseCe qui la tient
ConfidentialitéQui peut lire ?fuite, écoute, accès excessifchiffrement, contrôle d'accès
IntégritéLa donnée est-elle intacte ?modification, corruptionsignature, MAC, journal d'audit
DisponibilitéLe service répond-il ?déni de service, panne, rançongicielredondance, sauvegarde, filtrage
TraçabilitéQui a fait quoi, quand ?journaux absents ou effaçablesjournalisation centralisée, horodatage

L'acronyme français DICT — parfois DICP, avec la preuve à la place de la traçabilité — vaut mieux que le CIA anglo-saxon parce qu'il nomme la quatrième. Sans traçabilité, un incident n'est pas analysable : on constate le résultat sans pouvoir reconstituer le chemin, et le chapitre 9 sera sans objet.

Deux erreurs classiques méritent d'être défaites tout de suite.

Les propriétés ne se déduisent pas les unes des autres. Un fichier chiffré peut être supprimé — confidentialité intacte, disponibilité perdue. Une base parfaitement disponible peut avoir été modifiée par un attaquant — et si personne ne s'en aperçoit, la perte d'intégrité coûte plus cher qu'une fuite, parce que l'organisation continue de décider sur des données fausses.

Elles entrent en conflit. Le contrôle le plus sûr pour la confidentialité — refuser tout le monde — détruit la disponibilité. Une politique de mot de passe extrême produit des mots de passe écrits sur des feuilles collées aux écrans. La sécurité n'est pas la maximisation d'une propriété, c'est un arbitrage explicite entre les quatre, et cet arbitrage appartient au métier, pas à l'équipe technique. C'est le fond du chapitre 10.

Quatre mots qu'on ne doit plus confondre

Le vocabulaire du risque est le seul de ce cours qu'on emploie devant une direction. Le confondre coûte cher : c'est la différence entre un rapport qu'on lit et un rapport qu'on classe.

Un actif est ce qui a de la valeur : une base clients, un serveur de paie, une marque, la disponibilité d'un site de vente. C'est le point de départ, et l'oublier est l'erreur des débutants — on se met à sécuriser ce qui est technique plutôt que ce qui compte.

Une vulnérabilité est une faiblesse : un logiciel non corrigé, un mot de passe par défaut, une procédure qui autorise un virement sur simple courriel. Elle existe indépendamment de tout attaquant.

Une menace est un événement redouté associé à une source capable de le provoquer : un concurrent qui veut le fichier clients, un rançongiciel opportuniste, un employé qui part en emportant des données, un incendie. Une menace sans vulnérabilité correspondante ne se réalise pas ; une vulnérabilité sans menace ne coûte rien.

Le risque est ce qui reste quand on les croise, pondéré par les conséquences :

risque ≈ vraisemblance (menace × vulnérabilité) × gravité (impact sur l'actif)

Le signe ≈ est important. Cette formule n'est pas un calcul, c'est une grille de discussion : les deux facteurs s'estiment sur des échelles à quatre niveaux, jamais en euros à la décimale. Une méthode complète — EBIOS Risk Manager, ISO 27005 — organise cette estimation ; le chapitre 10 la conduira en entier.

La conséquence pratique est immédiate : on ne corrige pas les vulnérabilités par ordre de gravité technique, mais par ordre de risque. Une faille critique sur un serveur de test isolé passe après une faille moyenne sur le portail de paiement. Un score CVSS de 9,8 n'est pas un ordre de mission ; c'est un des facteurs de la vraisemblance.

Qui attaque, et ce que cela change

Le mot « pirate » ne décrit rien. Ce qui décrit, c'est le couple motivation × moyens, parce que c'est lui qui dit ce contre quoi vous pouvez espérer tenir.

ProfilMotivationMoyensCe qu'il vise
Opportunisteargent, rapideoutils publics, balayage massiftout ce qui est vulnérable et exposé
Cybercriminel organiséargentachat d'accès, rançongiciel comme serviceentreprises solvables, sauvegardes
Hacktivisteidéologie, visibilitévariablesites publics, défiguration, fuite
Étatiquerenseignement, sabotage0-day, chaîne d'approvisionnement, tempscibles précises, longue durée
Internerancune, appât du gain, erreuraccès légitimece à quoi il a déjà droit

Deux enseignements sortent de ce tableau, et ils vont dans des sens opposés.

Le premier est rassurant : l'immense majorité des attaques ne vous vise pas. Elles balaient Internet et prennent ce qui cède. Contre elles, l'hygiène élémentaire — correctifs appliqués, pas de service inutile exposé, pas de mot de passe par défaut, sauvegardes testées — suffit à changer de catégorie de victime.

Le second l'est moins : contre un attaquant étatique déterminé, la question n'est pas de tenir mais de détecter. Il a plus de temps et d'argent que vous, il achètera un accès ou compromettra un fournisseur. L'objectif réaliste devient la réduction du temps de présence, qui se mesure en jours et non en mois — d'où le poids donné à la traçabilité et au chapitre 9.

Le cas de l'attaquant interne mérite une mention à part, parce qu'il défait toutes les défenses périmétriques du chapitre 6 : il est déjà à l'intérieur, et ses actions sont légitimes une par une. C'est le moindre privilège du chapitre 3, la séparation des tâches et la journalisation qui répondent — pas le pare-feu.

La surface d'attaque

La surface d'attaque est l'ensemble des points par lesquels un attaquant peut interagir avec le système. Elle se compte, et c'est la seule mesure de sécurité qui se réduit directement par une action.

Elle a trois faces, et on n'en voit couramment qu'une :

  • Réseau — ports ouverts, services exposés, API publiques, accès distants, objets connectés.
  • Logicielle — code applicatif, dépendances tierces, interpréteurs, formats de fichiers acceptés.
  • Humaine — personnes joignables par courriel ou téléphone, prestataires, sous-traitants.

Trois principes de réduction, dans l'ordre d'efficacité :

  1. Supprimer ce qui n'est pas nécessaire. Un service désinstallé n'a aucune vulnérabilité. C'est la seule mesure dont l'efficacité ne se dégrade pas avec le temps.
  2. Restreindre ce qui reste. Un service qui n'écoute que sur 127.0.0.1 a une surface proche de zéro, à coût nul.
  3. Cloisonner ce qui doit rester exposé, pour que sa compromission ne donne pas le reste. C'est le rôle de la zone démilitarisée et de la segmentation, au chapitre 6.

Notez ce que ces trois principes ont en commun : aucun ne consiste à ajouter un produit de sécurité. La première réponse à une surface d'attaque trop large n'est pas un pare-feu de plus, c'est un inventaire — et l'inventaire est presque toujours faux, parce que personne ne sait plus quelles machines existent.

La chaîne d'attaque

Une intrusion réelle n'est pas un exploit unique : c'est une suite d'étapes, dont chacune prépare la suivante. Le modèle le plus employé en enseignement est la cyber kill chain, ici ramenée à cinq phases ; en pratique professionnelle, la matrice MITRE ATT&CK décrit les mêmes étapes avec beaucoup plus de détail, et sert de langage commun entre attaque et défense.

PhaseL'attaquant cherche àTrace typique
Reconnaissanceconnaître la cible sans y toucherbalayages, consultation du site, collecte d'adresses
Intrusionexécuter son premier codepièce jointe ouverte, exploit web, identifiants volés
Persistancesurvivre au redémarrageservice créé, tâche planifiée, clé de démarrage
Escalade et déplacementobtenir des droits, gagner d'autres machinescompte ajouté à un groupe, connexions internes anormales
Exfiltration ou impactatteindre son objectifgros transferts sortants, chiffrement de masse

L'intérêt du modèle n'est pas descriptif, il est stratégique, et tient dans une asymétrie qu'il faut avoir comprise avant toute la suite du cours :

L'attaquant doit réussir toutes les phases. Le défenseur n'a besoin d'en casser qu'une.

C'est ce qui rend la défense en profondeur rationnelle plutôt que paranoïaque. On ne mise pas sur un mur parfait, on multiplie les occasions de détecter et d'interrompre le long de la chaîne. Et c'est ce qui explique le poids donné à la détection en phase 2 et 3 : plus on intercepte tôt, moins l'incident coûte — la différence entre un poste réinstallé et une restauration complète de l'entreprise.

Quiz · 1 question

Un scanner remonte une vulnérabilité critique (CVSS 9,8) sur un serveur de recette accessible uniquement depuis le réseau interne, et une vulnérabilité moyenne (CVSS 5,4) sur le portail de paiement exposé sur Internet. Que corrige-t-on d'abord ?

  • La critique : le score CVSS mesure la gravité, il donne l'ordre de traitementscore de gravité
  • La moyenne : le risque croise l'exposition et la valeur de l'actif, pas seulement la gravité techniquerisque = vraisemblance × gravité
  • Les deux en même temps : tout écart doit être corrigé dans le même délaitraitement uniforme

Réponse : Le CVSS mesure la gravité intrinsèque d'une faille, hors contexte : il ignore qui peut l'atteindre et ce qu'il y a derrière. Le portail de paiement est exposé à Internet — vraisemblance élevée — et porte des données de transaction — gravité élevée. Le serveur de recette exige déjà un pied dans le réseau interne. Traiter « tout en même temps » n'est pas une réponse : les moyens sont finis, et refuser de prioriser revient à laisser le hasard le faire.

Le cadre légal et l'éthique du test d'intrusion

Ce cours vous apprendra à exploiter des vulnérabilités. Cette compétence est légale ; son exercice sur un système qui ne vous appartient pas ne l'est pas. La frontière n'est pas technique, et elle ne dépend ni de votre intention ni des dégâts causés.

En droit français, la loi Godfrain du 5 janvier 1988 a introduit les articles 323-1 et suivants du code pénal :

  • accéder ou se maintenir frauduleusement dans un système : deux ans d'emprisonnement et 60 000 € d'amende — portés à trois ans et 100 000 € si des données sont altérées ;
  • entraver le fonctionnement d'un système, ou introduire, modifier, supprimer frauduleusement des données : cinq ans et 150 000 € ;
  • détenir ou mettre à disposition un outil conçu pour commettre ces infractions : puni également, avec une réserve pour la recherche et la sécurité informatique.

Trois points sont contre-intuitifs et tombent régulièrement à l'examen.

« Se maintenir » suffit. Découvrir un accès par hasard est une chose ; y rester pour regarder en est une autre, et c'est déjà l'infraction. La bonne conduite est de sortir immédiatement et de signaler.

L'absence de dégât n'est pas une défense. L'infraction est constituée par l'accès, pas par le préjudice. La quantifier sert à fixer la peine, pas à l'écarter.

Un système mal protégé reste protégé en droit. L'argument « la porte était ouverte » a été jugé et rejeté ; il ne vous protégera pas. Symétriquement, la loi pour une République numérique de 2016 protège en France celui qui signale de bonne foi une faille à l'ANSSI — mais elle protège le signalement, pas l'exploration qui l'a précédé.

Le cadre exact dépend du pays. La convention de l'Union africaine sur la cybersécurité et la protection des données à caractère personnel — dite convention de Malabo, adoptée en 2014 et entrée en vigueur en 2023 — engage les États parties à incriminer les mêmes actes, et plusieurs États ont adopté des lois nationales sur la cybercriminalité. Vérifiez le droit applicable là où vous êtes ; les principes ci-dessous, eux, n'en dépendent pas.

Ce qui rend un test licite tient en quatre exigences, et aucune n'est facultative :

  1. Une autorisation écrite du propriétaire du système, signée avant le premier paquet.
  2. Un périmètre explicite : adresses, domaines, comptes, horaires. Ce qui n'y figure pas est hors autorisation, même si c'est techniquement accessible depuis le périmètre.
  3. Des limites d'action : ce que vous n'avez pas le droit de faire — déni de service, ingénierie sociale, exfiltration réelle de données de production.
  4. Une conduite en cas de découverte grave : à qui signaler, dans quel délai, et l'arrêt immédiat en cas de compromission préexistante constatée.

Dans ce cours, tout ce que vous exploiterez tournera dans un environnement isolé — machines virtuelles, réseau fermé, applications volontairement vulnérables du type DVWA ou Juice Shop — et vous signerez une charte d'usage en début de semestre. Ce n'est pas une formalité administrative : c'est la première fois que vous rédigez le périmètre d'un test, et c'est exactement le document que vous signerez plus tard, côté prestataire ou côté client.

Quiz · 1 question

Pendant un test d'intrusion autorisé sur le domaine cible, vous découvrez qu'un serveur du périmètre a déjà été compromis par un tiers, plusieurs mois avant votre mission. Que faites-vous ?

  • Vous poursuivez le test : le serveur est dans le périmètre autorisépérimètre autorisé
  • Vous analysez la compromission pour la documenter, puis vous continuezdocumentation complète
  • Vous arrêtez, vous préservez l'état du système et vous alertez immédiatement le commanditairearrêt et alerte

Réponse : Poursuivre détruit des preuves : chacune de vos actions devient indiscernable de celles de l'attaquant réel, et vous compromettez l'analyse forensique du chapitre 9 comme la recevabilité judiciaire. Votre autorisation couvrait un test, pas une réponse à incident — ce sont deux missions, deux contrats, souvent deux équipes. La conduite attendue est l'arrêt, la préservation en l'état, et l'alerte immédiate ; c'est d'ailleurs la clause 4 de toute convention de test sérieuse.

À vous

L'exercice ci-dessous n'exploite rien : vous êtes analyste, après coup. On vous remet les journaux d'un incident réel, réduits à onze événements sur vingt-huit jours.

Replacez chaque événement dans sa phase, puis répondez à la seule question qui compte pour l'organisation : à partir de quand cette attaque était-elle détectable ?

Exercice de code

Vous êtes analyste. On vous remet vingt-huit jours de journaux après un incident. Replacez chaque événement dans sa phase de la chaîne d'attaque, puis déterminez à partir de quel jour l'attaque était détectable.

Point de départ

// Vingt-huit jours de journaux, réduits à ce qui compte.
//
// Chaque ligne est un événement observé quelque part dans le système
// d'information. Votre travail : replacer chaque événement dans la phase de
// la chaîne d'attaque à laquelle il appartient, puis dire à quelle date
// l'attaque devenait détectable.

const JOURNAL = [
  { jour: 1,  source: "web",      evenement: "412 requêtes depuis une même IP vers /wp-login.php, /admin, /.git/config" },
  { jour: 2,  source: "web",      evenement: "consultation de la page Équipe : 34 fiches, 34 adresses de courriel" },
  { jour: 6,  source: "courriel", evenement: "message « Facture_Mars.docm » à 12 comptables, expéditeur usurpé" },
  { jour: 6,  source: "poste",    evenement: "WINWORD.EXE lance powershell.exe -enc <base64>" },
  { jour: 6,  source: "reseau",   evenement: "poste-comptable-04 ouvre une connexion sortante TLS vers 185.x.x.x:443" },
  { jour: 7,  source: "poste",    evenement: "création du service Windows « WinDefendUpd », démarrage automatique" },
  { jour: 7,  source: "poste",    evenement: "clé de registre Run ajoutée pour l'utilisateur mkonate" },
  { jour: 9,  source: "annuaire", evenement: "mkonate ajouté au groupe Administrateurs du domaine" },
  { jour: 11, source: "fichiers", evenement: "lecture de 8 400 fichiers du partage RH en 40 minutes" },
  { jour: 12, source: "reseau",   evenement: "4,2 Go sortis vers 185.x.x.x, par blocs de 20 Mo, entre 2 h et 5 h" },
  { jour: 14, source: "poste",    evenement: "chiffrement de masse, note de rançon déposée sur 60 postes" },
];

// Les cinq phases, dans l'ordre.
const PHASES = ["reconnaissance", "intrusion", "persistance", "escalade", "exfiltration"];

// ── À VOUS ────────────────────────────────────────────────────────────────
// 1. Complétez classer() : rendez le nom de la phase pour chaque événement.
//    Indice : ce n'est pas la source qui décide, c'est ce que l'attaquant
//    est en train d'obtenir.
// 2. Répondez à la question du bas : à partir de quel jour l'attaque
//    était-elle détectable par un défenseur attentif ?

function classer(e) {
  return "reconnaissance"; // à compléter
}

const premierJourDetectable = 14; // à corriger

// ── Vérification ──────────────────────────────────────────────────────────
console.log("Reconstitution de l'attaque\n");
let phasePrecedente = null;
for (const e of JOURNAL) {
  const phase = classer(e);
  const marque = phase === phasePrecedente ? "  " : "▸ ";
  console.log(marque + "J" + String(e.jour).padStart(2) + " [" + phase.padEnd(14) + "] " + e.evenement.slice(0, 62));
  phasePrecedente = phase;
}
console.log("\nDétectable à partir de J" + premierJourDetectable);
console.log("Exfiltration constatée à J12, rançongiciel à J14.");
console.log("Coût de la détection tardive :", 14 - premierJourDetectable, "jours d'avance perdus.");

Solution

function classer(e) {
  const t = e.evenement;
  // Reconnaissance : l'attaquant collecte, il n'est pas encore entré.
  if (t.includes("requêtes depuis une même IP") || t.includes("page Équipe")) {
    return "reconnaissance";
  }
  // Intrusion : le premier code de l'attaquant s'exécute chez la victime.
  if (t.includes("Facture_Mars") || t.includes("powershell") || t.includes("connexion sortante TLS")) {
    return "intrusion";
  }
  // Persistance : survivre au redémarrage.
  if (t.includes("service Windows") || t.includes("registre Run")) {
    return "persistance";
  }
  // Escalade : obtenir des droits qu'on n'avait pas.
  if (t.includes("Administrateurs du domaine")) {
    return "escalade";
  }
  // Exfiltration et impact.
  return "exfiltration";
}

const premierJourDetectable = 1;

// Le balayage de J1 était déjà anormal : 412 requêtes vers des chemins
// d'administration qui n'existent pas sur ce site. Aucun utilisateur
// légitime ne demande /.git/config.
//
// Mais la vraie leçon est ailleurs. Même en manquant J1 et J2 — ce qui est
// courant, le bruit de fond d'Internet ressemble à cela — il restait SIX
// jours entre l'intrusion (J6) et l'exfiltration (J12). Une seule règle,
// « WINWORD.EXE ne lance jamais powershell.exe », coupait l'attaque au
// premier jour où elle avait touché le système d'information.
//
// C'est le raisonnement de toute la défense en profondeur : on ne mise pas
// sur une détection parfaite en phase 1, on multiplie les occasions de
// détecter le long de la chaîne. L'attaquant, lui, doit réussir TOUTES les
// phases ; le défenseur n'a besoin d'en casser qu'une.

Ce que la suite en fait

Ce chapitre a posé une grille, et les neuf suivants la remplissent.

Le chapitre 2 outille la confidentialité et l'intégrité par la cryptographie. Les chapitres 3 et 4 traitent le contrôle d'accès et le durcissement du système — les phases d'intrusion, de persistance et d'escalade. Les chapitres 5 et 6 prennent le réseau, en attaque puis en défense. Les chapitres 7 et 8 descendent dans l'applicatif, où se trouve aujourd'hui la majorité de la surface exploitable. Le chapitre 9 traite ce qui arrive quand tout cela a échoué, et le chapitre 10 remet l'ensemble en ordre de risque.

Gardez la chaîne d'attaque sous les yeux : chaque technique de ce cours occupe une case précise, et savoir laquelle vaut mieux que savoir la technique.

À retenir

Flashcards · 4 cartes

Pourquoi le score CVSS d'une vulnérabilité ne suffit-il pas à décider de l'ordre des corrections ?
Parce qu'il mesure la gravité INTRINSÈQUE, hors contexte : il ignore l'exposition du système et la valeur de l'actif derrière. L'ordre de traitement se prend sur le RISQUE, qui croise vraisemblance et gravité. Une faille moyenne sur un portail de paiement exposé passe avant une faille critique sur un serveur de test interne.
Quelle asymétrie la chaîne d'attaque met-elle en évidence, et quelle stratégie de défense en découle ?
L'attaquant doit réussir TOUTES les phases ; le défenseur n'a besoin d'en casser qu'UNE. D'où la défense en profondeur : plutôt qu'un mur unique supposé parfait, on multiplie les occasions de détecter et d'interrompre le long de la chaîne — et plus l'interruption est précoce, moins l'incident coûte.
Quelles sont les quatre conditions qui rendent un test d'intrusion licite ?
Une autorisation ÉCRITE du propriétaire, signée avant le premier paquet ; un périmètre explicite (adresses, domaines, horaires) ; des limites d'action interdites ; une conduite définie en cas de découverte grave. L'absence de dégât n'est pas une défense : en droit français, l'infraction de l'article 323-1 est constituée par l'accès ou le maintien frauduleux lui-même.
Quelles sont les trois faces de la surface d'attaque, et dans quel ordre les réduit-on ?
Réseau, logicielle, humaine. On SUPPRIME d'abord ce qui est inutile — un service désinstallé n'a aucune vulnérabilité, et c'est la seule mesure qui ne se dégrade pas avec le temps ; on RESTREINT ensuite ce qui reste (écoute locale, filtrage) ; on CLOISONNE enfin ce qui doit rester exposé. Aucune de ces trois étapes ne consiste à acheter un produit.

Chapitre 2 · 6 h

Cryptographie appliquée

Utiliser les primitives sans les réimplémenter : modes de chiffrement, hachage et sel, HMAC et AEAD, signature, X.509 et TLS, bcrypt et Argon2, aléa, ouverture post-quantique.

En octobre 2013, Adobe perd 153 millions de comptes. Les mots de passe n'étaient pas hachés : ils étaient chiffrés, en 3DES, en mode ECB, avec une clé unique pour toute la base. Deux utilisateurs ayant le même mot de passe avaient donc le même bloc chiffré. Comme les indices de récupération, eux, étaient stockés en clair, il a suffi de lire quelques indices — « nom de mon chien », « 123 quatre fois » — pour étiqueter les blocs les plus fréquents et déchiffrer la base entière, sans jamais toucher à la clé.

Chaque brique employée était solide. L'assemblage était faux, et sur les quatre erreurs commises — chiffrer au lieu de hacher, un mode qui préserve les répétitions, une clé unique, des métadonnées en clair — aucune n'exigeait de casser quoi que ce soit.

C'est tout le sujet de ce chapitre. Vous n'implémenterez aucune primitive et vous n'en casserez aucune : vous apprendrez à les assembler correctement, ce qui est l'endroit exact où la cryptographie déployée échoue.

La règle du chapitre

N'implémentez jamais une primitive cryptographique. N'inventez jamais un protocole. Utilisez une bibliothèque éprouvée, à son niveau le plus élevé.

Ce n'est pas de la modestie. Une implémentation naïve d'AES est correcte fonctionnellement et vulnérable en pratique — parce qu'elle fuit par le temps d'exécution, par le cache, par la consommation. Le chapitre 12 de l'UE de cryptographie post-quantique du master est entièrement consacré à ces canaux auxiliaires ; retenez ici qu'un code qui « marche » n'est pas un code sûr.

Le corollaire est pratique : préférez toujours l'API la plus abstraite disponible. libsodium et son crypto_secretbox, l'AEAD de la bibliothèque standard, un TLS géré par le système — plutôt que « AES + mode + padding + IV » assemblés à la main. Chaque paramètre que l'API vous laisse choisir est un paramètre que vous pouvez choisir mal.

Chiffrement symétrique : la primitive, puis le mode

Le chiffrement symétrique emploie la même clé pour chiffrer et déchiffrer. La primitive standard est AES, en clés de 128, 192 ou 256 bits ; elle chiffre des blocs de 128 bits, et rien de plus. C'est le mode opératoire qui dit comment enchaîner ces blocs — et c'est lui qui décide de la sécurité réelle.

ModeCe qu'il faitVerdict
ECBchaque bloc chiffré indépendammentà proscrire : blocs égaux, chiffrés égaux
CBCchaque bloc est mélangé au précédent, IV aléatoireacceptable, mais malléable et sensible à l'oracle de padding
CTRtransforme AES en chiffrement par flot, nonce + compteurbon, à condition de ne jamais réutiliser le nonce
GCMCTR + authentification intégréele défaut : confidentialité et intégrité

L'image du « pingouin ECB » est devenue canonique : une image chiffrée en ECB reste parfaitement reconnaissable, parce que les zones uniformes produisent des blocs chiffrés identiques. C'est exactement l'erreur d'Adobe, un pixel remplacé par un mot de passe.

Deux règles opérationnelles se retiennent telles quelles.

Un IV ou un nonce n'est pas un secret, mais il ne se répète jamais. L'IV de CBC doit être imprévisible et aléatoire ; le nonce de CTR et de GCM doit seulement être unique pour une clé donnée. Réutiliser un nonce en GCM ne fait pas que révéler le xor de deux clairs : cela permet de récupérer la clé d'authentification et de forger des messages valides. C'est la défaillance la plus fréquente du chiffrement moderne, et elle est totale.

Chiffrer n'est pas protéger l'intégrité. En CTR comme en GCM sans vérification, inverser un bit du chiffré inverse le bit correspondant du clair. Un attaquant qui sait où se trouve le montant dans VIREMENT 0100 EUR le modifie sans lire le message ni connaître la clé. D'où la section sur l'AEAD plus bas — et d'où le fait que GCM soit le mode par défaut plutôt que CTR.

Hachage : ce qu'une empreinte garantit

Une fonction de hachage produit une empreinte de taille fixe. On lui demande trois propriétés :

  • résistance à la préimage : à partir de l'empreinte, on ne retrouve pas l'entrée ;
  • résistance à la seconde préimage : à partir d'un message, on n'en trouve pas un autre de même empreinte ;
  • résistance aux collisions : on ne trouve pas deux messages quelconques de même empreinte.

La troisième est la plus fragile, à cause du paradoxe des anniversaires : une empreinte de n bits ne coûte que 2^(n/2) essais à faire collisionner. C'est pourquoi 128 bits d'empreinte ne donnent que 64 bits de sécurité en collision, et pourquoi SHA-256 est le minimum courant.

FonctionStatut
MD5cassée. Collisions en secondes. À n'employer pour rien qui touche à la sécurité
SHA-1cassée. Collision publique en 2017 (SHAttered), puis attaque à préfixe choisi en 2020
SHA-256, SHA-512recommandées
SHA-3, BLAKE2, BLAKE3recommandées ; SHA-3 est immune à l'extension de longueur

Trois confusions à défaire.

Hacher n'est pas chiffrer. Un hachage ne se déchiffre pas : il n'y a pas de clé et l'opération n'est pas inversible. Dire « le mot de passe est crypté » est doublement faux — et le verbe français est « chiffrer ».

Une empreinte seule ne prouve pas l'origine. Publier un fichier et son SHA-256 sur le même serveur ne protège de rien : qui modifie le fichier modifie l'empreinte. Il faut un canal distinct, ou une signature.

MD5 et SHA-1 ne sont pas « faibles », elles sont cassées. La nuance importe : contre les collisions, aucune longueur de clé ni aucun sel ne les répare.

Stocker un mot de passe

C'est le cas d'usage où l'intuition trompe le plus, parce que la bonne réponse consiste à choisir délibérément une fonction lente.

Un serveur vérifie un mot de passe une fois par connexion : 250 ms de calcul y sont invisibles. Un attaquant qui a volé la base en teste des milliards — et il paie les mêmes 250 ms par essai. La lenteur ne coûte presque rien au défenseur et tout à l'attaquant. C'est l'unique cas de ce cours où l'inefficacité est la mesure de sécurité.

Le stockage correct combine trois éléments, dont aucun ne remplace les autres :

  1. Un sel aléatoire, unique par utilisateur, stocké en clair à côté de l'empreinte. Il ne rend pas un mot de passe faible plus difficile à deviner : il empêche de mutualiser l'attaque — plus de table arc-en-ciel, plus de table précalculée réutilisable, et deux utilisateurs de même mot de passe n'ont plus la même empreinte.
  2. Une fonction lente et paramétrable : Argon2id de préférence, sinon scrypt ou bcrypt. PBKDF2 reste acceptable quand une contrainte de conformité l'impose, mais il se parallélise trop bien sur GPU.
  3. Des paramètres calibrés sur votre matériel : pour Argon2id, viser de l'ordre de 64 Mio de mémoire et une durée de 200 à 500 ms sur le serveur cible. La consommation mémoire est le point clé — c'est elle qui neutralise l'avantage des GPU et des circuits dédiés.

On y ajoute parfois un poivre : un secret global, stocké hors de la base — variable d'environnement, module matériel. Il ne sert que dans un scénario, mais un scénario fréquent : la base fuit, le code ne fuit pas. Le poivre ne remplace jamais le sel.

Quiz · 1 question

Une équipe stocke ses mots de passe en SHA-256 avec un sel aléatoire de 32 octets par utilisateur. Est-ce correct ?

  • Oui : sel unique et fonction moderne, c'est l'état de l'artsel + fonction moderne
  • Non : SHA-256 est trop rapide, il faut une fonction lente comme Argon2id ou bcryptvitesse de la fonction
  • Non : le sel doit rester secret, sinon il ne sert à riensecret du sel

Réponse : Le sel est fait pour être public — il est stocké en clair à côté de l'empreinte, et son rôle est d'empêcher la mutualisation de l'attaque, pas de cacher quoi que ce soit. Le vrai défaut est la vitesse : SHA-256 est conçue pour être rapide, et un GPU en calcule des milliards par seconde. Le sel oblige l'attaquant à traiter les comptes un par un, mais chaque compte reste bon marché. Il faut les deux : le sel contre la mutualisation, la lenteur contre le débit.

Intégrité et authenticité : HMAC, puis AEAD

Pour prouver qu'un message n'a pas été modifié et vient bien du détenteur de la clé, on emploie un code d'authentification de message. Le standard est HMAC, construit sur une fonction de hachage — HMAC-SHA256 — et sa construction n'est pas décorative : elle existe précisément pour résister à l'attaque par extension de longueur, qui casse le naïf hacher(clé + message).

Quand on veut à la fois chiffrer et authentifier, trois assemblages sont possibles et un seul est sûr en général : chiffrer puis authentifier le chiffré (encrypt-then-MAC). Les deux autres ordres ont produit des vulnérabilités réelles dans TLS et dans SSH.

En pratique, on ne fait plus l'assemblage soi-même : on emploie un chiffrement authentifié (AEAD), qui fait les deux en une opération et refuse de déchiffrer un message altéré.

ConstructionQuand
AES-GCMmatériel avec accélération AES — c'est-à-dire presque tout serveur ou processeur récent
ChaCha20-Poly1305logiciel pur, mobile, embarqué : plus rapide et plus résistant aux attaques par cache
XChaCha20-Poly1305même chose avec un nonce assez long pour être tiré au hasard sans risque de collision

Les AEAD acceptent aussi des données associées : authentifiées mais non chiffrées — un en-tête, un identifiant de session, un numéro de version. C'est l'endroit propre où lier un chiffré à son contexte, et donc empêcher qu'il soit rejoué ailleurs.

Un détail d'implémentation, souvent négligé et pourtant décisif : toute comparaison de secret se fait en temps constant. Un === sur une signature s'arrête au premier octet différent et révèle, par le temps de réponse, combien d'octets étaient corrects — ce qui suffit à forger la valeur octet par octet. Toute bibliothèque sérieuse fournit une comparaison dédiée ; utilisez-la.

Asymétrique : échanger une clé, signer un message

La cryptographie asymétrique emploie deux clés liées mathématiquement : une publique, une privée. Elle résout deux problèmes que le symétrique ne sait pas résoudre — se mettre d'accord sur une clé sans s'être jamais rencontrés, et prouver une origine à un tiers.

UsageQui emploie quoiStandards
Échange de cléson dérive un secret communECDH sur X25519 ; RSA-KEM en héritage
Signatureprivée pour signer, publique pour vérifierEd25519, ECDSA, RSA-PSS
Chiffrementpublique pour chiffrer, privée pour déchiffrerRSA-OAEP, uniquement pour de petites données

Trois points qui reviennent tout le temps.

On ne chiffre pas un gros message en asymétrique. C'est des milliers de fois plus lent, et RSA est borné par la taille du module. Le schéma réel est hybride : une clé symétrique aléatoire chiffre le message, et l'asymétrique ne protège que cette clé. TLS, PGP, S/MIME et les messageries chiffrées font tous exactement cela.

Signature et MAC ne donnent pas la même garantie. Un MAC repose sur une clé partagée : le vérifieur peut fabriquer lui-même n'importe quel message valide, donc rien ne prouve l'origine devant un tiers. Seule la signature apporte la non-répudiation.

La confidentialité persistante est une propriété du protocole, pas de la primitive. Si la clé de session dérive d'une clé statique, la compromission de celle-ci déchiffre tout le trafic passé enregistré. C'est pourquoi TLS 1.3 impose un échange éphémère : la clé de session n'est reconstituable à partir d'aucun secret durable.

Certificats, PKI, TLS

Une clé publique ne dit pas à qui elle appartient. Un certificat X.509 est cette clé publique accompagnée d'une identité — un nom de domaine — et d'une signature d'une autorité de certification. Le navigateur ne fait confiance au certificat que parce qu'il fait déjà confiance à l'autorité, dont la clé est dans son magasin racine : la confiance est déléguée le long d'une chaîne, jusqu'à une racine installée d'avance.

Ce que TLS garantit : la confidentialité et l'intégrité du transport, et l'authentification du serveur — vous parlez bien à banque.example.

Ce que TLS ne garantit pas, et qu'on lui prête constamment : que le site d'en face soit honnête ; que l'application derrière soit sûre ; que la donnée soit protégée une fois arrivée. Un site de hameçonnage a un cadenas vert, obtenu gratuitement et automatiquement. Le cadenas authentifie le domaine, pas l'intention.

Trois erreurs d'implémentation à connaître, parce qu'elles sont fréquentes et silencieuses :

  1. Désactiver la vérification du certificat pour faire taire une erreur en développement, puis livrer ce code. La connexion reste chiffrée — contre n'importe qui sauf l'attaquant du milieu, c'est-à-dire contre personne d'utile.
  2. Vérifier la chaîne mais pas le nom. Un certificat valide pour un autre domaine reste un certificat valide ; sans contrôle du nom, l'attaquant présente le sien.
  3. Ignorer la révocation et l'expiration. OCSP agrafé, listes de révocation, durées de vie courtes : la révocation reste le point faible de la PKI, et la réponse moderne est la réduction de la durée de validité — quelques mois — plutôt que la révocation elle-même.

Deux mécanismes utiles complètent le tableau. La transparence des certificats publie dans des journaux publics auditables tout certificat émis, ce qui rend une émission frauduleuse détectable après coup. L'épinglage fige la clé attendue dans l'application : très efficace sur une application mobile que vous maîtrisez, très dangereux sur le web, où une erreur bloque le domaine pour la durée de l'épinglage.

Quiz · 1 question

Une application mobile envoie les identifiants de ses utilisateurs en HTTPS vers son API. Le développeur a ajouté une option qui accepte les certificats auto-signés, pour tester derrière le proxy de l'entreprise. Que se passe-t-il en production ?

  • Rien : le trafic reste chiffré en AES, donc illisible pour un tierschiffrement du transport
  • N'importe qui sur le chemin peut présenter son propre certificat et lire tout le traficauthentification du pair
  • Le risque est limité : seul l'opérateur du réseau pourrait intercepteracteur privilégié

Réponse : Le chiffrement sans authentification du pair ne protège de rien : vous chiffrez soigneusement à destination de l'attaquant. Celui-ci présente un certificat auto-signé, l'application l'accepte, il déchiffre, lit, modifie, puis rechiffre vers le vrai serveur — l'homme du milieu du chapitre 5, monté en trois commandes sur un Wi-Fi public. Ce n'est pas un risque limité à l'opérateur : tout appareil du même réseau local peut se placer sur le chemin par usurpation ARP.

L'aléa, et pourquoi il casse tout

Toute la cryptographie repose sur des valeurs imprévisibles : clés, IV, nonces, sels, jetons de session, jetons de réinitialisation de mot de passe. Un aléa prévisible rend l'ensemble inutile, sans qu'aucune primitive n'ait été cassée.

La règle est binaire. Utilisez un générateur cryptographique/dev/urandom, getrandom(), crypto.randomBytes, crypto.getRandomValues, secrets en Python. Jamais un générateur généraliste : Math.random(), rand(), random.random(), ni quoi que ce soit initialisé par l'horloge. Ces derniers sont conçus pour la simulation, et leur état interne se reconstitue à partir de quelques sorties observées.

L'histoire donne la mesure du risque. En 2008, une ligne retirée par erreur d'OpenSSL dans Debian a réduit l'entropie du générateur au seul identifiant de processus : environ 32 000 clés possibles, pendant près de deux ans. Toutes les clés SSH, TLS et OpenVPN générées dans cet intervalle étaient énumérables en quelques minutes. Aucun algorithme n'était en cause.

Ouverture : ce que le quantique change

Un ordinateur quantique de taille suffisante casserait, par l'algorithme de Shor, toute la cryptographie asymétrique déployée : RSA, Diffie-Hellman, courbes elliptiques. Le symétrique et le hachage tiennent mieux — l'algorithme de Grover ne donne qu'un gain quadratique, dont on se protège en doublant les tailles, d'où la préférence pour AES-256 et SHA-384.

L'échéance est incertaine, mais une menace est déjà actuelle : récolter maintenant, déchiffrer plus tard. Un adversaire enregistre aujourd'hui du trafic chiffré qu'il déchiffrera le jour venu. Toute donnée dont la valeur dépasse dix ans est donc concernée dès à présent.

Les standards existent depuis 2024 : ML-KEM (FIPS 203) pour l'échange de clés, ML-DSA (FIPS 204) et SLH-DSA (FIPS 205) pour la signature. Le déploiement en cours est hybride — X25519 combiné à ML-KEM — de façon que la sécurité tienne si l'une des deux familles tombe. Le reste appartient au master ; l'UE de cryptographie post-quantique y consacre quatorze chapitres.

À vous

L'exercice suit le fil de tous les TP de ce cours : attaquer d'abord, corriger ensuite.

Vous recevez une base de mots de passe hachés qui a fui. Vous la cassez avec un dictionnaire de douze mots, en comptant vos hachages. Puis vous ajoutez un sel par compte et vous rejouez exactement la même attaque. Ce n'est pas le nombre de comptes cassés qui change — c'est le coût, et c'est là qu'est la leçon.

Exercice de code

Une base de mots de passe hachés a fui. Cassez-la avec un dictionnaire de douze mots, en comptant vos hachages. Ajoutez ensuite un sel par compte et rejouez la même attaque : ce n'est pas le nombre de comptes cassés qui change, c'est le coût.

Point de départ

// Une base d'utilisateurs a fui. Les mots de passe sont « hachés », donc
// tout va bien — c'est du moins ce qu'affirme le communiqué de presse.
//
// La fonction de hachage ci-dessous est un jouet : le vrai SHA-256 ne
// changerait RIEN à ce que vous allez montrer. C'est le schéma qui est en
// cause, pas la primitive.

function hacher(texte) {
  let h = 0x811c9dc5;
  for (let i = 0; i < texte.length; i++) {
    h ^= texte.charCodeAt(i);
    h = Math.imul(h, 0x01000193) >>> 0;
  }
  return h.toString(16).padStart(8, "0");
}

// ── La fuite ──────────────────────────────────────────────────────────────
const FUITE = [
  { compte: "amina",   hache: hacher("soleil") },
  { compte: "bakary",  hache: hacher("123456") },
  { compte: "chantal", hache: hacher("motdepasse") },
  { compte: "diallo",  hache: hacher("soleil") },
  { compte: "eve",     hache: hacher("Tr0ub4dor&3-2026") },
  { compte: "fatou",   hache: hacher("azerty") },
  { compte: "gerard",  hache: hacher("123456") },
  { compte: "hawa",    hache: hacher("soleil") },
];

const DICTIONNAIRE = [
  "123456", "azerty", "motdepasse", "soleil", "qwerty", "admin",
  "bonjour", "football", "password", "iloveyou", "000000", "abc123",
];

// ── ATTAQUE 1 — à vous ────────────────────────────────────────────────────
// Construisez une table haché → mot, puis retrouvez les comptes cassés.
// Combien de fois hachez-vous ? Retenez ce nombre.
let calculs1 = 0;

function attaquerSansSel() {
  const casses = [];
  // à compléter
  return casses;
}

// ── LA CORRECTION — à vous aussi ──────────────────────────────────────────
// Ajoutez un sel ALÉATOIRE ET DISTINCT par compte, stocké en clair à côté du
// haché, et rejouez la même attaque.
function selAleatoire() {
  return Math.random().toString(36).slice(2, 10);
}

const FUITE_SALEE = [
  { compte: "amina",   sel: "", hache: "" }, // à construire
];

let calculs2 = 0;

function attaquerAvecSel() {
  const casses = [];
  // à compléter
  return casses;
}

// ── Mesure ────────────────────────────────────────────────────────────────
const c1 = attaquerSansSel();
console.log("Sans sel  :", c1.length, "comptes cassés sur", FUITE.length, "—", calculs1, "hachages");
const c2 = attaquerAvecSel();
console.log("Avec sel  :", c2.length, "comptes cassés sur", FUITE_SALEE.length, "—", calculs2, "hachages");

Solution

// ── ATTAQUE 1 ─────────────────────────────────────────────────────────────
let calculs1 = 0;

function attaquerSansSel() {
  // UNE table, calculée une seule fois, valable pour tous les comptes.
  const table = new Map();
  for (const mot of DICTIONNAIRE) {
    table.set(hacher(mot), mot);
    calculs1++;
  }
  const casses = [];
  for (const u of FUITE) {
    const mot = table.get(u.hache);           // lecture, pas de calcul
    if (mot) casses.push(u.compte + " = " + mot);
  }
  return casses;
}
// 7 comptes sur 8, pour 12 hachages. Et le coût ne dépend PAS du nombre de
// comptes : la même table casserait huit millions d'utilisateurs.
// Remarquez au passage que amina, diallo et hawa ont le même haché — donc le
// même mot de passe. La base non salée fuit cette information à elle seule.
// Seule eve résiste, et c'est son mot de passe qui la sauve, pas le schéma.

// ── LA CORRECTION ─────────────────────────────────────────────────────────
const FUITE_SALEE = FUITE.map((u, i) => {
  const clair = ["soleil", "123456", "motdepasse", "soleil",
                 "Tr0ub4dor&3-2026", "azerty", "123456", "soleil"][i];
  const sel = selAleatoire();
  return { compte: u.compte, sel, hache: hacher(sel + clair) };
});

let calculs2 = 0;

function attaquerAvecSel() {
  const casses = [];
  for (const u of FUITE_SALEE) {
    // La table ne se réutilise plus : il faut la REFAIRE pour chaque sel.
    for (const mot of DICTIONNAIRE) {
      calculs2++;
      if (hacher(u.sel + mot) === u.hache) {
        casses.push(u.compte + " = " + mot);
        break;
      }
    }
  }
  return casses;
}
// Toujours 7 comptes cassés — mais pour ~70 hachages au lieu de 12, et
// surtout un coût désormais PROPORTIONNEL au nombre de comptes.
//
// C'est exactement ce que le sel fait, et rien de plus : il ne rend pas un
// mot de passe faible plus difficile à deviner, il détruit la MUTUALISATION
// de l'attaque. Plus de table arc-en-ciel, plus de table précalculée
// réutilisable, plus de hachés identiques révélant des mots de passe égaux.
//
// Sur cette base de 8 comptes le facteur est de 6 ; sur 10 millions de
// comptes il est de 10 millions. C'est la seule raison pour laquelle le sel
// existe.
//
// Il reste la deuxième moitié du travail, que ce jouet ne montre pas :
// hacher LENTEMENT. Notre fonction fait quelques nanosecondes, ce qui laisse
// un attaquant en tester des milliards par seconde sur GPU, sel ou pas.
// Argon2id ou bcrypt calibrés à ~250 ms le ramènent à quelques milliers par
// seconde. Sel ET lenteur : l'un contre la mutualisation, l'autre contre le
// débit. Ni l'un ni l'autre ne se remplace.

Ce que la suite en fait

La cryptographie est un outil, pas une solution ; elle protège une donnée en transit ou au repos, et ne dit rien de qui a le droit d'y accéder. C'est précisément l'objet du chapitre 3, qui reprend le stockage des mots de passe vu ici pour le placer dans une chaîne complète d'authentification, et y ajoute les sessions, les jetons et les modèles d'autorisation.

Le chapitre 6 réemploiera TLS pour les VPN et les tunnels, et le chapitre 7 pour la sécurité des API et des JWT — où l'on verra qu'un jeton signé mal vérifié annule tout ce qui précède.

À retenir

Flashcards · 4 cartes

Pourquoi le sel ne suffit-il pas à protéger une base de mots de passe ?
Parce qu'il ne traite qu'un des deux problèmes. Le sel détruit la MUTUALISATION de l'attaque : plus de table arc-en-ciel, plus d'empreintes identiques révélant des mots de passe égaux. Mais chaque compte reste bon marché à attaquer si la fonction est rapide. Il faut aussi la LENTEUR — Argon2id, scrypt ou bcrypt calibrés à 200-500 ms — pour effondrer le débit de l'attaquant.
Qu'est-ce que TLS garantit, et qu'est-ce qu'on lui prête à tort ?
Il garantit la confidentialité et l'intégrité du transport, et l'authentification du SERVEUR : vous parlez bien au domaine annoncé. Il ne dit rien de l'honnêteté du site, de la sécurité de l'application derrière, ni du sort de la donnée une fois arrivée. Un site de hameçonnage a un cadenas valide : le cadenas authentifie le domaine, pas l'intention.
Que se passe-t-il si un nonce est réutilisé avec la même clé en AES-GCM ?
L'effondrement complet. Comme en CTR, le xor des deux clairs se déduit des deux chiffrés — mais surtout, la réutilisation permet de récupérer la clé d'authentification et donc de FORGER des messages valides. C'est la défaillance la plus fréquente du chiffrement moderne : le nonce n'est pas un secret, mais il ne doit jamais se répéter pour une clé donnée.
Pourquoi ne chiffre-t-on jamais un gros message directement en RSA ?
Parce que c'est des milliers de fois plus lent que le symétrique et borné par la taille du module. Le schéma réel est HYBRIDE : une clé symétrique aléatoire chiffre le message, et l'asymétrique ne protège que cette clé. TLS, PGP, S/MIME et les messageries chiffrées fonctionnent tous ainsi.