Construction d'une bibliothèque de schémas d'attaque à partir de rapports CTI
Aperçu
Les rapports de cyber-renseignement (CTI) provenant de fournisseurs tels que Mandiant, CrowdStrike, Talos et Microsoft contiennent des descriptions détaillées des comportements des adversaires. Ces informations peuvent être extraites, normalisées et cataloguées dans une bibliothèque structurée de schémas d'attaque. Cette compétence couvre l'analyse syntaxique des rapports CTI pour extraire les techniques adverses, la mise en correspondance des comportements avec les identifiants de techniques MITRE ATT&CK, la création d'objets Attack Pattern STIX 2.1, la construction d'une bibliothèque interrogeable indexée par tactique, technique et acteur de menace, ainsi que la génération de modèles de règles de détection à partir des motifs documentés.
Quand l'utiliser
- Lors du déploiement ou de la configuration de capacités de construction de bibliothèque de schémas d'attaque dans votre environnement
- Lors de l'établissement de contrôles de sécurité conformes aux exigences réglementaires
- Lors de la construction ou de l'amélioration de l'architecture de sécurité pour ce domaine
- Lors de la réalisation d'évaluations de sécurité nécessitant cette implémentation
Prérequis
- Python 3.9+ avec les bibliothèques
stix2,mitreattack-python,spacy,requests - Collection de rapports CTI (format PDF, HTML ou texte)
- Données STIX de MITRE ATT&CK (locales ou via TAXII)
- Compréhension de la structure des techniques ATT&CK et des conventions de nommage
- Familiarité avec les concepts d'ingénierie de détection (Sigma, YARA)
Concepts clés
Extraction de schémas d'attaque
Les rapports CTI décrivent les comportements adverses en langage naturel. L'extraction implique l'identification de verbes d'action et de termes techniques qui correspondent aux techniques ATT&CK, la reconnaissance des noms d'outils et de familles de malwares, l'identification des indicateurs infrastructurels, et la mise en correspondance des séquences de comportements avec les chaînes d'attaque (phases du kill chain).
Objets Attack Pattern STIX 2.1
STIX définit Attack Pattern comme un objet de domaine structuré (SDO) qui décrit les façons dont les adversaires tentent de compromettre des cibles. Chaque schéma est lié à ATT&CK via des références externes, inclut les phases du kill chain (tactiques) et peut être relié à des objets Intrusion Set, Malware et Tool.
Génération de règles de détection
Les schémas d'attaque extraits renseignent l'ingénierie de détection en fournissant : des exemples de procédures spécifiques pour la création de règles Sigma, des séquences comportementales pour les règles de corrélation, des motifs d'IOC pour les règles YARA et Snort, et des exigences de sources de données pour combler les lacunes de télémétrie.
Flux de travail
Étape 1 : Analyser les rapports CTI et extraire les comportements
import re
import json
from collections import defaultdict
class CTIReportParser:
"""Analyser les rapports CTI pour extraire les comportements adverses."""
BEHAVIOR_INDICATORS = [
"used", "executed", "deployed", "leveraged", "exploited",
"established", "created", "modified", "downloaded", "uploaded",
"exfiltrated", "injected", "enumerated", "spawned", "dropped",
"persisted", "escalated", "moved laterally", "collected",
"encrypted", "compressed", "encoded", "obfuscated",
]
TOOL_PATTERNS = [
r'\b(Cobalt Strike|Mimikatz|PsExec|BloodHound|Rubeus|Impacket)\b',
r'\b(PowerShell|cmd\.exe|WMI|WMIC|certutil|bitsadmin)\b',
r'\b(Metasploit|Empire|Covenant|Sliver|Brute Ratel)\b',
r'\b(Lazagne|SharpHound|ADFind|Sharphound|Invoke-Obfuscation)\b',
]
TECHNIQUE_KEYWORDS = {
"spearphishing": "T1566",
"phishing attachment": "T1566.001",
"phishing link": "T1566.002",
"powershell": "T1059.001",
"command line": "T1059.003",
"scheduled task": "T1053.005",
"registry run key": "T1547.001",
"process injection": "T1055",
"dll side-loading": "T1574.002",
"credential dumping": "T1003",
"lsass": "T1003.001",
"kerberoasting": "T1558.003",
"pass the hash": "T1550.002",
"remote desktop": "T1021.001",
"smb": "T1021.002",
"winrm": "T1021.006",
"data staging": "T1074",
"exfiltration over c2": "T1041",
"dns tunneling": "T1071.004",
"web shell": "T1505.003",
}
def parse_report(self, text, report_metadata=None):
"""Analyser un rapport CTI et extraire les comportements."""
sentences = re.split(r'[.!?]\s+', text)
behaviors = []
for sentence in sentences:
sentence_lower = sentence.lower()
# Vérifier les indicateurs de comportement
for indicator in self.BEHAVIOR_INDICATORS:
if indicator in sentence_lower:
behavior = {
"sentence": sentence.strip(),
"action": indicator,
"tools": self._extract_tools(sentence),
"technique_hints": self._match_techniques(sentence_lower),
}
if behavior["technique_hints"]:
behaviors.append(behavior)
break
print(f"[+] Extrait {len(behaviors)} indicateurs comportementaux du rapport")
return behaviors
def _extract_tools(self, text):
"""Extraire les noms d'outils/malwares du texte."""
tools = set()
for pattern in self.TOOL_PATTERNS:
matches = re.findall(pattern, text, re.IGNORECASE)
tools.update(matches)
return list(tools)
def _match_techniques(self, text):
"""Faire correspondre le texte aux indices de techniques ATT&CK."""
matches = []
for keyword, tech_id in self.TECHNIQUE_KEYWORDS.items():
if keyword in text:
matches.append({"keyword": keyword, "technique_id": tech_id})
return matches
parser = CTIReportParser()
sample_report = """
The threat actor used spearphishing attachments with macro-enabled documents to
gain initial access. Once inside, they executed PowerShell scripts to download
additional tooling. The actor leveraged Mimikatz to dump credentials from LSASS
memory. They then used pass the hash techniques for lateral movement via SMB
to multiple systems. Data was staged in a compressed archive and exfiltrated
over the existing C2 channel. The actor established persistence through
scheduled tasks and registry run keys.
"""
behaviors = parser.parse_report(sample_report)
Étape 2 : Mapper les comportements aux techniques ATT&CK
from attackcti import attack_client
class ATTACKMapper:
def __init__(self):
self.lift = attack_client()
self.techniques = {}
self._load_techniques()
def _load_techniques(self):
"""Charger toutes les techniques ATT&CK pour la mise en correspondance."""
all_techs = self.lift.get_enterprise_techniques()
for tech in all_techs:
tech_id = ""
for ref in tech.get("external_references", []):
if ref.get("source_name") == "mitre-attack":
tech_id = ref.get("external_id", "")
break
if tech_id:
self.techniques[tech_id] = {
"name": tech.get("name", ""),
"description": tech.get("description", "")[:500],
"tactics": [p.get("phase_name") for p in tech.get("kill_chain_phases", [])],
"platforms": tech.get("x_mitre_platforms", []),
"data_sources": tech.get("x_mitre_data_sources", []),
}
print(f"[+] Chargé {len(self.techniques)} techniques ATT&CK")
def map_behaviors(self, behaviors):
"""Mapper les comportements extraits aux techniques ATT&CK."""
mapped = []
for behavior in behaviors:
for hint in behavior.get("technique_hints", []):
tech_id = hint["technique_id"]
if tech_id in self.techniques:
tech_info = self.techniques[tech_id]
mapped.append({
"technique_id": tech_id,
"technique_name": tech_info["name"],
"tactics": tech_info["tactics"],
"source_sentence": behavior["sentence"],
"tools_observed": behavior["tools"],
"keyword_matched": hint["keyword"],
"data_sources": tech_info["data_sources"],
})
print(f"[+] Mappé {len(mapped)} comportements aux techniques ATT&CK")
return mapped
mapper = ATTACKMapper()
mapped_behaviors = mapper.map_behaviors(behaviors)
Étape 3 : Créer une bibliothèque de schémas d'attaque STIX 2.1
from stix2 import AttackPattern, Relationship, Bundle, TLP_GREEN
from datetime import datetime
class AttackPatternLibrary:
def __init__(self):
self.patterns = []
self.relationships = []
def add_pattern_from_mapping(self, mapping, report_source="Rapport CTI"):
"""Créer un objet Attack Pattern STIX à partir d'une mise en correspondance."""
pattern = AttackPattern(
name=mapping["technique_name"],
description=f"Observé : {mapping['source_sentence']}\n\n"
f"Outils : {', '.join(mapping['tools_observed']) or 'Aucun identifié'}\n"
f"Source : {report_source}",
external_references=[{
"source_name": "mitre-attack",
"external_id": mapping["technique_id"],
"url": f"https://attack.mitre.org/techniques/{mapping['technique_id'].replace('.', '/')}/",
}],
kill_chain_phases=[{
"kill_chain_name": "mitre-attack",
"phase_name": tactic,
} for tactic in mapping["tactics"]],
object_marking_refs=[TLP_GREEN],
)
self.patterns.append(pattern)
return pattern
def build_library(self, mapped_behaviors, report_source="Rapport CTI"):
"""Construire une bibliothèque complète de schémas d'attaque à partir des mises en correspondance."""
seen_techniques = set()
for mapping in mapped_behaviors:
tech_id = mapping["technique_id"]
if tech_id not in seen_techniques:
self.add_pattern_from_mapping(mapping, report_source)
seen_techniques.add(tech_id)
bundle = Bundle(objects=self.patterns + self.relationships)
print(f"[+] Bibliothèque : {len(self.patterns)} schémas d'attaque")
return bundle
def export_library(self, output_file="attack_pattern_library.json"):
bundle = Bundle(objects=self.patterns + self.relationships)
with open(output_file, "w") as f:
f.write(bundle.serialize(pretty=True))
print(f"[+] Bibliothèque exportée vers {output_file}")
def generate_detection_templates(self, mapped_behaviors):
"""Générer des modèles de règles Sigma à partir de schémas d'attaque."""
templates = []
for mapping in mapped_behaviors:
template = {
"title": f"Détection : {mapping['technique_name']} ({mapping['technique_id']})",
"status": "experimental",
"description": f"Détecte {mapping['technique_name']} basé sur l'observation du rapport CTI",
"references": [
f"https://attack.mitre.org/techniques/{mapping['technique_id'].replace('.', '/')}/",
],
"tags": [
f"attack.{mapping['tactics'][0]}" if mapping['tactics'] else "attack.unknown",
f"attack.{mapping['technique_id'].lower()}",
],
"data_sources": mapping.get("data_sources", []),
"observed_tools": mapping.get("tools_observed", []),
"source_context": mapping["source_sentence"],
}
templates.append(template)
with open("detection_templates.json", "w") as f:
json.dump(templates, f, indent=2)
print(f"[+] Généré {len(templates)} modèles de détection")
return templates
library = AttackPatternLibrary()
bundle = library.build_library(mapped_behaviors, "Rapport CTI exemple")
library.export_library()
templates = library.generate_detection_templates(mapped_behaviors)
Critères de validation
- Rapport CTI analysé et indicateurs comportementaux extraits
- Comportements mappés aux techniques ATT&CK avec confiance
- Objets Attack Pattern STIX 2.1 créés avec des références appropriées
- Bibliothèque interrogeable par tactique, technique et acteur de menace
- Modèles de détection générés à partir des motifs documentés
- Bibliothèque exportable en tant que bundle STIX pour le partage