Aller au contenu principal
own2pwn
appsec/threat-modeling.tsx

Threat modeling : anticiper les attaques avant d'écrire une ligne de code

Le threat modeling, ou modélisation des menaces, consiste à débusquer les attaques dès la conception. Méthodes STRIDE, DREAD, PASTA, attack trees, et la pratique concrète.

own2pwn··12 min de lecture

Revue d'architecture, un mardi matin. Le lead dev déroule ses slides : un nouveau service de paiement, une file de messages, un bucket S3 pour les justificatifs, un webhook qui notifie le back-office. Tout le monde hoche la tête, on parle scalabilité, coût, latence. Et puis quelqu'un au fond de la salle, un architecte sécu ou un RSSI qui traînait là, pose la question qui gèle le tableau blanc : « et si un attaquant rejouait le webhook ? Qui vérifie que le montant vient bien de Stripe et pas d'un curl depuis internet ? » Silence. Personne n'y avait pensé. Cette question, arrivée trop tard dans beaucoup d'équipes et jamais dans d'autres, c'est tout l'objet du threat modeling.

La modélisation des menaces ne cherche pas à trouver des bugs dans du code existant. Elle se pose bien plus tôt, sur le papier, quand le système n'est encore qu'un diagramme : elle consiste à imaginer méthodiquement comment un adversaire s'y prendrait pour casser ce que vous êtes en train de dessiner, et à décider quoi faire avant que le premier commit ne fige les mauvaises décisions. C'est l'activité la moins chère de toute la chaîne AppSec, parce qu'à ce stade corriger une faille coûte le prix d'une phrase dans un document, pas d'un sprint de refonte.

À qui s'adresse cet article
Aux architectes, lead devs et RSSI qui veulent intégrer la sécurité au moment de la conception, pas en rustine après le pentest. On part du principe que vous savez lire un diagramme d'architecture ; on ne suppose aucune connaissance préalable des méthodes formelles.

Ce que le threat modeling est vraiment

On confond souvent la modélisation des menaces avec un scan, un audit ou une analyse de risques. Ce n'est aucun des trois. Un scan cherche des failles connues dans un système qui tourne. Un audit vérifie une conformité à une norme. Le threat modeling, lui, est un exercice de conception : on raisonne sur ce qui pourrait mal tourner, structurellement, dans une architecture donnée, en se mettant dans la tête de l'attaquant.

Adam Shostack, l'auteur de référence sur le sujet (il a longtemps porté la pratique chez Microsoft), a ramené tout ça à quatre questions d'une simplicité désarmante. Elles tiennent l'exercice de bout en bout, et si vous ne devez retenir qu'une chose de cet article, retenez ces quatre-là :

quatre-questions
Question 1
Sur quoi on travaille ?
On dessine le système : composants, flux de données, dépendances. Sans ce modèle partagé, chacun sécurise un système différent dans sa tête.
Question 2
Qu'est-ce qui peut mal tourner ?
Le cœur offensif : on énumère les menaces, poste par poste. C'est là que STRIDE et consorts entrent en jeu.
Question 3
Qu'est-ce qu'on fait ?
On décide : mitiger, transférer, accepter ou éliminer. Chaque menace repart avec une contre-mesure ou une décision assumée.
Question 4
A-t-on bien fait ?
On revient vérifier : le modèle est-il complet, les mitigations tiennent-elles, le système a-t-il changé depuis ? On reboucle.
Les quatre questions de Shostack : un cycle, pas une checklist qu'on remplit une fois.

La quatrième question est celle qu'on saute le plus souvent, et c'est une erreur. Un threat model n'est pas un livrable qu'on classe et qu'on oublie : c'est un artefact vivant qui doit suivre l'architecture. Le jour où vous ajoutez un cache Redis exposé ou une nouvelle intégration tierce, la deuxième question se repose. On y revient plus bas, parce que cette boucle change tout à la manière dont on intègre la pratique dans une équipe.

STRIDE, la méthode qui structure le « qu'est-ce qui peut mal tourner »

Demander à une salle « qu'est-ce qui peut mal tourner ? » sans cadre, c'est le meilleur moyen d'obtenir trois idées évidentes et un long silence. STRIDE existe justement pour transformer cette page blanche en énumération systématique. C'est un acronyme, inventé chez Microsoft, qui liste six catégories de menaces. Pour chaque élément de votre diagramme, vous passez les six en revue : la plupart ne s'appliqueront pas, mais le simple fait de les avoir considérées évite l'angle mort.

stride.txt
  LETTRE  MENACE                    VIOLE            CONTRE-MESURE TYPE
  ------  ------------------------  ---------------  -----------------------
   S      Spoofing                  Authenticité     Authentification forte
          (usurpation d'identité)                    (MFA, mTLS, signatures)

   T      Tampering                 Integrite        Signatures, hash, WORM,
          (altération de données)                    controle d'acces ecriture

   R      Repudiation               Non-repudiation  Logs signes, horodatage,
          (deni d'une action)                        piste d'audit inviolable

   I      Information disclosure    Confidentialite  Chiffrement, cloisonnement,
          (fuite de donnees)                         principe du moindre acces

   D      Denial of service         Disponibilite    Rate limiting, quotas,
          (deni de service)                          autoscaling, timeouts

   E      Elevation of privilege    Autorisation     Moindre privilege, RBAC,
          (elevation de privilege)                   validation cote serveur
Chaque menace STRIDE viole une propriété de sécurité précise, et appelle une famille de contre-mesures.

La force de STRIDE, c'est qu'il mappe chaque menace sur une propriété de sécurité connue. Vous ne cherchez plus « des attaques » dans l'abstrait, vous vous demandez, pour ce webhook du début : son origine est-elle vraiment authentifiée (S) ? Peut-on modifier le montant en transit (T) ? Garde-t-on une trace signée de qui a déclenché quoi (R) ? Prises une par une, ces questions sont faciles. C'est leur exhaustivité qui fait le travail.

Détaillons les six, parce que le diable est dans l'exemple concret :

Spoofing : se faire passer pour un autre

L'attaquant prétend être une entité qu'il n'est pas : un utilisateur, un service interne, un serveur de confiance. Le webhook non vérifié de notre revue d'archi en est l'exemple parfait. On y répond par de l'authentification qui ne se contente pas d'un mot de passe : signatures HMAC sur les webhooks, TLS mutuel entre services, jetons à courte durée de vie. La question à se poser devant chaque flèche du diagramme : « comment le destinataire sait-il que l'émetteur est bien qui il prétend être ? »

Tampering : modifier ce qui devrait être immuable

Altération d'une donnée en transit ou au repos : un montant changé dans une requête, un fichier de config réécrit, un message de file empoisonné. Les contre-mesures tournent autour de l'intégrité : signatures, empreintes de hachage vérifiées, contrôle d'accès strict en écriture, stockage en écriture unique pour les données sensibles. C'est ici que l'on attrape une bonne partie des IDOR et des manipulations de paramètres, cousines directes du Broken Access Control qui trône en tête de l'OWASP Top 10.

Repudiation : nier une action qu'on a commise

Un utilisateur (ou un attaquant) effectue une opération, puis affirme ne l'avoir jamais faite, et vous n'avez aucun moyen de prouver le contraire. Sur un système de paiement ou un back-office administratif, cette menace est loin d'être théorique. La parade : des journaux d'audit horodatés, signés, stockés hors de portée de celui qui pourrait vouloir les effacer. Beaucoup d'équipes découvrent l'absence de ces logs le jour où elles en ont désespérément besoin, en plein incident.

Information disclosure : la fuite de données

La divulgation d'informations qui devraient rester confidentielles : un bucket S3 mal configuré, un message d'erreur trop bavard, une API qui renvoie plus de champs que l'écran n'en affiche. Le justificatif stocké dans le S3 de notre exemple mérite ici une vraie attention : qui peut le lire, l'URL est-elle devinable, y a-t-il chiffrement au repos ? On répond par le chiffrement, le cloisonnement réseau et le principe du moindre accès.

Denial of service : rendre le système indisponible

L'attaquant sature une ressource pour empêcher les utilisateurs légitimes d'y accéder : une file de messages qu'on inonde, un endpoint coûteux qu'on martèle, une expression régulière qu'on fait exploser. On s'en protège avec du rate limiting, des quotas, des timeouts agressifs et une capacité à absorber la charge. Cette catégorie est souvent la moins prise au sérieux en conception, alors qu'elle est triviale à déclencher.

Elevation of privilege : franchir une frontière d'autorisation

Un utilisateur standard qui obtient des droits d'admin, un service qui accède à des données hors de son périmètre. C'est souvent la menace la plus grave, parce qu'elle transforme une petite brèche en compromission totale. La défense repose sur le moindre privilège, un contrôle d'accès basé sur les rôles, et surtout une validation d'autorisation systématiquement côté serveur, jamais déléguée au client.

Le tableau STRIDE-par-élément, en pratique
La manière la plus productive d'appliquer STRIDE : dresser une matrice. En lignes, chaque élément du diagramme (processus, flux, magasin de données) ; en colonnes, les six lettres. On coche les cases pertinentes, on ignore les autres sans culpabiliser. Un processus subit surtout du S, T, R, E ; un flux de données du T et du I ; un magasin du T, I, R. Cette grille évite la page blanche et rend l'exercice traçable.

Les autres méthodes : DREAD, PASTA, attack trees

STRIDE répond à « quelles menaces ? ». D'autres cadres répondent à des questions voisines, et il est utile de savoir lequel dégainer.

DREAD ne cherche pas les menaces, il les note. Une fois vos menaces STRIDE listées, DREAD sert à les prioriser sur cinq axes : Damage (impact), Reproducibility (facilité à reproduire), Exploitability (facilité d'exploitation), Affected users (population touchée), Discoverability (facilité à découvrir). On attribue une note à chacun, on additionne, on trie. Attention : DREAD est notoirement subjectif, deux évaluateurs donnent des scores différents, et Microsoft l'a d'ailleurs abandonné en interne. Utilisez-le comme un support de discussion pour ordonner des risques, pas comme une mesure scientifique.

PASTA (Process for Attack Simulation and Threat Analysis) joue dans une autre cour. C'est une méthode en sept étapes, lourde, centrée sur le risque métier, qui part des objectifs business pour remonter jusqu'aux contre-mesures techniques. On la sort pour un système critique où la sécurité doit être justifiée devant la direction, pas pour cadrer un microservice un mardi matin. Elle demande du temps et de la coordination entre équipes.

Les attack trees (arbres d'attaque), enfin, prennent le problème par l'objectif de l'attaquant. On place le but à la racine (« voler les justificatifs »), puis on décompose en sous-objectifs et en moyens concrets, branche après branche. C'est visuel, très parlant pour raisonner sur un scénario précis, et complémentaire de STRIDE : STRIDE balaie large et systématiquement, l'arbre creuse en profondeur un chemin d'attaque donné.

attack-tree.txt
  OBJECTIF : lire les justificatifs stockes dans le bucket
  |
  +-- Acceder directement au bucket S3
  |   +-- Bucket public mal configure ......... (I : mauvaise ACL)
  |   +-- Cle d'acces fuitee dans le code ..... (I : secret en clair)
  |
  +-- Passer par l'application
  |   +-- IDOR sur l'URL du justificatif ...... (T + E : pas de controle)
  |   +-- Elevation vers un compte admin ...... (E : RBAC absent)
  |
  +-- Intercepter en transit
      +-- MITM sur un flux non chiffre ........ (I : pas de TLS interne)
Un arbre d'attaque : l'objectif de l'adversaire en racine, décomposé en moyens concrets.

Le bon réflexe n'est pas de choisir une méthode et de s'y tenir religieusement. C'est d'utiliser STRIDE comme colonne vertébrale pour l'énumération, un tri à la DREAD pour prioriser, et un arbre d'attaque quand un scénario mérite qu'on l'explore à fond. La méthode est un outil, pas une religion.

Comment on le mène concrètement : du diagramme aux mitigations

En pratique, une session de threat modeling suit toujours la même mécanique, quelle que soit la méthode. Elle commence par un dessin, elle se termine par une liste de décisions.

demarche
Socle
Le diagramme de flux de données
Un DFD : processus, magasins, entités externes, flux. Le langage commun sur lequel tout le reste s'appuie.
Couche
Les frontières de confiance
On trace où le niveau de confiance change. Chaque frontière franchie est un point d'inspection obligatoire.
Couche
L'énumération STRIDE
Pour chaque élément et chaque flux qui traverse une frontière, on passe les six menaces en revue.
Sommet
Les mitigations décidées
Chaque menace retenue repart avec une contre-mesure, ou une décision assumée de l'accepter.
La démarche empile quatre couches, du modèle partagé en bas aux décisions actées en haut.

1. Dessiner le diagramme de flux de données

Un DFD (data flow diagram) n'a rien de sophistiqué. Quatre types d'éléments suffisent : les processus (votre code, vos services), les magasins de données (bases, buckets, files), les entités externes (utilisateurs, API tierces) et les flux qui les relient. On dessine le système à un niveau d'abstraction où l'on peut raisonner, sans se noyer dans le détail d'implémentation. Un diagramme lisible sur un écran vaut mieux qu'un schéma UML de trente pages que personne ne relira.

2. Tracer les frontières de confiance

C'est l'étape qui distingue un vrai threat model d'un joli dessin. Une frontière de confiance (trust boundary) marque l'endroit où le niveau de confiance dans les données change : la limite entre internet et votre réseau, entre un service exposé et un service interne, entre le code client et le serveur. Toute donnée qui franchit une frontière doit être considérée comme hostile jusqu'à preuve du contraire, et donc validée, authentifiée, contrôlée. Reprenons l'architecture de notre revue :

dfd-frontieres
Entité externe
Prestataire de paiement
Émet un webhook signé vers votre système. Situé hors de votre périmètre de confiance.
Processus exposé
Handler du webhook
Point d'entrée public. Doit vérifier la signature HMAC (S) avant toute chose, puis valider le contenu (T).
Magasin
File de messages
Ne devrait accepter que des messages du handler validé. Franchir cette frontière sans contrôle rouvre le T et le D.
Processus sensible
Back-office
Agit sur les paiements. Une élévation de privilège ici (E) transforme la brèche en compromission métier.
Le webhook franchit la frontière internet vers back-office : c'est là que le contrôle manquait.

Sur ce schéma, chaque flèche qui traverse une frontière est un endroit où poser les six questions STRIDE. Le handler du webhook cumule du S (l'origine est-elle authentifiée ?), du T (le contenu peut-il être forgé ?) et du R (garde-t-on la trace ?). C'est mécanique, et c'est précisément ce qui manquait dans la revue du début : personne n'avait dessiné la frontière, donc personne n'avait vu qu'on la franchissait sans contrôle.

3. Dériver les mitigations

Pour chaque menace jugée pertinente, quatre réponses possibles, et une seule est de la lâcheté déguisée : mitiger (ajouter une contre-mesure), éliminer (supprimer la fonctionnalité ou le composant à risque), transférer (déléguer le risque, par exemple à un prestataire ou une assurance) ou accepter (assumer explicitement, avec une trace écrite de qui a pris la décision et pourquoi). Accepter un risque en connaissance de cause est une décision légitime. L'ignorer parce qu'on ne l'a jamais identifié ne l'est pas.

Outillez-vous, mais gardez le cerveau allumé
Des outils comme OWASP Threat Dragon ou le Microsoft Threat Modeling Tool aident à dessiner les DFD et à générer des menaces STRIDE automatiquement à partir du diagramme. Pratique pour démarrer et pour ne rien oublier de systématique. Mais aucun outil ne connaît votre logique métier : les menaces les plus dangereuses, les abus de workflow et les trous d'autorisation, restent le fruit d'une tête humaine qui comprend ce que le système est censé faire.

Quand le faire, et ses limites

Le meilleur moment pour modéliser les menaces, c'est la conception, avant que le code n'existe. Le deuxième meilleur moment, c'est maintenant. Un threat model sur un système déjà en production reste extrêmement utile, il révèle souvent des frontières de confiance qu'on avait oubliées. Mais la vraie valeur se capte tôt, quand changer une décision d'architecture ne coûte qu'une discussion. C'est la logique du shift-left, la même qui pousse à mettre du SAST et du DAST au plus tôt dans la CI/CD : plus une faille est détectée tard, plus elle coûte cher à corriger.

Concrètement, on déclenche une session à chaque nouvelle fonctionnalité qui touche des données sensibles, à chaque changement d'architecture qui déplace une frontière de confiance, à chaque intégration tierce. Et on reboucle régulièrement, parce qu'un système vit et que son modèle de menaces vit avec lui. La quatrième question de Shostack, « a-t-on bien fait ? », n'est pas rhétorique : elle impose de revenir.

Un modèle n'est pas une preuve
Voici la limite qu'il faut marteler. Le threat modeling raisonne sur ce que vous croyez savoir de votre système. Il ne teste rien. Un modèle peut être élégant, exhaustif, validé en réunion, et complètement faux si l'implémentation ne correspond pas au diagramme, ou si une hypothèse de départ est erronée. Le contrôle d'autorisation que le modèle suppose présent est peut-être absent en vrai. La signature de webhook que tout le monde croyait vérifiée ne l'est peut-être qu'en dev. Un threat model dessine où chercher ; seul le test réel confirme ce qui tient.

C'est pour ça que la modélisation des menaces et le pentest ne s'opposent pas, ils se complètent. Le threat model vous dit où concentrer l'effort offensif : les frontières critiques, les processus sensibles, les flux mal authentifiés. Le pentest, lui, va cogner dessus pour de vrai et vous dire si vos hypothèses tenaient. Un attaquant qui rejoue votre webhook ne se soucie pas de votre joli diagramme ; il essaie. Si vous vous demandez ce que représente cet effort de validation, on détaille le prix d'un test d'intrusion web et ce qui fait varier la facture.

Cette articulation entre analyse à froid et validation à chaud, on la retrouve d'ailleurs dans tout l'outillage AppSec moderne. C'est exactement la même tension qu'entre le SAST, le DAST et l'IAST : l'analyse statique voit tout le code mais hors contexte, l'analyse dynamique ne voit que ce qui est réellement exploitable. Le threat modeling est le cran encore plus en amont : il travaille avant même qu'il y ait du code à analyser. Empilés, ces regards se couvrent mutuellement les angles morts.

À retenir

  • Le threat modeling anticipe les attaques dès la conception, quand corriger une faille ne coûte qu'une phrase dans un document plutôt qu'un sprint de refonte.
  • Les quatre questions de Shostack tiennent l'exercice : sur quoi on travaille, ce qui peut mal tourner, ce qu'on fait, et a-t-on bien fait. La dernière impose de reboucler, c'est celle qu'on saute le plus.
  • STRIDE transforme la page blanche en énumération systématique : Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege. DREAD priorise, PASTA cadre le risque métier, les attack trees creusent un scénario.
  • En pratique : un diagramme de flux de données, des frontières de confiance tracées, STRIDE appliqué sur chaque flux qui les franchit, puis une mitigation décidée pour chaque menace retenue.
  • Un modèle n'est pas une preuve. Il dit où chercher ; seul le pentest confirme ce qui tient réellement en face d'un attaquant.

Vous concevez un système sensible et vous voulez que la question « et si un attaquant faisait X ? » arrive à la conception plutôt qu'après l'incident ? On aide à cadrer le threat model, à tracer les bonnes frontières, puis à valider le tout par du test réel. Parlez-en avec un humain via la page contact.

Articles liés