Motifs d'analyse STRIDE
Identification systématique des menaces à l'aide de la méthodologie STRIDE.
Quand utiliser cette compétence
- Initier de nouvelles sessions de modélisation des menaces
- Analyser l'architecture système existante
- Examiner les décisions de conception de sécurité
- Créer de la documentation sur les menaces
- Former les équipes à l'identification des menaces
- Préparation à la conformité et aux audits
Concepts fondamentaux
1. Catégories STRIDE
S - Spoofing → Menaces d'authentification
T - Tampering → Menaces d'intégrité
R - Repudiation → Menaces de non-répudiation
I - Information → Menaces de confidentialité
Disclosure
D - Denial of → Menaces de disponibilité
Service
E - Elevation of → Menaces d'autorisation
Privilege
2. Matrice d'analyse des menaces
| Catégorie | Question | Famille de contrôles |
|---|---|---|
| Spoofing | Un attaquant peut-il usurper l'identité d'autrui ? | Authentification |
| Tampering | Un attaquant peut-il modifier des données ? | Intégrité |
| Repudiation | Un attaquant peut-il nier ses actions ? | Journalisation/Audit |
| Info Disclosure | Un attaquant peut-il accéder à des données ? | Chiffrement |
| DoS | Un attaquant peut-il perturber la disponibilité ? | Limitation de débit |
| Elevation | Un attaquant peut-il obtenir des privilèges ? | Autorisation |
Modèles
Modèle 1 : Document de modèle de menace STRIDE
# Modèle de menace : [Nom du système]
## 1. Vue d'ensemble du système
### 1.1 Description
[Description brève du système et de son objectif]
### 1.2 Diagramme de flux de données
[Utilisateur] --> [Application web] --> [Passerelle API] --> [Services backend] | v [Base de données]
### 1.3 Limites de confiance
- **Limite externe** : Internet vers DMZ
- **Limite interne** : DMZ vers réseau interne
- **Limite de données** : Application vers base de données
## 2. Actifs
| Actif | Sensibilité | Description |
|-------|-------------|-------------|
| Identifiants utilisateur | Élevée | Jetons d'authentification, mots de passe |
| Données personnelles | Élevée | Informations d'identification personnelle, données financières |
| Données de session | Moyenne | Sessions utilisateur actives |
| Journaux d'application | Moyenne | Enregistrements d'activité système |
| Configuration | Élevée | Paramètres système, secrets |
## 3. Analyse STRIDE
### 3.1 Menaces de spoofing
| ID | Menace | Cible | Impact | Probabilité |
|----|--------|-------|--------|-------------|
| S1 | Détournement de session | Sessions utilisateur | Élevé | Moyen |
| S2 | Falsification de jeton | Jetons JWT | Élevé | Faible |
| S3 | Credential stuffing | Point de connexion | Élevé | Élevé |
**Atténuations :**
- [ ] Implémenter l'authentification multifacteur
- [ ] Utiliser une gestion sécurisée des sessions
- [ ] Implémenter des politiques de verrouillage de compte
### 3.2 Menaces de tampering
| ID | Menace | Cible | Impact | Probabilité |
|----|--------|-------|--------|-------------|
| T1 | Injection SQL | Requêtes de base de données | Critique | Moyen |
| T2 | Manipulation de paramètres | Requêtes API | Élevé | Élevé |
| T3 | Abus de téléchargement | Stockage de fichiers | Élevé | Moyen |
**Atténuations :**
- [ ] Validation des entrées sur tous les points de terminaison
- [ ] Requêtes paramétrées
- [ ] Validation du type de fichier
### 3.3 Menaces de repudiation
| ID | Menace | Cible | Impact | Probabilité |
|----|--------|-------|--------|-------------|
| R1 | Déni de transaction | Opérations financières | Élevé | Moyen |
| R2 | Manipulation de journaux d'accès | Journaux d'audit | Moyen | Faible |
| R3 | Attribution d'actions | Actions utilisateur | Moyen | Moyen |
**Atténuations :**
- [ ] Journalisation d'audit complète
- [ ] Protection de l'intégrité des journaux
- [ ] Signatures numériques pour les actions critiques
### 3.4 Menaces de divulgation d'informations
| ID | Menace | Cible | Impact | Probabilité |
|----|--------|-------|--------|-------------|
| I1 | Violation de données | Données personnelles | Critique | Moyen |
| I2 | Fuite de messages d'erreur | Informations système | Faible | Élevé |
| I3 | Transmission non sécurisée | Trafic réseau | Élevé | Moyen |
**Atténuations :**
- [ ] Chiffrement au repos et en transit
- [ ] Assainissement des messages d'erreur
- [ ] Implémenter TLS 1.3
### 3.5 Menaces de déni de service
| ID | Menace | Cible | Impact | Probabilité |
|----|--------|-------|--------|-------------|
| D1 | Épuisement des ressources | Serveurs API | Élevé | Élevé |
| D2 | Surcharge de base de données | Base de données | Critique | Moyen |
| D3 | Saturation de bande passante | Réseau | Élevé | Moyen |
**Atténuations :**
- [ ] Limitation de débit
- [ ] Mise à l'échelle automatique
- [ ] Protection DDoS
### 3.6 Menaces d'escalade de privilèges
| ID | Menace | Cible | Impact | Probabilité |
|----|--------|-------|--------|-------------|
| E1 | Vulnérabilités IDOR | Ressources utilisateur | Élevé | Élevé |
| E2 | Manipulation de rôle | Accès administrateur | Critique | Faible |
| E3 | Manipulation de claims JWT | Autorisation | Élevé | Moyen |
**Atténuations :**
- [ ] Contrôles d'autorisation appropriés
- [ ] Principe du moindre privilège
- [ ] Validation des rôles côté serveur
## 4. Évaluation des risques
### 4.1 Matrice des risques
IMPACT
Faible Moy Élevé Crit
Faible 1 2 3 4
P Moy 2 4 6 8 R Élevé 3 6 9 12 O Crit 4 8 12 16 B
### 4.2 Risques priorisés
| Rang | Menace | Score de risque | Priorité |
|------|--------|-----------------|----------|
| 1 | Injection SQL (T1) | 12 | Critique |
| 2 | IDOR (E1) | 9 | Élevé |
| 3 | Credential Stuffing (S3) | 9 | Élevé |
| 4 | Violation de données (I1) | 8 | Élevé |
## 5. Recommandations
### Actions immédiates
1. Implémenter un cadre de validation des entrées
2. Ajouter la limitation de débit aux points de terminaison d'authentification
3. Activer la journalisation d'audit complète
### Court terme (30 jours)
1. Déployer un WAF avec un ensemble de règles OWASP
2. Implémenter l'authentification multifacteur pour les opérations sensibles
3. Chiffrer toutes les données personnelles au repos
### Long terme (90 jours)
1. Formation de sensibilisation à la sécurité
2. Tests de pénétration
3. Programme de prime aux bugs
Modèle 2 : Code d'analyse STRIDE
from dataclasses import dataclass, field
from enum import Enum
from typing import List, Dict, Optional
import json
class StrideCategory(Enum):
SPOOFING = "S"
TAMPERING = "T"
REPUDIATION = "R"
INFORMATION_DISCLOSURE = "I"
DENIAL_OF_SERVICE = "D"
ELEVATION_OF_PRIVILEGE = "E"
class Impact(Enum):
LOW = 1
MEDIUM = 2
HIGH = 3
CRITICAL = 4
class Likelihood(Enum):
LOW = 1
MEDIUM = 2
HIGH = 3
CRITICAL = 4
@dataclass
class Threat:
id: str
category: StrideCategory
title: str
description: str
target: str
impact: Impact
likelihood: Likelihood
mitigations: List[str] = field(default_factory=list)
status: str = "open"
@property
def risk_score(self) -> int:
return self.impact.value * self.likelihood.value
@property
def risk_level(self) -> str:
score = self.risk_score
if score >= 12:
return "Critical"
elif score >= 6:
return "High"
elif score >= 3:
return "Medium"
return "Low"
@dataclass
class Asset:
name: str
sensitivity: str
description: str
data_classification: str
@dataclass
class TrustBoundary:
name: str
description: str
from_zone: str
to_zone: str
@dataclass
class ThreatModel:
name: str
version: str
description: str
assets: List[Asset] = field(default_factory=list)
boundaries: List[TrustBoundary] = field(default_factory=list)
threats: List[Threat] = field(default_factory=list)
def add_threat(self, threat: Threat) -> None:
self.threats.append(threat)
def get_threats_by_category(self, category: StrideCategory) -> List[Threat]:
return [t for t in self.threats if t.category == category]
def get_critical_threats(self) -> List[Threat]:
return [t for t in self.threats if t.risk_level in ("Critical", "High")]
def generate_report(self) -> Dict:
"""Générer un rapport du modèle de menace."""
return {
"summary": {
"name": self.name,
"version": self.version,
"total_threats": len(self.threats),
"critical_threats": len([t for t in self.threats if t.risk_level == "Critical"]),
"high_threats": len([t for t in self.threats if t.risk_level == "High"]),
},
"by_category": {
cat.name: len(self.get_threats_by_category(cat))
for cat in StrideCategory
},
"top_risks": [
{
"id": t.id,
"title": t.title,
"risk_score": t.risk_score,
"risk_level": t.risk_level
}
for t in sorted(self.threats, key=lambda x: x.risk_score, reverse=True)[:10]
]
}
class StrideAnalyzer:
"""Assistant automatisé pour l'analyse STRIDE."""
STRIDE_QUESTIONS = {
StrideCategory.SPOOFING: [
"Un attaquant peut-il usurper l'identité d'un utilisateur légitime ?",
"Les jetons d'authentification sont-ils correctement validés ?",
"Les identifiants de session peuvent-ils être prédits ou volés ?",
"L'authentification multifacteur est-elle disponible ?",
],
StrideCategory.TAMPERING: [
"Les données peuvent-elles être modifiées en transit ?",
"Les données peuvent-elles être modifiées au repos ?",
"Les contrôles de validation des entrées sont-ils suffisants ?",
"Un attaquant peut-il manipuler la logique de l'application ?",
],
StrideCategory.REPUDIATION: [
"Toutes les actions pertinentes pour la sécurité sont-elles journalisées ?",
"Les journaux peuvent-ils être manipulés ?",
"Y a-t-il une attribution suffisante pour les actions ?",
"Les horodatages sont-ils fiables et synchronisés ?",
],
StrideCategory.INFORMATION_DISCLOSURE: [
"Les données sensibles sont-elles chiffrées au repos ?",
"Les données sensibles sont-elles chiffrées en transit ?",
"Les messages d'erreur peuvent-ils révéler des informations sensibles ?",
"Les contrôles d'accès sont-ils correctement appliqués ?",
],
StrideCategory.DENIAL_OF_SERVICE: [
"Les limitations de débit sont-elles implémentées ?",
"Les ressources peuvent-elles être épuisées par une entrée malveillante ?",
"Y a-t-il une protection contre les attaques par amplification ?",
"Existe-t-il des points de défaillance unique ?",
],
StrideCategory.ELEVATION_OF_PRIVILEGE: [
"Les contrôles d'autorisation sont-ils appliqués de manière cohérente ?",
"Les utilisateurs peuvent-ils accéder aux ressources d'autres utilisateurs ?",
"Une escalade de privilèges peut-elle se produire par manipulation de paramètres ?",
"Le principe du moindre privilège est-il suivi ?",
],
}
def generate_questionnaire(self, component: str) -> List[Dict]:
"""Générer un questionnaire STRIDE pour un composant."""
questionnaire = []
for category, questions in self.STRIDE_QUESTIONS.items():
for q in questions:
questionnaire.append({
"component": component,
"category": category.name,
"question": q,
"answer": None,
"notes": ""
})
return questionnaire
def suggest_mitigations(self, category: StrideCategory) -> List[str]:
"""Suggérer les atténuations courantes pour une catégorie STRIDE."""
mitigations = {
StrideCategory.SPOOFING: [
"Implémenter l'authentification multifacteur",
"Utiliser une gestion sécurisée des sessions",
"Implémenter des politiques de verrouillage de compte",
"Utiliser des jetons cryptographiquement sécurisés",
"Valider l'authentification à chaque requête",
],
StrideCategory.TAMPERING: [
"Implémenter la validation des entrées",
"Utiliser des requêtes paramétrées",
"Appliquer des contrôles d'intégrité (HMAC, signatures)",
"Implémenter une politique de sécurité du contenu",
"Utiliser une infrastructure immuable",
],
StrideCategory.REPUDIATION: [
"Activer la journalisation d'audit complète",
"Protéger l'intégrité des journaux",
"Implémenter les signatures numériques",
"Utiliser une journalisation centralisée et inviolable",
"Maintenir des horodatages précis",
],
StrideCategory.INFORMATION_DISCLOSURE: [
"Chiffrer les données au repos et en transit",
"Implémenter des contrôles d'accès appropriés",
"Assainir les messages d'erreur",
"Utiliser des valeurs par défaut sécurisées",
"Implémenter la classification des données",
],
StrideCategory.DENIAL_OF_SERVICE: [
"Implémenter la limitation de débit",
"Utiliser la mise à l'échelle automatique",
"Déployer une protection DDoS",
"Implémenter les disjoncteurs",
"Définir des quotas de ressources",
],
StrideCategory.ELEVATION_OF_PRIVILEGE: [
"Implémenter l'autorisation appropriée",
"Suivre le principe du moindre privilège",
"Valider les permissions côté serveur",
"Utiliser le contrôle d'accès basé sur les rôles",
"Implémenter les limites de sécurité",
],
}
return mitigations.get(category, [])
Modèle 3 : Analyse du diagramme de flux de données
from dataclasses import dataclass
from typing import List, Set, Tuple
from enum import Enum
class ElementType(Enum):
EXTERNAL_ENTITY = "external"
PROCESS = "process"
DATA_STORE = "datastore"
DATA_FLOW = "dataflow"
@dataclass
class DFDElement:
id: str
name: str
type: ElementType
trust_level: int # 0 = non fiable, plus élevé = plus fiable
description: str = ""
@dataclass
class DataFlow:
id: str
name: str
source: str
destination: str
data_type: str
protocol: str
encrypted: bool = False
class DFDAnalyzer:
"""Analyser les diagrammes de flux de données pour les menaces STRIDE."""
def __init__(self):
self.elements: Dict[str, DFDElement] = {}
self.flows: List[DataFlow] = []
def add_element(self, element: DFDElement) -> None:
self.elements[element.id] = element
def add_flow(self, flow: DataFlow) -> None:
self.flows.append(flow)
def find_trust_boundary_crossings(self) -> List[Tuple[DataFlow, int]]:
"""Trouver les flux de données qui franchissent les limites de confiance."""
crossings = []
for flow in self.flows:
source = self.elements.get(flow.source)
dest = self.elements.get(flow.destination)
if source and dest and source.trust_level != dest.trust_level:
trust_diff = abs(source.trust_level - dest.trust_level)
crossings.append((flow, trust_diff))
return sorted(crossings, key=lambda x: x[1], reverse=True)
def identify_threats_per_element(self) -> Dict[str, List[StrideCategory]]:
"""Mapper les catégories STRIDE applicables aux types d'éléments."""
threat_mapping = {
ElementType.EXTERNAL_ENTITY: [
StrideCategory.SPOOFING,
StrideCategory.REPUDIATION,
],
ElementType.PROCESS: [
StrideCategory.SPOOFING,
StrideCategory.TAMPERING,
StrideCategory.REPUDIATION,
StrideCategory.INFORMATION_DISCLOSURE,
StrideCategory.DENIAL_OF_SERVICE,
StrideCategory.ELEVATION_OF_PRIVILEGE,
],
ElementType.DATA_STORE: [
StrideCategory.TAMPERING,
StrideCategory.REPUDIATION,
StrideCategory.INFORMATION_DISCLOSURE,
StrideCategory.DENIAL_OF_SERVICE,
],
ElementType.DATA_FLOW: [
StrideCategory.TAMPERING,
StrideCategory.INFORMATION_DISCLOSURE,
StrideCategory.DENIAL_OF_SERVICE,
],
}
result = {}
for elem_id, elem in self.elements.items():
result[elem_id] = threat_mapping.get(elem.type, [])
return result
def analyze_unencrypted_flows(self) -> List[DataFlow]:
"""Trouver les flux de données non chiffrés franchissant les limites de confiance."""
risky_flows = []
for flow in self.flows:
if not flow.encrypted:
source = self.elements.get(flow.source)
dest = self.elements.get(flow.destination)
if source and dest and source.trust_level != dest.trust_level:
risky_flows.append(flow)
return risky_flows
def generate_threat_enumeration(self) -> List[Dict]:
"""Générer une énumération de menaces complète."""
threats = []
element_threats = self.identify_threats_per_element()
for elem_id, categories in element_threats.items():
elem = self.elements[elem_id]
for category in categories:
threats.append({
"element_id": elem_id,
"element_name": elem.name,
"element_type": elem.type.value,
"stride_category": category.name,
"description": f"Menace {category.name} contre {elem.name}",
"trust_level": elem.trust_level
})
return threats
Modèle 4 : STRIDE par interaction
from typing import List, Dict, Optional
from dataclasses import dataclass
@dataclass
class Interaction:
"""Représente une interaction entre deux composants."""
id: str
source: str
target: str
action: str
data: str
protocol: str
class StridePerInteraction:
"""Appliquer STRIDE à chaque interaction du système."""
INTERACTION_THREATS = {
# Type source -> Type cible -> Menaces applicables
("external", "process"): {
"S": "L'entité externe usurpe l'identité du processus",
"T": "Tampering avec les données envoyées au processus",
"R": "L'entité externe nie l'envoi de données",
"I": "Exposition des données pendant la transmission",
"D": "Inondation du processus de requêtes",
"E": "Exploitation du processus pour obtenir des privilèges",
},
("process", "datastore"): {
"T": "Le processus tampering avec les données stockées",
"R": "Le processus nie les modifications de données",
"I": "Accès non autorisé aux données par le processus",
"D": "Le processus épuise les ressources de stockage",
},
("process", "process"): {
"S": "Un processus usurpe l'identité d'un autre processus",
"T": "Tampering avec les données inter-processus",
"I": "Fuite de données entre processus",
"D": "Un processus submerge un autre",
"E": "Un processus obtient un accès élevé",
},
}
def analyze_interaction(
self,
interaction: Interaction,
source_type: str,
target_type: str
) -> List[Dict]:
"""Analyser une interaction unique pour les menaces STRIDE."""
threats = []
key = (source_type, target_type)
applicable_threats = self.INTERACTION_THREATS.get(key, {})
for stride_code, description in applicable_threats.items():
threats.append({
"interaction_id": interaction.id,
"source": interaction.source,
"target": interaction.target,
"stride_category": stride_code,
"threat_description": description,
"context": f"{interaction.action} - {interaction.data}",
})
return threats
def generate_threat_matrix(
self,
interactions: List[Interaction],
element_types: Dict[str, str]
) -> List[Dict]:
"""Générer la matrice de menaces complète pour toutes les interactions."""
all_threats = []
for interaction in interactions:
source_type = element_types.get(interaction.source, "unknown")
target_type = element_types.get(interaction.target, "unknown")
threats = self.analyze_interaction(
interaction, source_type, target_type
)
all_threats.extend(threats)
return all_threats
Bonnes pratiques
À faire
- Impliquer les parties prenantes - Perspectives de sécurité, développement et opérations
- Être systématique - Couvrir toutes les catégories STRIDE
- Prioriser de manière réaliste - Se concentrer sur les menaces à fort impact
- Mettre à jour régulièrement - Les modèles de menace sont des documents vivants
- Utiliser des aides visuelles - Les diagrammes de flux aident la communication
À éviter
- Ne pas sauter de catégories - Chacune révèle des menaces différentes
- Ne pas assumer la sécurité - Questionner chaque composant
- Ne pas travailler en isolement - La modélisation collaborative est meilleure
- Ne pas ignorer les menaces à faible probabilité - Les menaces à fort impact comptent
- Ne pas s'arrêter à l'identification - Suivre jusqu'aux atténuations