Automatisez votre veille cyber threat intelligence en 2026 : STIX 2.1, MISP, OpenCTI, TheHive, pipeline IOC Python et intégration SIEM complète.
TL;DR — En résumé
Guide technique approfondi sur threat intelligence : automatiser la veille cyber. Cet article presente les techniques, outils et bonnes pratiques.
La threat intelligence automatisée transforme la veille cyber d'un travail manuel chronophage en un pipeline structuré de collecte, normalisation et exploitation des indicateurs de compromission. En 2026, les équipes SOC qui n'ont pas automatisé leur TI traitent des données périmées avec 24 à 72 heures de retard sur les attaquants. Ce guide détaille l'architecture technique complète : STIX/TAXII, MISP, OpenCTI, TheHive/Cortex, et les scripts Python pour automatiser chaque étape.
La threat intelligence automatiser veille cyber 2026 ne se résume pas à agréger des flux RSS ou des listes de blocage IP. C'est une discipline structurée qui transforme des données brutes sur les menaces en renseignements actionnables — compris, contextualisés, et intégrés dans les défenses en temps réel. La différence entre une équipe SOC qui subit les attaques et une qui les anticipe tient souvent à la qualité de son pipeline TI. Les standards STIX 2.1 et TAXII 2.1 ont imposé un langage commun qui permet enfin l'interopérabilité entre les outils. MISP et OpenCTI sont devenus les backbones open source de milliers de SOC dans le monde. TheHive et Cortex ferment la boucle entre l'intelligence et la réponse à incident. Ce guide part du standard et descend jusqu'au script Python qui tourne à 3h du matin pour extraire les IOC d'une alerte CERT-FR avant votre équipe. L'objectif : un pipeline TI complet, du feed à l'alerte SIEM, sans intervention manuelle pour les cas nominaux. Pour les cas complexes, la valeur ajoutée humaine reste irremplaçable — mais elle doit s'exercer sur les décisions stratégiques, pas sur le copier-coller d'IP dans des listes de blocage.
À retenir
- STIX 2.1 : le format JSON standard pour structurer les renseignements sur les menaces — indicateurs, malwares, acteurs de menace, relations entre eux — interopérable entre tous les outils de la chaîne TI.
- MISP : plateforme open source de partage de threat intelligence, déployable en Docker en moins d'une heure, avec des feeds CERT-FR et CIRCL intégrables immédiatement.
- OpenCTI : couche d'analyse et de visualisation au-dessus de MISP, avec connectors vers MITRE ATT&CK, AlienVault OTX, et intégration GraphQL pour l'automatisation.
- Pipeline complet : collecte (feeds TAXII/RSS/API) → normalisation STIX → déduplication → enrichissement (VT, Shodan) → scoring TLP/PAP → push SIEM/firewall — tout automatisable en Python.
- TheHive + Cortex : le duo case management + enrichissement automatique qui connecte l'intelligence aux processus de réponse à incident, avec des centaines d'analyzers disponibles.
Pourquoi STIX 2.1 et TAXII sont-ils devenus les standards incontournables ?
STIX 2.1 (Structured Threat Information Expression) est le standard JSON pour représenter les informations sur les menaces cyber. Il définit trois catégories d'objets :
- SDO (STIX Domain Objects) : Indicator, Malware, Attack-Pattern, Threat-Actor, Campaign, Tool, Vulnerability, Course-of-Action
- SCO (STIX Cyber Observables) : IPv4-Addr, Domain-Name, URL, File (avec hashes), Email-Message, Process, User-Account
- SRO (STIX Relationship Objects) : les relations typées entre SDO/SCO (ex: Indicator "indicates" Malware)
Voici un exemple concret d'objets STIX 2.1 — un indicateur d'IP malveillante liée à un malware :
{
"type": "bundle",
"id": "bundle--12345678-1234-1234-1234-123456789012",
"objects": [
{
"type": "indicator",
"spec_version": "2.1",
"id": "indicator--44d88612-fea8-a8f3-6de8-2e1278abb02f",
"created": "2026-07-17T08:00:00.000Z",
"modified": "2026-07-17T08:00:00.000Z",
"name": "C2 IP address - Emotet botnet",
"pattern": "[ipv4-addr:value = '185.220.101.45']",
"pattern_type": "stix",
"valid_from": "2026-07-17T08:00:00.000Z",
"indicator_types": ["malicious-activity"],
"confidence": 85,
"labels": ["emotet", "c2", "botnet"]
},
{
"type": "malware",
"spec_version": "2.1",
"id": "malware--fdd60b30-b537-4b89-bc83-8c69dd85e756",
"created": "2026-07-17T08:00:00.000Z",
"modified": "2026-07-17T08:00:00.000Z",
"name": "Emotet",
"malware_types": ["trojan", "dropper"],
"is_family": true
},
{
"type": "relationship",
"spec_version": "2.1",
"id": "relationship--44d88612-fea8-a8f3-6de8-2e1278abb02e",
"created": "2026-07-17T08:00:00.000Z",
"modified": "2026-07-17T08:00:00.000Z",
"relationship_type": "indicates",
"source_ref": "indicator--44d88612-fea8-a8f3-6de8-2e1278abb02f",
"target_ref": "malware--fdd60b30-b537-4b89-bc83-8c69dd85e756"
}
]
}
TAXII 2.1 (Trusted Automated Exchange of Intelligence Information) est le protocole HTTP REST pour transporter les objets STIX. Il définit deux endpoints principaux : Discovery (liste des services disponibles) et Collections (flux d'objets STIX). Les clients TAXII peuvent pousser (push) ou tirer (pull) des données depuis un serveur TAXII, avec filtrage par type d'objet, date de création, ou label.
MISP — Configuration et Feeds en Production
MISP (Malware Information Sharing Platform) est la plateforme de threat intelligence open source la plus déployée au monde. Voici le déploiement Docker minimal en production :
# Déploiement MISP avec Docker Compose
git clone https://github.com/MISP/misp-docker.git
cd misp-docker
cp template.env .env
# Configurer les variables d'environnement
echo "MISP_BASEURL=https://misp.votre-domaine.fr" >> .env
echo "[email protected]" >> .env
echo "MISP_ADMIN_PASSPHRASE=VotreMotDePasseSecurise2026!" >> .env
# Démarrer MISP
docker-compose up -d
# Vérifier le statut
docker-compose ps
docker-compose logs -f misp-core
# Configurer les feeds CERT-FR et CIRCL dans MISP
# Via l'API Python :
pip install pymisp
Script Python pour configurer les feeds essentiels et ajouter des IOC via l'API MISP :
from pymisp import PyMISP, MISPEvent, MISPAttribute
import json
# Connexion à MISP
misp = PyMISP(
url='https://misp.votre-domaine.fr',
key='VOTRE_CLE_API_MISP',
ssl=True
)
# Activer le feed CIRCL OSINT (feed officiel)
feeds = [
{
'name': 'CIRCL OSINT Feed',
'provider': 'CIRCL',
'url': 'https://www.circl.lu/doc/misp/feed-osint/',
'enabled': True,
'distribution': 0, # Organisation only
'input_source': 'network',
'source_format': 'misp',
},
{
'name': 'CERT-FR Feed',
'provider': 'ANSSI CERT-FR',
'url': 'https://www.cert.ssi.gouv.fr/ioc/',
'enabled': True,
'distribution': 0,
'input_source': 'network',
'source_format': 'misp',
}
]
for feed_config in feeds:
result = misp.add_feed(feed_config, pythonify=True)
print(f"Feed ajouté: {result.name}")
# Ajouter un IOC manuellement
event = MISPEvent()
event.info = "Emotet C2 Infrastructure - 2026-07-17"
event.distribution = 0 # Organisation only
event.threat_level_id = 2 # Medium
event.analysis = 2 # Completed
# Ajouter un attribut IP
attr = MISPAttribute()
attr.type = 'ip-dst'
attr.value = '185.220.101.45'
attr.comment = 'Emotet C2 server observé le 2026-07-17'
attr.to_ids = True # Activer la règle IDS
event.add_attribute(**attr.__dict__)
# Publier l'événement
result = misp.add_event(event, pythonify=True)
misp.publish(result, alert=False)
print(f"Événement créé: {result.id}")
# Requêter les IOC des 24 dernières heures
from datetime import datetime, timedelta
yesterday = (datetime.now() - timedelta(hours=24)).strftime('%Y-%m-%dT%H:%M:%S')
events = misp.search(
controller='events',
type_attribute='ip-dst',
timestamp=yesterday,
to_ids=True,
pythonify=True
)
for event in events:
print(f"Event {event.id}: {event.info}")
for attr in event.attributes:
print(f" [{attr.type}] {attr.value}")
# Export STIX 2.1 depuis MISP
stix_export = misp.get_stix(event.id, '2')
with open('/tmp/export_stix.json', 'w') as f:
json.dump(stix_export, f, indent=2)
print("Export STIX 2.1 sauvegardé")
MISP intègre aussi les taxonomies (TLP, PAP, Adversary Infrastructure) et les galaxies (MITRE ATT&CK, threat actors). La galerie ATT&CK mappée sur les événements MISP permet de corréler automatiquement les IOC avec des TTPs — indispensable pour les rapports de threat intelligence contextualisés. Pour aller plus loin dans la corrélation des menaces, notre article sur le threat hunting avec Microsoft 365 Sentinel détaille l'intégration des IOC MISP dans un SIEM cloud.
OpenCTI — La Plateforme CTI Open Source de Nouvelle Génération
OpenCTI est la plateforme CTI open source développée par Filigran (anciennement ANSSI/Luatix). Son architecture repose sur :
- Elasticsearch : stockage et indexation des objets STIX 2.1
- RabbitMQ : queue de messages pour les connectors asynchrones
- Redis : cache et sessions utilisateurs
- MinIO : stockage des fichiers (rapports PDF, exports)
Les connectors disponibles couvrent les sources majeures : MITRE ATT&CK (auto-import des TTPs), AlienVault OTX, CAPE Sandbox, OpenCTI Datasets, CrowdStrike, Recorded Future (payant), et des dizaines d'autres. Chaque connector tourne comme un microservice Docker indépendant, consommant depuis RabbitMQ.
L'API GraphQL d'OpenCTI permet d'automatiser toutes les opérations. Exemple de requête pour récupérer les indicateurs récents :
import requests
import json
OPENCTI_URL = 'https://opencti.votre-domaine.fr'
OPENCTI_TOKEN = 'votre-token-api'
# Requête GraphQL pour les indicateurs des 48 dernières heures
query = """
query GetRecentIndicators {
indicators(
filters: {
filters: [{
key: "created_at",
values: ["2026-07-15T00:00:00Z"],
operator: gt
}]
},
first: 100,
orderBy: created_at,
orderMode: desc
) {
edges {
node {
id
name
pattern
indicator_types
confidence
created_at
objectLabel {
edges {
node { value }
}
}
}
}
}
}
"""
response = requests.post(
f'{OPENCTI_URL}/graphql',
json={'query': query},
headers={
'Authorization': f'Bearer {OPENCTI_TOKEN}',
'Content-Type': 'application/json'
}
)
data = response.json()
indicators = data['data']['indicators']['edges']
print(f"Indicateurs récupérés: {len(indicators)}")
for edge in indicators:
node = edge['node']
print(f" [{node['confidence']}%] {node['name']}: {node['pattern']}")
OpenCTI excelle dans la visualisation des relations entre entités — voir comment un groupe APT (Threat Actor) utilise un malware spécifique, qui l'a utilisé dans quelle campagne, contre quels secteurs d'activité, avec quels IOC associés. C'est cette capacité de graphe de connaissance qui différencie OpenCTI d'une simple liste de blocage.
TheHive + Cortex — Du Renseignement à la Réponse à Incident
TheHive est un SIRP (Security Incident Response Platform) open source qui gère les cas d'investigation. Cortex est le moteur d'analyse et de réponse automatique, avec des centaines d'analyzers et de responders. Ensemble, ils ferment la boucle entre la threat intelligence et la réponse opérationnelle.
Le workflow typique : une alerte MISP déclenche la création automatique d'un case TheHive via l'intégration MISP-TheHive. L'analyste assigné lance des analyzers Cortex sur les IOC — VirusTotal pour les hashes, Shodan pour les IPs, PassiveDNS pour les domaines, etc. Les résultats enrichissent le case automatiquement. Si un IOC est confirmé malveillant, un responder Cortex peut bloquer l'IP sur le firewall ou créer une règle SIEM.
Notre guide sur les playbooks IA pour l'incident response détaille comment automatiser les playbooks TheHive pour les cas les plus fréquents (phishing, malware, credential theft).
Enrichissement IOC — VirusTotal API v3 et Shodan API
L'enrichissement automatique des IOC est l'une des tâches les plus chronophages du SOC — et la plus facile à automatiser. Voici un script Python complet pour enrichir des IP, URL et hashes via VirusTotal API v3 :
import requests
import time
import json
from typing import Optional
VT_API_KEY = 'VOTRE_CLE_VT_API_v3'
SHODAN_API_KEY = 'VOTRE_CLE_SHODAN'
class IOCEnricher:
def __init__(self, vt_key: str, shodan_key: str):
self.vt_key = vt_key
self.shodan_key = shodan_key
self.vt_base = 'https://www.virustotal.com/api/v3'
self.shodan_base = 'https://api.shodan.io'
def enrich_hash(self, file_hash: str) -> dict:
"""Enrichit un hash MD5/SHA1/SHA256 via VT API v3"""
headers = {'x-apikey': self.vt_key}
response = requests.get(
f'{self.vt_base}/files/{file_hash}',
headers=headers
)
if response.status_code == 200:
data = response.json()['data']['attributes']
return {
'hash': file_hash,
'type': 'hash',
'malicious': data['last_analysis_stats']['malicious'],
'suspicious': data['last_analysis_stats']['suspicious'],
'total': sum(data['last_analysis_stats'].values()),
'names': data.get('names', [])[:5],
'verdict': 'malicious' if data['last_analysis_stats']['malicious'] > 3 else 'clean'
}
time.sleep(1) # Respect rate limit public API: 4 req/min
return {'hash': file_hash, 'error': f'VT error {response.status_code}'}
def enrich_ip(self, ip: str) -> dict:
"""Enrichit une IP via VT API v3 + Shodan"""
headers = {'x-apikey': self.vt_key}
# VirusTotal
vt_response = requests.get(
f'{self.vt_base}/ip_addresses/{ip}',
headers=headers
)
result = {'ip': ip, 'type': 'ip'}
if vt_response.status_code == 200:
vt_data = vt_response.json()['data']['attributes']
result['vt_malicious'] = vt_data['last_analysis_stats']['malicious']
result['vt_country'] = vt_data.get('country', 'Unknown')
result['vt_owner'] = vt_data.get('as_owner', 'Unknown')
# Shodan
time.sleep(1)
shodan_response = requests.get(
f'{self.shodan_base}/shodan/host/{ip}',
params={'key': self.shodan_key}
)
if shodan_response.status_code == 200:
shodan_data = shodan_response.json()
result['open_ports'] = [p['port'] for p in shodan_data.get('data', [])]
result['hostnames'] = shodan_data.get('hostnames', [])
result['shodan_tags'] = shodan_data.get('tags', [])
result['verdict'] = 'malicious' if result.get('vt_malicious', 0) > 3 else 'unknown'
return result
def enrich_url(self, url: str) -> dict:
"""Enrichit une URL via VT API v3"""
import base64
headers = {'x-apikey': self.vt_key}
url_id = base64.urlsafe_b64encode(url.encode()).decode().strip('=')
response = requests.get(
f'{self.vt_base}/urls/{url_id}',
headers=headers
)
if response.status_code == 200:
data = response.json()['data']['attributes']
return {
'url': url,
'type': 'url',
'malicious': data['last_analysis_stats']['malicious'],
'verdict': 'malicious' if data['last_analysis_stats']['malicious'] > 2 else 'clean'
}
return {'url': url, 'error': f'VT error {response.status_code}'}
# Utilisation
enricher = IOCEnricher(VT_API_KEY, SHODAN_API_KEY)
iocs_to_enrich = [
{'type': 'ip', 'value': '185.220.101.45'},
{'type': 'hash', 'value': 'd41d8cd98f00b204e9800998ecf8427e'},
{'type': 'url', 'value': 'http://malicious-site.example.com/payload'},
]
for ioc in iocs_to_enrich:
if ioc['type'] == 'ip':
result = enricher.enrich_ip(ioc['value'])
elif ioc['type'] == 'hash':
result = enricher.enrich_hash(ioc['value'])
elif ioc['type'] == 'url':
result = enricher.enrich_url(ioc['value'])
print(json.dumps(result, indent=2))
time.sleep(1) # Rate limit VT API public: 4 req/min
Pour la priorisation des vulnérabilités associées aux IOC, notre article sur la gestion des vulnérabilités par IA et score EPSS détaille comment combiner threat intelligence et EPSS pour prioriser les patches.
Comment automatiser un pipeline d'agrégation IOC de bout en bout ?
Un pipeline TI complet prend les données brutes de multiples sources et produit des IOC enrichis, scorés, et prêts à être poussés vers les défenses. Architecture simplifiée :
import feedparser
import re
import hashlib
import json
from datetime import datetime
from collections import defaultdict
class TIPipeline:
"""Pipeline simplifié de Threat Intelligence automatisé"""
def __init__(self):
self.ioc_store = defaultdict(dict) # ioc_value -> metadata
self.sources = []
def collect_from_rss_feed(self, feed_url: str, source_name: str):
"""Collecte IOC depuis un flux RSS (CERT-FR, etc.)"""
feed = feedparser.parse(feed_url)
iocs_found = []
# Patterns de détection IOC dans le texte
ip_pattern = re.compile(
r'\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}'
r'(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b'
)
domain_pattern = re.compile(
r'\b(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)'
r'+(?:com|net|org|fr|de|ru|cn|tk|top|xyz)\b'
)
hash_pattern = re.compile(r'\b[0-9a-fA-F]{32,64}\b')
for entry in feed.entries[:20]: # Dernières 20 entrées
text = f"{entry.get('title', '')} {entry.get('summary', '')}"
for ip in ip_pattern.findall(text):
# Filtrer IPs privées/localhost
if not any(ip.startswith(prefix) for prefix in
['10.', '192.168.', '172.16.', '127.']):
iocs_found.append({
'type': 'ip-dst',
'value': ip,
'source': source_name,
'source_url': entry.get('link', ''),
'first_seen': datetime.now().isoformat()
})
return iocs_found
def deduplicate(self, iocs: list) -> list:
"""Déduplique les IOC par valeur"""
seen = set()
unique = []
for ioc in iocs:
key = f"{ioc['type']}:{ioc['value']}"
if key not in seen:
seen.add(key)
unique.append(ioc)
return unique
def score_ioc(self, ioc: dict, enrichment: dict = None) -> dict:
"""Score un IOC selon multiple critères"""
score = 0
# Source trust score
source_scores = {
'CERT-FR': 90,
'CIRCL-OSINT': 85,
'AlienVault-OTX': 70,
'Twitter-IOC': 40,
}
score += source_scores.get(ioc.get('source', ''), 50)
# Enrichissement VT
if enrichment and enrichment.get('vt_malicious', 0) > 5:
score = min(100, score + 20)
elif enrichment and enrichment.get('vt_malicious', 0) > 2:
score = min(100, score + 10)
ioc['confidence_score'] = score
ioc['tlp'] = 'RED' if score > 85 else ('AMBER' if score > 60 else 'GREEN')
return ioc
def push_to_siem(self, iocs: list, siem_endpoint: str):
"""Push IOC vers SIEM (format générique)"""
import requests
payload = {
'timestamp': datetime.now().isoformat(),
'source': 'TI-Pipeline',
'iocs': iocs
}
# Exemple: push vers Wazuh ou Elastic
# response = requests.post(siem_endpoint, json=payload)
print(f"[SIEM] {len(iocs)} IOC prêts pour push vers {siem_endpoint}")
return payload
# Utilisation
pipeline = TIPipeline()
# Collecte depuis CERT-FR RSS
certfr_iocs = pipeline.collect_from_rss_feed(
'https://www.cert.ssi.gouv.fr/avis/feed/',
'CERT-FR'
)
print(f"Collecté: {len(certfr_iocs)} IOC depuis CERT-FR")
# Déduplication
unique_iocs = pipeline.deduplicate(certfr_iocs)
print(f"Après déduplication: {len(unique_iocs)} IOC uniques")
# Scoring et push
scored_iocs = [pipeline.score_ioc(ioc) for ioc in unique_iocs]
pipeline.push_to_siem(
[ioc for ioc in scored_iocs if ioc['confidence_score'] > 60],
'https://siem.votre-domaine.fr/api/ioc'
)
Parsing des Alertes CERT-FR — Automatisation Complète
L'ANSSI CERT-FR publie des avis de sécurité réguliers au format RSS. Voici un parser complet qui extrait les IOC, les enrichit et les pousse automatiquement dans MISP :
import feedparser
import re
import requests
from datetime import datetime
from pymisp import PyMISP, MISPEvent, MISPAttribute
MISP_URL = 'https://misp.votre-domaine.fr'
MISP_KEY = 'VOTRE_CLE_MISP'
CERTFR_RSS = 'https://www.cert.ssi.gouv.fr/avis/feed/'
def parse_certfr_alerts():
"""Parse les dernières alertes CERT-FR et extrait les IOC"""
misp = PyMISP(MISP_URL, MISP_KEY, ssl=True)
feed = feedparser.parse(CERTFR_RSS)
# Patterns IOC
ip_re = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b')
cve_re = re.compile(r'CVE-\d{4}-\d{4,7}')
domain_re = re.compile(r'\b(?:[a-z0-9\-]+\.){1,3}(?:com|net|org|fr|ru|cn)\b', re.I)
processed = 0
for entry in feed.entries[:5]: # 5 dernières alertes
# Vérifier si déjà dans MISP
existing = misp.search(
controller='events',
value=entry.link,
type_attribute='url',
pythonify=True
)
if existing:
print(f"Alerte déjà dans MISP: {entry.title}")
continue
# Créer l'événement MISP
event = MISPEvent()
event.info = f"[CERT-FR] {entry.title}"
event.distribution = 1 # This community only
event.threat_level_id = 2 # Medium par défaut
event.analysis = 1 # Ongoing
# Ajouter l'URL source
event.add_attribute('url', entry.link, comment='Source CERT-FR', to_ids=False)
# Extraire le contenu complet (summary HTML)
text = re.sub(r'<[^>]+>', '', entry.get('summary', ''))
# Extraire CVE
for cve in set(cve_re.findall(text)):
event.add_attribute('vulnerability', cve, comment='CVE CERT-FR', to_ids=False)
# Extraire IPs (avec filtre privées)
for ip in set(ip_re.findall(text)):
if not any(ip.startswith(p) for p in ['10.', '192.168.', '127.', '0.']):
event.add_attribute('ip-dst', ip, comment='IP CERT-FR', to_ids=True)
# Sauvegarder dans MISP
result = misp.add_event(event, pythonify=True)
print(f"Événement MISP créé: {result.id} - {entry.title}")
processed += 1
print(f"Total alertes CERT-FR traitées: {processed}")
return processed
if __name__ == '__main__':
parse_certfr_alerts()
Ce script tourne idéalement en cron toutes les heures. En production, ajouter une persistance des entrées déjà traitées (Redis ou SQLite) pour éviter les doublons même si MISP est temporairement indisponible. Notre article sur le forensics cloud AWS/Azure détaille comment utiliser ces IOC dans des investigations cloud.
Comment scorer et classifier les IOC avec TLP et PAP ?
Le TLP (Traffic Light Protocol) est le standard de classification du partage d'information :
- TLP:RED : partage strictement limité aux destinataires nommés — pas de copie, pas de diffusion
- TLP:AMBER : partage limité à l'organisation et ses clients directs
- TLP:AMBER+STRICT : même restriction mais sans les clients
- TLP:GREEN : partage dans la communauté de confiance élargie
- TLP:CLEAR : partage public autorisé
Le PAP (Permissible Actions Protocol) complète TLP en indiquant ce qu'on peut faire avec l'information : PAP:RED (détection passive uniquement), PAP:AMBER (blocage actif autorisé), PAP:GREEN (hunting actif autorisé), PAP:WHITE (tout autorisé).
En pratique, les IOC CERT-FR sont généralement TLP:CLEAR/PAP:GREEN — partageables et utilisables pour le blocage actif. Les IOC issus de partenariats sectoriels (ex: ISAC) sont souvent TLP:AMBER — ne pas les pousser dans des systèmes de partage public.
Intégration SIEM — Push vers Microsoft Sentinel et Wazuh
Une fois les IOC enrichis et scorés, ils doivent alimenter les SIEM et les défenses actives. Pour Microsoft Sentinel via l'API Log Analytics :
import requests
import json
import datetime
import hashlib
import hmac
import base64
def push_iocs_to_sentinel(workspace_id: str, workspace_key: str, iocs: list):
"""Push IOC vers Microsoft Sentinel Log Analytics"""
log_type = 'ThreatIntelligenceIndicator'
# Formatter les IOC au format Sentinel
records = []
for ioc in iocs:
records.append({
'TimeGenerated': datetime.datetime.utcnow().isoformat() + 'Z',
'IndicatorType': ioc.get('type', 'unknown'),
'IndicatorValue': ioc['value'],
'ThreatType': ioc.get('threat_type', 'Malware'),
'ConfidenceScore': ioc.get('confidence_score', 50),
'TLPLevel': ioc.get('tlp', 'AMBER'),
'Source': ioc.get('source', 'Internal-TI'),
'IsActive': True
})
body = json.dumps(records)
content_length = len(body)
rfc1123date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
string_to_hash = f"POST\n{content_length}\napplication/json\nx-ms-date:{rfc1123date}\n/api/logs"
bytes_to_hash = string_to_hash.encode('utf-8')
decoded_key = base64.b64decode(workspace_key)
encoded_hash = base64.b64encode(
hmac.new(decoded_key, bytes_to_hash, digestmod=hashlib.sha256).digest()
).decode('utf-8')
signature = f"SharedKey {workspace_id}:{encoded_hash}"
url = f"https://{workspace_id}.ods.opinsights.azure.com/api/logs?api-version=2016-04-01"
response = requests.post(
url,
data=body,
headers={
'content-type': 'application/json',
'Authorization': signature,
'Log-Type': log_type,
'x-ms-date': rfc1123date,
}
)
print(f"Sentinel push: HTTP {response.status_code} - {len(records)} IOC envoyés")
return response.status_code == 200
Pour les environnements on-premise, Wazuh active response peut bloquer automatiquement les IPs malveillantes basé sur les IOC MISP. L'intégration se fait via le connector Wazuh-MISP disponible dans la marketplace Wazuh. Notre article sur l'OSINT 2026 et les outils de reconnaissance couvre les sources OSINT complémentaires à intégrer dans votre pipeline TI.
Plateformes CTI — Tableau Comparatif 2026
| Plateforme | Type | Open Source | Points forts | Limites | Coût |
|---|---|---|---|---|---|
| MISP | Partage TI | Oui | Communauté massive, feeds gratuits, API riche | UI vieillissante, recherche limitée | Gratuit |
| OpenCTI | Analyse CTI | Oui | Graphe de connaissances, STIX natif, modern UI | Lourd à déployer, ressources importantes | Gratuit (EE payant) |
| Anomali ThreatStream | TIP commercial | Non | Feeds premium, Machine Learning, intégrations SIEM | Coût élevé, dépendance vendeur | 50k-200k$/an |
| ThreatConnect | TIP + SOAR | Non | Playbooks intégrés, scoring automatique | Complexité, courbe d'apprentissage | 30k-150k$/an |
| Mandiant Advantage | TI premium | Non | Intelligence stratégique APT, attribution | Prix très élevé, sur-calibré pour PME | 100k+$/an |
Pour la plupart des SOC de taille intermédiaire, la combinaison MISP + OpenCTI + TheHive/Cortex couvre 90% des besoins à coût quasi-nul (hors infrastructure et temps humain).
Questions fréquentes
Quelle différence entre threat intelligence et threat hunting ?
La threat intelligence est la collecte et l'analyse de renseignements sur les menaces potentielles — elle répond à "qui nous menace et comment". Le threat hunting est la recherche proactive d'attaquants déjà dans le réseau en utilisant ces renseignements comme hypothèses de départ. La TI alimente le hunting : les IOC et TTPs détectés deviennent des hypothèses à tester dans les logs SIEM. Sans TI solide, le hunting est aveugle.
MISP ou OpenCTI — lequel choisir en premier ?
Commencer par MISP : l'écosystème de feeds et la communauté sont imbattables, l'installation est plus simple, et les intégrations avec les outils de sécurité (Suricata, TheHive, Wazuh) sont matures. Ajouter OpenCTI une fois que MISP est opérationnel, pour la couche d'analyse et de visualisation des relations. Les deux se complètent plutôt qu'ils ne se concurrencent.
Comment gérer les faux positifs dans un pipeline TI automatisé ?
Les faux positifs sont le cancer des pipelines TI non maîtrisés. Les bonnes pratiques : appliquer un score de confiance minimum (70+) avant de bloquer automatiquement, maintenir une allowlist d'IPs légitimes connues (CDN, DNS publics, fournisseurs SaaS), implémenter un mécanisme de "sighting" pour décroître le score des IOC qui ne déclenchent jamais d'alerte, et réviser manuellement la liste des règles IDS actives tous les 30 jours.
Quel volume d'IOC un SOC peut-il réalistement traiter ?
Un flux OSINT non filtré peut générer des millions d'IOC par jour — impossible à utiliser directement. La règle d'or : filtrer à l'entrée par qualité de source (score de confiance source), déduire aggressivement, et ne pousser vers les défenses actives que les IOC avec confidence score > 70 et activité < 30 jours. Un SOC mature de taille moyenne gère 50 000 à 200 000 IOC actifs dans son SIEM.
Comment automatiser la veille sur les nouvelles CVE liées à votre stack ?
L'approche en trois couches : feeds NVD et CERT-FR filtrés par mots-clés (noms de vos produits, vendors), alertes GitHub Security Advisory pour vos dépendances open source, et monitoring OSV (Open Source Vulnerabilities) pour les packages npm/pip/Maven. Ces trois sources alimentent directement MISP avec tags produits, permettant de prioriser par pertinence plutôt que par CVSS brut.
Conclusion
Un pipeline de threat intelligence automatisé n'est pas un luxe réservé aux grands groupes — c'est une nécessité opérationnelle pour tout SOC qui veut traiter des menaces réelles plutôt que de se noyer dans le bruit. La combinaison MITRE ATT&CK pour les TTPs, MISP pour le partage communautaire, OpenCTI pour l'analyse, et TheHive pour la réponse couvre un spectre complet à coût maîtrisé. La valeur différentielle n'est pas dans les outils — c'est dans la qualité du pipeline : sources fiables, déduplication rigoureuse, enrichissement pertinent, et surtout intégration réelle dans les processus de réponse. Un IOC dans MISP qui n'est jamais poussé vers un SIEM ou un firewall ne protège personne.
Vous souhaitez mettre en place un pipeline de threat intelligence automatisé ? Nos consultants SOC accompagnent les équipes dans le déploiement de MISP, OpenCTI et l'automatisation des flux de menaces — de l'architecture à l'intégration SIEM. Contactez-nous pour un audit de votre maturité TI.
Télécharger cet article en PDF
Format A4 optimisé pour l'impression et la lecture hors ligne
À propos de l'auteur
Ayi NEDJIMI
Auditeur Senior Cybersécurité & Consultant IA
Expert Judiciaire — Cour d'Appel de Paris
Habilitation Confidentiel Défense
[email protected]
Ayi NEDJIMI est un vétéran de la cybersécurité avec plus de 25 ans d'expérience sur des missions critiques. Ancien développeur Microsoft à Redmond sur le module GINA (Windows NT4) et co-auteur de la version française du guide de sécurité Windows NT4 pour la NSA.
À la tête d'Ayi NEDJIMI Consultants, il réalise des audits Lead Auditor ISO 42001 et ISO 27001, des pentests d'infrastructures critiques, du forensics et des missions de conformité NIS2 / AI Act.
Conférencier international (Europe & US), il a formé plus de 10 000 professionnels.
Domaines d'expertise
Ressources & Outils de l'auteur
Testez vos connaissances
Mini-quiz de certification lié à cet article — propulsé par CertifExpress
Articles connexes
Un projet cybersécurité ? Parlons-en.
Pentest, conformité NIS 2, ISO 27001, audit IA, RSSI externalisé… nos experts répondent sous 24h pour évaluer votre besoin et vous proposer un accompagnement sur mesure.
Commentaires
Aucun commentaire pour le moment. Soyez le premier à commenter !
Laisser un commentaire