stride-analysis-patterns

Par wshobson · agents

Appliquez la méthodologie STRIDE pour identifier les menaces de manière systématique. À utiliser lors de l'analyse de la sécurité d'un système, des sessions de modélisation des menaces ou de la création de documentation de sécurité.

npx skills add https://github.com/wshobson/agents --skill stride-analysis-patterns

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

Skills similaires