C2 — Sécurité des systèmesDans le dialogue d’impression, choisissez « Enregistrer au format PDF » comme destination.
Retour

Licence 3 · Cybersécurité

Cours 2Sécurité des systèmes

Contrôler qui entre et ce qu'il peut faire une fois entré : authentification, autorisation, et durcissement du système d'exploitation.

2 chapitres · 12 h de travail estimé

  1. 1. Authentification et contrôle d'accès5 h
  2. 2. Sécurité des systèmes d'exploitation7 h

Chapitre 1 · 5 h

Authentification et contrôle d'accès

Identification, authentification, autorisation ; facteurs et MFA ; sessions et jetons ; DAC, MAC, RBAC ; moindre privilège ; dictionnaire, force brute et tables arc-en-ciel.

Le 7 mai 2021, Colonial Pipeline arrête le principal oléoduc de la côte est des États-Unis. Pénuries de carburant dans dix-sept États, état d'urgence fédéral, 4,4 millions de dollars de rançon. Le point d'entrée : un compte VPN inactif, encore valide, dont le mot de passe figurait dans une fuite antérieure, et qui n'était pas protégé par une authentification multifacteur.

Aucune vulnérabilité logicielle n'a été exploitée. Aucun chiffrement n'a été cassé. Un attaquant s'est authentifié — correctement, du point de vue du système — avec des identifiants valides.

C'est le cas général plutôt que l'exception. Le contrôle d'accès est la fonction de sécurité la plus sollicitée d'un système : à chaque requête, il faut décider qui parle et ce qu'il a le droit de faire. Ce chapitre traite les deux questions, dans cet ordre, et l'ordre n'est pas négociable.

Trois mots que l'on confond, et ce que la confusion coûte

TermeQuestionExempleÉchec typique
IdentificationQui prétendez-vous être ?saisir amina@exemple.frénumération de comptes
AuthentificationPouvez-vous le prouver ?mot de passe, clé, empreinteidentifiants volés ou devinés
AutorisationAvez-vous le droit de faire ceci ?lire ce dossier, virer ces fondscontrôle d'accès défaillant

L'identification n'est pas une preuve : une adresse de courriel est publique. La confondre avec l'authentification produit la faille classique du « lien de réinitialisation envoyé à l'adresse saisie » — où c'est l'attaquant qui choisit l'adresse.

L'autorisation est distincte de l'authentification et se vérifie à chaque requête, côté serveur. Un utilisateur authentifié n'est pas un utilisateur autorisé. C'est la confusion la plus coûteuse du domaine : elle produit la première catégorie de l'OWASP Top 10, que le chapitre 7 exploitera pour de bon.

Une note pratique sur l'énumération de comptes : si le formulaire répond « ce compte n'existe pas » puis « mot de passe incorrect », il vient de dire à l'attaquant quels comptes existent — et transforme une attaque à l'aveugle en attaque ciblée. La réponse doit être identique, en texte comme en temps de réponse, dans les deux cas.

Les facteurs, et pourquoi il en faut plusieurs

Un facteur d'authentification appartient à l'une de trois catégories :

  • ce que l'on sait : mot de passe, code PIN, question secrète ;
  • ce que l'on possède : téléphone, clé matérielle, carte à puce ;
  • ce que l'on est : empreinte, visage, voix.

Une authentification est multifacteur quand elle combine des catégories différentes. Un mot de passe suivi d'une question secrète n'est pas du MFA : les deux relèvent du savoir, et les mêmes fuites les emportent ensemble.

Tous les seconds facteurs ne se valent pas, et l'écart est plus grand qu'on ne l'imagine.

Second facteurRésiste au vol de mot de passeRésiste au hameçonnageRemarque
Code par SMSouinonvulnérable au détournement de carte SIM et au relais en temps réel
Code TOTP (application)ouinonl'attaquant relaie le code sur un faux site en quelques secondes
Notification à validerouifaibleexposé à la lassitude : l'utilisateur finit par accepter
FIDO2 / WebAuthnouiouila clé signe le domaine d'origine — un faux site n'obtient rien

La colonne décisive est la troisième. TOTP et SMS transmettent un secret que l'utilisateur peut recopier ailleurs ; une clé FIDO2 lie cryptographiquement la réponse au domaine qui la demande, ce qu'aucun site de hameçonnage ne peut contourner. C'est la seule technologie de ce chapitre qui supprime une classe entière d'attaques au lieu de la rendre plus coûteuse.

Cela ne rend pas le SMS inutile : un MFA faible vaut infiniment mieux que pas de MFA du tout, et il aurait suffi à empêcher Colonial Pipeline. La hiérarchie sert à choisir où investir, pas à refuser l'intermédiaire.

Comment tombent les mots de passe

Quatre attaques, souvent confondues, aux contre-mesures différentes.

La force brute essaie tout l'espace. Elle n'est réaliste que hors ligne, sur une base volée. En ligne, dix essais par minute la rendent absurde.

L'attaque par dictionnaire essaie des mots de passe probables — listes de fuites, mutations connues. Elle réussit parce que les humains choisissent mal : Printemps2026! satisfait toutes les règles de composition et figure dans toutes les listes.

Le bourrage d'identifiants rejoue des couples adresse/mot de passe issus d'autres fuites. Il exploite la réutilisation, et c'est aujourd'hui l'attaque la plus rentable : la victime a un mot de passe excellent, mais le même partout.

La pulvérisation inverse la boucle : un seul mot de passe très probable, essayé sur des milliers de comptes. Un compte ne voit qu'un essai, ce qui la rend invisible à tout verrouillage par compte.

Les tables arc-en-ciel ne sont pas une attaque distincte mais un compromis temps-mémoire : on précalcule pour ne plus calculer. Le sel du chapitre 2 les a rendues obsolètes — et c'est précisément pour cela qu'il existe.

Les défenses, dans l'ordre d'efficacité :

  1. Un stockage lent et salé — chapitre 2. C'est le seul levier qui agit sur tous les comptes à la fois, et il ne dépend pas des utilisateurs.
  2. La comparaison aux mots de passe compromis à la création. Refuser les mots de passe déjà présents dans les fuites publiques élimine l'essentiel du dictionnaire et du bourrage.
  3. La limitation de débit, par compte et par adresse source, avec un délai croissant. Le verrouillage dur crée un déni de service ; le ralentissement progressif, non.
  4. Le MFA, qui rend l'ensemble largement théorique — un mot de passe volé ne suffit plus.
  5. La détection : pulvérisation, connexions impossibles géographiquement, comptes dormants réactivés. C'est ce dernier point qui manquait à Colonial Pipeline.

Ce que les recommandations actuelles — NIST SP 800-63B, ANSSI — ont abandonné, et qu'il faut cesser d'exiger : les règles de composition obligatoires (une majuscule, un chiffre, un symbole) et l'expiration périodique. Les deux dégradent mesurablement la sécurité, parce qu'elles poussent vers des motifs prévisibles. On demande désormais de la longueur — douze caractères au minimum — et l'absence dans les listes de compromission.

Quiz · 1 question

Un service impose 8 caractères avec majuscule, chiffre et symbole, et un changement tous les 90 jours. Un audit constate un taux élevé de compromission par bourrage d'identifiants. Quelle correction est la plus efficace ?

  • Passer à 12 caractères minimum, supprimer l'expiration, et refuser les mots de passe présents dans les fuites connueslongueur et listes de compromission
  • Imposer deux symboles au lieu d'un et réduire l'expiration à 30 joursrègles plus strictes
  • Chiffrer la base de mots de passe avec AES-256 plutôt que de la hacherchiffrement de la base

Réponse : Durcir les règles de composition et raccourcir l'expiration accentue exactement le comportement à l'origine du problème : l'utilisateur produit « Printemps2026! », puis « Ete2026! », tous deux dans les listes d'attaque. Chiffrer la base est la faute d'Adobe en 2013 — un mot de passe ne se déchiffre pas, il se hache lentement. La longueur et la comparaison aux fuites attaquent la cause réelle : des mots de passe prévisibles et réutilisés.

Sessions et jetons

Une fois l'utilisateur authentifié, on ne redemande pas le mot de passe à chaque requête : on lui remet un jeton de session. Ce jeton devient l'équivalent du mot de passe pour toute sa durée de vie — et il se protège comme tel.

Ce qu'un identifiant de session doit être : imprévisible (au moins 128 bits d'un générateur cryptographique — jamais un compteur, jamais l'identifiant de l'utilisateur), transmis uniquement en HTTPS, stocké dans un cookie portant les attributs HttpOnly (inaccessible au JavaScript, donc au vol par XSS), Secure et SameSite.

Trois règles de cycle de vie, chacune répondant à une attaque précise :

  • Régénérer l'identifiant à la connexion, et à tout changement de privilège. Sans cela, l'attaquant fixe d'avance la valeur du cookie dans le navigateur de la victime, attend qu'elle se connecte, et hérite d'une session authentifiée : c'est la fixation de session.
  • Expirer : une durée absolue et une durée d'inactivité. Une session éternelle est un mot de passe éternel.
  • Révoquer réellement à la déconnexion, côté serveur. Supprimer le cookie du navigateur n'invalide rien pour qui l'avait déjà copié.

Le cas des JWT mérite un mot, parce qu'il est mal compris. Un JWT est un jeton auto-porté : le serveur ne stocke rien, il vérifie une signature. C'est commode pour répartir la charge, et cela crée un problème réel : on ne peut pas révoquer ce qu'on ne stocke pas. Un JWT volé reste valide jusqu'à son expiration, quoi qu'il arrive — compte supprimé, droits retirés, mot de passe changé. La parade habituelle est une durée de vie très courte accompagnée d'un jeton de rafraîchissement, lui, révocable. Le chapitre 7 reprendra les JWT côté attaque, où ils échouent surtout par vérification de signature incomplète.

Autoriser : quatre modèles

L'autorisation répond à « ce sujet peut-il faire cette action sur cet objet ? ». Quatre modèles, du plus souple au plus rigide.

ModèleQui décideForceFaiblesse
DAC — discrétionnairele propriétaire de l'objetsimple, naturella permission se propage sans contrôle central
MAC — obligatoireune politique centrale, non contournablerésiste à l'utilisateur imprudent et au malicielrigide, coûteux à administrer
RBAC — par rôlesl'administrateur, via des rôlespasse à l'échelle, s'auditedérive : les rôles s'accumulent
ABAC — par attributsdes règles sur le contextetrès fin (heure, lieu, appareil)difficile à raisonner et à tester

Les permissions Unix — propriétaire, groupe, autres — sont du DAC : le propriétaire d'un fichier décide qui le lit, et rien n'empêche un utilisateur de tout ouvrir en lecture. SELinux et AppArmor ajoutent une couche MAC par-dessus : même root ne franchit pas une règle interdite par la politique, ce qui limite les dégâts d'un processus compromis. Le chapitre 4 y revient.

Le RBAC est ce que vous implémenterez en pratique. Sa maladie chronique est la dérive de privilèges : un employé change trois fois de poste, accumule trois jeux de rôles, et finit avec des droits que personne n'a jamais décidé de lui donner. Le remède n'est pas technique mais organisationnel — une revue périodique des habilitations, dont le chapitre 10 fait une exigence de gouvernance.

Moindre privilège, et séparation des tâches

Deux principes, souvent cités ensemble, qui ne répondent pas à la même menace.

Le moindre privilège : chaque sujet reçoit exactement les droits nécessaires à sa fonction, pour la durée nécessaire, et rien de plus. Il ne prévient pas l'intrusion — il borne son rayon d'action. Une application web compromise qui tourne sous un compte dédié sans droit d'écriture sur son propre code n'offre à l'attaquant qu'une fraction de ce qu'un compte administrateur lui aurait donné. C'est le principe qui décide de l'ampleur d'un incident, et c'est pourquoi il traverse tout ce cours.

La séparation des tâches : aucune personne seule ne doit pouvoir mener à terme une opération critique. Celui qui saisit un virement ne l'approuve pas ; celui qui écrit le code ne le déploie pas en production seul. Elle répond à la menace interne du chapitre 1, celle contre laquelle aucune défense périmétrique ne peut rien.

Quiz · 1 question

Une API délivre des JWT valables 24 h. Un administrateur licencie un employé et supprime son compte à 9 h. L'employé avait obtenu un jeton à 8 h 30. Que peut-il faire ?

  • Plus rien : la suppression du compte invalide immédiatement tous ses jetonsrévocation immédiate
  • Continuer à utiliser l'API jusqu'à 8 h 30 le lendemain, sauf si une liste de révocation est vérifiée à chaque requêtejeton auto-porté
  • Rien, à condition que l'API soit en HTTPSchiffrement du transport

Réponse : Un JWT est auto-porté : le serveur vérifie une signature et une date d'expiration, sans consulter aucun état. Rien dans le jeton ne dépend de l'existence du compte, et le supprimer ne change donc rien. HTTPS protège le transport, pas la validité du jeton. La parade habituelle est une durée de vie très courte — quelques minutes — avec un jeton de rafraîchissement révocable, ou une liste de révocation consultée à chaque requête, ce qui rend le jeton à nouveau dépendant d'un état côté serveur.

À vous

La politique de mot de passe est le seul sujet de ce cours où l'intuition commune est mesurablement fausse. Plutôt que de l'affirmer, calculez.

L'exercice vous fait estimer l'entropie de quatre secrets, puis le temps nécessaire pour les casser dans trois scénarios : base volée hachée en SHA-256, base volée hachée en bcrypt, et attaque en ligne limitée à dix essais par minute. Vous en tirerez la politique à écrire — et elle ne ressemble pas à celle de votre banque.

Exercice de code

Calculez l'entropie de quatre secrets, puis le temps moyen pour les casser dans trois scénarios : base volée hachée en SHA-256, base volée hachée en bcrypt, et attaque en ligne limitée à dix essais par minute. Concluez sur la politique à écrire.

Point de départ

// Combien de temps tient un mot de passe ? La question n'a pas de réponse
// tant qu'on n'a pas dit CONTRE QUOI. Trois scénarios, trois ordres de
// grandeur — et la même politique de mot de passe n'y répond pas.

// Débits observés en 2024 sur une seule carte graphique de bureau.
const SCENARIOS = [
  { nom: "hors ligne, base en SHA-256", essaisParSeconde: 1e10 },
  { nom: "hors ligne, base en bcrypt (coût 12)", essaisParSeconde: 2e4 },
  { nom: "en ligne, 10 essais par minute", essaisParSeconde: 10 / 60 },
];

const CANDIDATS = [
  { mdp: "Passw0rd!",        alphabet: 95, longueur: 9 },
  { mdp: "chat",             alphabet: 26, longueur: 4 },
  { mdp: "correcte-agrafe-batterie-crampon", alphabet: 0, longueur: 0 }, // à traiter
  { mdp: "aX7#kL2@qR9",      alphabet: 95, longueur: 11 },
];

// ── À VOUS ────────────────────────────────────────────────────────────────
// 1. entropie() : le nombre de bits d'un mot de passe tiré au hasard dans un
//    alphabet de taille A et de longueur L. (Indice : log2 de A puissance L.)
// 2. delai() : le temps MOYEN pour le trouver par force brute — on tombe
//    dessus à la moitié de l'espace en moyenne.
// 3. La phrase de passe est tirée au hasard dans un dictionnaire de 7776
//    mots (4 mots). Quel alphabet, quelle longueur ?

function entropie(alphabet, longueur) {
  return 0; // à compléter
}

function delai(bits, essaisParSeconde) {
  return 0; // secondes ; à compléter
}

// ── Affichage ─────────────────────────────────────────────────────────────
function lisible(secondes) {
  const u = [["s", 60], ["min", 60], ["h", 24], ["j", 365], ["ans", 1e9]];
  let v = secondes, i = 0;
  while (i < u.length - 1 && v >= u[i][1]) { v /= u[i][1]; i++; }
  return v.toExponential(1) + " " + u[i][0];
}

for (const c of CANDIDATS) {
  const bits = entropie(c.alphabet, c.longueur);
  console.log("\n" + c.mdp + "  (" + bits.toFixed(0) + " bits)");
  for (const s of SCENARIOS) {
    console.log("   " + s.nom.padEnd(38) + lisible(delai(bits, s.essaisParSeconde)));
  }
}

Solution

function entropie(alphabet, longueur) {
  return longueur * Math.log2(alphabet);
}

function delai(bits, essaisParSeconde) {
  return Math.pow(2, bits - 1) / essaisParSeconde;   // moitié de l'espace
}

// La phrase de passe : 4 mots tirés dans une liste de 7776.
// alphabet = 7776, longueur = 4  →  4 × log2(7776) ≈ 51,7 bits.

// ── Ce que le tableau montre ──────────────────────────────────────────────
//
// 1. « Passw0rd! » vaut 59 bits SI on suppose qu'il a été tiré au hasard
//    parmi les 95 caractères imprimables. Il ne l'a pas été : c'est un mot
//    du dictionnaire avec les substitutions attendues, et il figure dans
//    toutes les listes d'attaque. Sa vraie entropie est proche de 10 bits.
//    L'entropie mesure le TIRAGE, pas la chaîne — c'est l'erreur de lecture
//    la plus commune du domaine.
//
// 2. La phrase de passe (51,7 bits) bat « aX7#kL2@qR9 » ? Non : 72 bits
//    contre 51,7. Mais elle bat très largement tout ce qu'un humain retient
//    ET saisit sans erreur, et c'est le bon critère. La longueur rapporte
//    linéairement en bits ; la complexité de l'alphabet, logarithmiquement.
//    Ajouter un mot vaut mieux qu'ajouter un symbole.
//
// 3. Le scénario décide de tout. Le même « chat » de 19 bits tombe en
//    microsecondes hors ligne et tient plusieurs heures face à une limitation
//    à 10 essais par minute. C'est pourquoi la limitation de débit et le
//    verrouillage progressif comptent autant que la politique de mot de
//    passe : ils changent le scénario, pas le secret.
//
// 4. Et c'est pourquoi le stockage est le vrai levier du défenseur. Passer
//    de SHA-256 à bcrypt coût 12 multiplie le délai par 500 000 sur TOUS les
//    mots de passe de la base à la fois — bien plus que ce qu'on obtiendra
//    jamais en imposant un caractère spécial de plus aux utilisateurs.
//
// La politique qui suit de ces quatre points est celle du NIST SP 800-63B :
// minimum 12 caractères, aucune règle de composition imposée, aucune
// expiration périodique, comparaison à une liste de mots de passe déjà
// compromis, et limitation du débit. Le reste — les majuscules obligatoires,
// le changement tous les 90 jours — produit « Printemps2026! » et rien
// d'autre.

Ce que la suite en fait

Ce chapitre a traité le contrôle d'accès comme une abstraction : sujets, objets, permissions. Le chapitre 4 le regarde là où il s'implémente réellement — les permissions Unix et les jetons d'accès Windows — et surtout là où il se contourne : l'escalade de privilèges, qui est la matérialisation exacte de la phase 4 de la chaîne d'attaque.

Le chapitre 7 reprendra les sessions et les jetons côté attaquant : vol de cookie par XSS, CSRF, JWT mal vérifiés, contrôle d'accès défaillant. Vous y verrez que la première faille de l'OWASP Top 10 n'est pas une faiblesse d'authentification mais d'autorisation — précisément la distinction posée au début de ce chapitre.

À retenir

Flashcards · 4 cartes

Pourquoi une clé FIDO2 résiste-t-elle au hameçonnage alors qu'un code TOTP n'y résiste pas ?
Parce que la clé LIE cryptographiquement sa réponse au domaine d'origine qui la demande : sur un faux domaine, elle produit une signature inutilisable ailleurs. Un code TOTP est un secret transmissible — la victime le recopie sur le faux site, l'attaquant le relaie en quelques secondes sur le vrai. C'est la seule technologie du chapitre qui supprime une classe d'attaques au lieu de la renchérir.
Qu'est-ce que la fixation de session, et quelle règle unique l'empêche ?
L'attaquant impose d'avance une valeur d'identifiant de session au navigateur de la victime, attend qu'elle s'authentifie, puis réutilise ce même identifiant désormais authentifié. La règle : RÉGÉNÉRER l'identifiant de session à la connexion et à tout changement de privilège. Un identifiant qui survit à l'authentification est un identifiant que l'attaquant a pu choisir.
Quelle est la maladie chronique du RBAC, et quel est son remède ?
La dérive de privilèges : au fil des changements de poste, les rôles s'accumulent sans que personne ne retire les anciens, et l'utilisateur finit avec des droits que nul n'a jamais décidé de lui accorder. Le remède n'est pas technique mais organisationnel — une revue périodique des habilitations, avec retrait par défaut de ce qui n'est plus justifié.
Pourquoi les règles de composition et l'expiration périodique des mots de passe ont-elles été abandonnées par le NIST et l'ANSSI ?
Parce qu'elles dégradent mesurablement la sécurité : elles produisent des motifs prévisibles — « Printemps2026! » puis « Ete2026! » — présents dans toutes les listes d'attaque. Les recommandations actuelles demandent de la LONGUEUR (12 caractères minimum), l'absence dans les bases de mots de passe compromis, une limitation du débit, et du MFA. On n'impose plus de composition et on ne fait plus expirer sans motif.

Chapitre 2 · 7 h

Sécurité des systèmes d'exploitation

Permissions et escalade de privilèges sous Linux et Windows, durcissement, journalisation et audit, isolation par conteneurs, familles de maliciels, analyse statique et dynamique de base.

Un attaquant qui entre dans un système y entre presque toujours sans privilège : un compte de service, une session web, un utilisateur ordinaire hameçonné. Ce n'est pas encore un incident grave. Ce qui transforme un pied dans la porte en compromission complète, c'est l'escalade de privilèges — la phase 4 de la chaîne d'attaque, et le cœur de ce chapitre.

Le système d'exploitation est la couche où le contrôle d'accès abstrait du chapitre 3 devient concret : des bits de permission, des jetons, des appels système. C'est aussi la couche où il se contourne. On regarde d'abord comment il tient, puis par où il cède, sous Linux et sous Windows, avant de traiter le durcissement, l'isolation et les maliciels.

Linux : le modèle, et ses angles morts

Le modèle historique est discrétionnaire (DAC, chapitre 3) : chaque fichier a un propriétaire, un groupe, et trois triplets de permissions rwx — propriétaire, groupe, autres. root (UID 0) ignore ces permissions. Tout est fichier, y compris les périphériques et une grande partie de l'état du noyau, ce qui fait des permissions un mécanisme d'une portée bien plus large qu'il n'y paraît.

La subtilité qui compte pour la sécurité est le bit SUID. Un binaire SUID s'exécute avec les droits de son propriétaire, pas de celui qui le lance. passwd en a besoin : un utilisateur normal doit pouvoir modifier /etc/shadow, que lui seul ne peut pas écrire. Mais tout binaire SUID root est une frontière de privilège : si son code fait la moindre confiance à une entrée que l'appelant contrôle — un argument, une variable d'environnement, le PATH, le répertoire courant —, cette confiance devient une escalade. find / -perm -4000 2>/dev/null liste ces binaires ; c'est la première commande d'un attaquant après une intrusion, et elle devrait être la vôtre en audit.

Les mécanismes qui réduisent la portée de root, dans l'ordre où on les rencontre :

  • Les capabilities POSIX découpent les pouvoirs de root en une quarantaine de morceaux. Un binaire qui doit seulement ouvrir un port bas reçoit CAP_NET_BIND_SERVICE, et non le bit SUID root entier. C'est le moindre privilège appliqué au noyau.
  • sudo journalise et restreint : qui peut exécuter quoi, en tant que qui. Sa mauvaise configuration — une entrée trop large, un éditeur autorisé qui sait lancer un shell — est une source d'escalade à part entière.
  • Le MAC (SELinux, AppArmor, chapitre 3) confine chaque programme à un profil : même compromis, même lancé par root, un processus ne fait que ce que sa politique autorise. C'est ce qui distingue une compromission d'application d'une compromission de machine.

Windows : un autre vocabulaire, les mêmes questions

Windows ne raisonne pas en rwx mais en jetons d'accès et listes de contrôle d'accès (ACL), plus riches et plus fines. Chaque processus porte un jeton qui énumère l'utilisateur, ses groupes et ses privilèges ; chaque objet — fichier, clé de registre, service — porte une ACL qui dit qui peut quoi.

Les points saillants pour la sécurité :

  • Le contrôle de compte d'utilisateur (UAC) fait tourner l'administrateur lui-même avec un jeton restreint par défaut ; l'élévation est explicite. Ce n'est pas une frontière de sécurité au sens strict — Microsoft le dit — mais un garde-fou.
  • Les services tournent souvent avec des comptes très privilégiés (SYSTEM). Un service dont le binaire est modifiable par un utilisateur, ou dont le chemin non entre-guillemets contient un espace, est une escalade directe vers SYSTEM — l'équivalent Windows du SUID mal écrit.
  • L'Active Directory est la véritable cible : compromettre un poste importe peu, compromettre le contrôleur de domaine donne toute l'organisation. Les attaques par pass-the-hash et Kerberoasting visent cette bascule, et c'est pourquoi le déplacement latéral (chapitre 5) s'y concentre.

L'essentiel à retenir n'est pas la syntaxe mais la symétrie : sous les deux systèmes, la même question se pose — quel processus, avec quels droits, fait confiance à quelle entrée — et l'escalade est toujours l'exploitation d'une confiance mal placée à une frontière de privilège.

Le durcissement

Durcir un système, c'est réduire sa surface d'attaque (chapitre 1) avant qu'un attaquant ne s'en occupe. Les mesures, par ordre d'efficacité :

  1. Supprimer ce qui est inutile : services, paquets, comptes par défaut, comptes de test. Ce qui n'existe pas ne se compromet pas, et cette mesure ne se dégrade pas dans le temps.
  2. Corriger : la gestion des correctifs est, statistiquement, la mesure qui évite le plus d'incidents réels. La majorité des compromissions exploitent une vulnérabilité pour laquelle un correctif existait — parfois depuis des années.
  3. Configurer selon un référentiel : les guides CIS, les recommandations ANSSI donnent des bases mesurables plutôt que des intuitions.
  4. Restreindre les comptes : pas de connexion directe en root, MFA sur les accès distants, moindre privilège partout.
  5. Chiffrer au repos : LUKS, BitLocker. Protège contre le vol physique, pas contre un système compromis en fonctionnement — la distinction est importante et souvent oubliée.

Journalisation et audit

On ne peut pas répondre à ce qu'on n'a pas enregistré. La journalisation est le socle du chapitre 9, et se prépare avant l'incident, jamais pendant.

Les sources qui comptent : authentifications (réussies et échouées), élévations de privilège, création de comptes et de services, exécution de processus, accès aux fichiers sensibles. Sous Linux, auditd et journald ; sous Windows, le journal d'événements et Sysmon, dont la finesse en fait un standard de fait en détection.

Deux principes non négociables, parce qu'un attaquant compétent les cible en premier :

  • Centraliser. Un journal qui reste sur la machine compromise sera effacé — l'effacement des traces est une étape standard de l'intrusion. Il faut l'expédier ailleurs, en temps réel, vers un collecteur que l'attaquant n'atteint pas. C'est le rôle du SIEM, chapitre 6.
  • Horodater et protéger en intégrité. Un journal modifiable ne prouve rien, ni en analyse ni devant un tribunal (chaîne de conservation, chapitre 9).

L'isolation par conteneurs

Un conteneur isole un processus — système de fichiers, réseau, arborescence de processus — en partageant le noyau de l'hôte. C'est ce partage qui fait toute la différence de posture de sécurité avec une machine virtuelle, laquelle embarque son propre noyau derrière un hyperviseur.

ConteneurMachine virtuelle
Isolationprocessus, noyau partagénoyau séparé, hyperviseur
Surface d'évasiontout le noyau de l'hôtel'hyperviseur, bien plus mince
Coûtléger, démarrage en secondeslourd, démarrage en dizaines de secondes

La conséquence de sécurité est directe : un conteneur n'est pas une frontière de sécurité aussi forte qu'une VM. Une vulnérabilité du noyau, ou un conteneur mal configuré, permet une évasion vers l'hôte. Les erreurs les plus fréquentes, à connaître :

  • lancer le conteneur en --privileged, ou monter le socket Docker à l'intérieur : c'est donner root sur l'hôte, directement ;
  • tourner en root dans le conteneur — devenu la valeur par défaut à éviter ;
  • monter des répertoires sensibles de l'hôte ;
  • partir d'une image obèse et non vérifiée, dont on ne connaît pas le contenu (chaîne d'approvisionnement, chapitre 8).

Bien configuré — utilisateur non-root, capabilities minimales, seccomp, système de fichiers en lecture seule —, le conteneur reste un excellent outil de cloisonnement, dans l'esprit de la défense en profondeur. Il ne remplace pas la VM quand la frontière doit être forte, par exemple entre deux clients d'une même infrastructure.

Quiz · 1 question

Une équipe isole les applications de plusieurs clients sur un même serveur, chaque application dans un conteneur lancé avec --privileged pour « éviter les problèmes de permissions ». Quel est le risque ?

  • Aucun risque majeur : les conteneurs isolent les processus les uns des autresisolation des processus
  • Un conteneur privilégié partage le noyau et dispose de droits quasi complets sur l'hôte : sa compromission donne l'hôte, donc tous les autres clientsnoyau partagé et privilèges
  • Le seul risque est une consommation excessive de ressources par un conteneurressources

Réponse : Un conteneur partage déjà le noyau de l'hôte ; le drapeau --privileged retire en plus l'essentiel des barrières restantes — capabilities complètes, accès aux périphériques. La compromission d'un seul conteneur donne alors l'hôte, et donc tous les autres clients hébergés dessus : l'isolation recherchée est annulée. Pour une frontière forte entre clients, la machine virtuelle, avec son noyau séparé, est le bon outil ; à défaut, un conteneur non privilégié, non-root, à capabilities minimales.

Les maliciels

Un maliciel est un programme dont la fonction est hostile. Le vocabulaire décrit surtout le mode de propagation, ce qui aide à raisonner sur la défense :

FamilleCe qui la définit
Viruss'attache à un fichier hôte, se propage à son exécution
Verse propage seul sur le réseau, sans action de l'utilisateur — le ver Morris
Cheval de Troiese fait passer pour légitime ; l'utilisateur l'installe lui-même
Rançongicielchiffre les données et exige une rançon — la menace dominante actuelle
Porte dérobéeménage un accès persistant et discret
Enregistreur de frappe, espiogicielcapte et exfiltre de l'information
Rootkitse dissimule au niveau système, voire noyau

Deux points structurent la défense. D'abord, la propagation est souvent hybride : un rançongiciel moderne combine un cheval de Troie pour l'entrée, un ver pour le déplacement latéral, et une charge de chiffrement — il occupe donc plusieurs cases de la chaîne d'attaque à la fois. Ensuite, la défense a basculé : l'antivirus par signatures ne détecte que le connu, et un maliciel polymorphe change de signature à chaque copie. La détection moderne (EDR/XDR) observe le comportement — un processus Office qui lance PowerShell, un chiffrement massif de fichiers en quelques minutes — parce que le comportement, lui, est plus coûteux à maquiller que l'apparence.

Analyse de maliciel : statique et dynamique

Face à un binaire suspect, deux approches complémentaires. Elles se pratiquent dans un environnement isolé et jetable — c'est l'application directe de la charte du chapitre 1 : on n'exécute jamais un maliciel sur une machine qui compte.

L'analyse statique examine sans exécuter : type de fichier, chaînes de caractères, domaines et adresses en dur, ressources embarquées, imports d'API, puis désassemblage. Sûre, mais mise en échec par l'empaquetage et l'obscurcissement — le code réel n'apparaît qu'à l'exécution.

L'analyse dynamique exécute dans un bac à sable instrumenté et observe : fichiers créés, clés de registre modifiées, processus engendrés, connexions réseau. Elle révèle le comportement réel, mais le maliciel peut détecter le bac à sable — présence d'outils d'analyse, absence d'activité humaine, machine trop récente — et rester inerte pour tromper l'analyste.

Aucune des deux ne suffit seule, et c'est leur combinaison qui donne les indicateurs de compromission — empreintes, domaines, clés — que le chapitre 9 exploitera pour rechercher la même menace ailleurs dans le système d'information.

À vous

L'escalade de privilèges se comprend en la montant. L'exercice reprend le SUID mal écrit décrit plus haut : un binaire SUID root qui appelle tar sans chemin absolu. Vous êtes un utilisateur ordinaire ; obtenez une exécution en root en détournant le PATH, puis écrivez les trois corrections par ordre d'importance.

Rien n'est « cassé » ici, au sens de la mémoire : vous exploitez une confiance mal placée à une frontière de privilège, ce qui est la forme générale de toute escalade.

Exercice de code

Un binaire SUID root appelle tar sans chemin absolu. En tant qu'utilisateur normal, obtenez une exécution en root en détournant le PATH. Écrivez ensuite les trois corrections, par ordre d'importance.

Point de départ

// Un binaire installé SUID root sauvegarde /etc/backup. Son code C, simplifié :
//
//   int main(void) {
//       setuid(0);
//       system("tar czf /root/backup.tgz /etc/backup");   // <-- le défaut
//       return 0;
//   }
//
// SUID root signifie qu'il s'exécute avec les droits du PROPRIÉTAIRE (root),
// quel que soit l'utilisateur qui le lance. On simule ici son exécution.

// L'environnement, contrôlé par l'utilisateur qui lance le binaire.
let PATH = "/usr/local/bin:/usr/bin:/bin";

// Le "système" : cherche la commande dans le PATH, de gauche à droite.
function resoudre(commande) {
  for (const rep of PATH.split(":")) {
    if (FICHIERS[rep + "/" + commande]) return rep + "/" + commande;
  }
  return null;
}

const FICHIERS = {
  "/bin/tar":        { proprietaire: "root", contenu: "le vrai tar" },
  "/usr/bin/tar":    { proprietaire: "root", contenu: "le vrai tar" },
};

// system("tar ...") ne donne PAS de chemin absolu : il résout via le PATH.
function executerSUID() {
  const chemin = resoudre("tar");        // <-- ici tout se joue
  const prog = FICHIERS[chemin];
  console.log("root exécute : " + chemin + "  (" + prog.contenu + ")");
  if (prog.contenu.includes("id -u")) {
    console.log(">>> SHELL ROOT OBTENU <<<");
  }
}

// ── ATTAQUE — à vous ──────────────────────────────────────────────────────
// Vous êtes un utilisateur normal. Vous ne pouvez pas écrire dans /bin ni
// /usr/bin, mais vous contrôlez votre PATH et votre répertoire personnel.
// Placez un faux "tar" que le binaire SUID exécutera EN ROOT.

// (1) créez un faux tar dans un répertoire où vous, vous pouvez écrire :
// FICHIERS["/home/etudiant/tar"] = { proprietaire: "etudiant", contenu: "..." };
// (2) modifiez PATH pour qu'il soit trouvé en premier :
// PATH = "...";

executerSUID();

Solution

// ── ATTAQUE ───────────────────────────────────────────────────────────────
// (1) Un faux "tar" qui, au lieu d'archiver, ouvre un shell — ici on marque
//     simplement l'exécution par "id -u".
FICHIERS["/home/etudiant/tar"] = { proprietaire: "etudiant", contenu: "#!/bin/sh -- id -u; /bin/sh" };
// (2) On met notre répertoire EN TÊTE du PATH.
PATH = "/home/etudiant:/usr/local/bin:/usr/bin:/bin";

executerSUID();
// root exécute /home/etudiant/tar : le programme de l'attaquant tourne avec
// les droits de root. C'est l'escalade, et elle n'a rien cassé — elle a
// simplement exploité une décision de conception : « chercher tar dans le
// PATH » signifie « laisser l'utilisateur choisir quel tar ».

// ── LA CORRECTION ─────────────────────────────────────────────────────────
// Trois défauts, trois corrections, par ordre d'importance :
//
// 1. NE PAS appeler system(). Elle passe par /bin/sh, qui lit l'environnement
//    (PATH, IFS, ...). Utiliser execve() avec un chemin ABSOLU et un
//    environnement nettoyé :
//        char *argv[] = {"/bin/tar","czf","/root/backup.tgz","/etc/backup",0};
//        char *envp[] = {0};
//        execve("/bin/tar", argv, envp);
//
// 2. NE PAS être SUID root si ce n'est pas indispensable. Ce binaire n'a
//    besoin que d'écrire dans /root/ : une capability POSIX ciblée, ou un
//    compte de service dédié, vaut mieux que tous les droits de root.
//    C'est le moindre privilège du chapitre 3, appliqué au bit SUID.
//
// 3. Abaisser les privilèges dès que possible, et vérifier que setuid() a
//    réussi (sa valeur de retour est ignorée dans le code d'origine).
//
// La leçon générale : un programme privilégié ne doit faire CONFIANCE à aucune
// entrée contrôlée par l'appelant — et le PATH, l'environnement, le
// répertoire courant en font partie autant que les arguments. C'est le même
// principe que la validation d'entrée du chapitre 7, un cran plus bas dans
// la pile.

Ce que la suite en fait

Ce chapitre a traité la sécurité d'une machine prise isolément. Mais un attaquant qui a compromis un poste ne s'y arrête pas : il se déplace vers les autres, et c'est le réseau qui le porte. Le chapitre 5 relit donc TCP/IP du point de vue de l'attaquant — reconnaissance, usurpation, interception — et le chapitre 6 construit la défense qui cloisonne ces déplacements.

La journalisation posée ici est le socle du chapitre 9 : sans les sources d'événements décrites plus haut, la réponse à incident n'a rien à analyser. Gardez aussi le moindre privilège en tête — c'est lui qui décidera de l'ampleur de tout ce que les chapitres suivants exploiteront.

À retenir

Flashcards · 4 cartes

Pourquoi un binaire SUID root qui appelle une commande sans chemin absolu est-il dangereux ?
Parce qu'il s'exécute avec les droits de root mais résout la commande via le PATH, que l'appelant contrôle. Un utilisateur place un faux binaire en tête de son PATH et le fait exécuter EN ROOT — sans casser quoi que ce soit. C'est la forme générale de l'escalade : une confiance mal placée à une frontière de privilège. Correctif : chemin absolu, environnement nettoyé, execve() plutôt que system(), et pas de SUID root si une capability ciblée suffit.
Pourquoi un conteneur n'est-il pas une frontière de sécurité aussi forte qu'une machine virtuelle ?
Parce qu'il partage le NOYAU de l'hôte, alors qu'une VM embarque le sien derrière un hyperviseur. Une vulnérabilité du noyau, ou une mauvaise configuration (--privileged, socket Docker monté, root dans le conteneur), permet une ÉVASION vers l'hôte. Pour une frontière forte — entre clients par exemple — on emploie une VM ; le conteneur reste un bon outil de cloisonnement s'il est non-root et à capabilities minimales.
Pourquoi la détection de maliciels a-t-elle basculé des signatures vers le comportement ?
Parce qu'une signature ne détecte que le connu, et qu'un maliciel polymorphe change de signature à chaque copie. Le comportement — un processus Office qui lance PowerShell, un chiffrement massif en quelques minutes — est bien plus coûteux à maquiller que l'apparence. C'est le principe des EDR/XDR modernes.
Pourquoi faut-il centraliser les journaux, et non les laisser sur la machine qui les produit ?
Parce que l'effacement des traces est une étape standard de l'intrusion : un journal resté sur la machine compromise sera modifié ou supprimé par l'attaquant. Il faut l'expédier en temps réel vers un collecteur qu'il n'atteint pas (le SIEM du chapitre 6), horodaté et protégé en intégrité — sans quoi il ne prouve rien, ni en analyse ni devant un tribunal.