Ingénierie de détection

Partager du renseignement avec STIX et TAXII

Le modèle d'objets et les patterns STIX 2.1, un bundle complet, les collections TAXII 2.1 avec curl et les marquages TLP 2.0.

1 Introduction

Le renseignement sur la menace n'est utile que s'il atteint les outils capables d'agir dessus. Recopier à la main des IOC d'un PDF vers un pare-feu est lent, source d'erreurs, et fait perdre tout le contexte : qui est derrière l'activité, quel malware, quel niveau de confiance accorder à la source, qui a le droit de le voir. Deux standards ouverts de l'OASIS règlent ce problème :

STIX 2.1 — la langue

Structured Threat Information Expression : un format JSON pour décrire acteurs, malwares, techniques, indicateurs, observations et les relations entre eux, sous forme de graphe.

TAXII 2.1 — le transport

Trusted Automated Exchange of Intelligence Information : une API REST sur HTTPS pour publier et récupérer du contenu STIX sur des serveurs, organisé en collections.

Pour faire simple : STIX est la lettre (avec une structure standard que tout destinataire sait lire), TAXII est la Poste. Tous deux sont devenus des standards OASIS en version 2.1 en 2021, et ce sont eux qui se cachent derrière la plupart des « flux TAXII » proposés par les ISAC, les CERT, les éditeurs et des plateformes comme MISP ou OpenCTI.

STIX 1.x (XML) et TAXII 1.x sont obsolètes et incompatibles avec la version 2. Si un partenaire vous envoie encore du XML, il vous faudra un convertisseur.

2 Modèle d'objets

En STIX, tout est un objet JSON doté d'un type et d'un id unique de la forme type--UUID, par exemple malware--481ba5c9-2b13-47e5-87d7-c2464ade08ec. Les objets se répartissent en trois grandes familles.

SDO — STIX Domain Objects (les « noms » de la CTI)

STIX 2.1 définit 18 SDO. Ceux que vous croiserez tous les jours :

Type Décrit Obligatoire (en plus des propriétés communes)
indicatorUn motif de détection d'activité suspectepattern, pattern_type, valid_from
malwareUne famille de malware ou un échantillon précisis_family (+ name si famille)
threat-actorDes individus ou groupes aux intentions malveillantesname
intrusion-setUn ensemble d'activités attribué à un même acteur (souvent inconnu), par ex. « APT29 »name
attack-patternUn TTP, en général une technique ATT&CKname
campaignUne série d'attaques sur une période, avec un but communname
vulnerabilityUne faille, généralement référencée par son CVEname
identityUne organisation, une personne ou un secteur (auteurs, victimes)name
reportUn rapport publié qui regroupe d'autres objetsname, published, object_refs

Les autres sont course-of-action, grouping, infrastructure, location, malware-analysis, note, observed-data, opinion et tool. Tout SDO porte les propriétés communes type, spec_version ("2.1"), id, created et modified.

SRO — les relations (les « verbes »)

relationship relie deux objets avec un relationship_type :

  • indicator → indicates → malware
  • threat-actor → uses → malware / attack-pattern
  • campaign → attributed-to → threat-actor
  • malware → targets → identity / vulnerability

sighting signifie « cet indicateur, ce malware ou cet acteur a été vu ici, N fois, entre ces dates ». Les sightings sont le moyen pour les défenseurs de faire un retour aux producteurs.

SCO — les observables (les « faits »)

Des éléments techniques observés sur un système ou un réseau, sans jugement associé :

  • file — hashs, nom, taille
  • ipv4-addr / ipv6-addr — valeur
  • domain-name, url, email-addr
  • process, network-traffic, windows-registry-key, mutex, x509-certificate…

Les SCO n'ont ni created ni modified, et leurs identifiants devraient être des UUIDv5 déterministes calculés à partir de propriétés clés : une même IP obtient toujours le même ID.

Observable ou indicateur ? ipv4-addr 203.0.113.45 est un fait. Un indicator dont le motif correspond à cette IP est une affirmation (« cette IP est malveillante ») avec une période de validité, un niveau de confiance et un auteur. Cette distinction est au cœur de STIX.

3 Langage de patterns

Le pattern d'un indicateur s'écrit dans le STIX Patterning language ("pattern_type": "stix"). Il décrit quels observables doivent être vus pour que l'indicateur corresponde. La brique de base est l'expression de comparaison type-objet:propriété opérateur valeur, placée entre crochets pour former une expression d'observation.

# Un hash SHA-256
[file:hashes.'SHA-256' = '9c165ab24690c682be401bdaafca19fd5124eb9b9f08dd495de87d2e0c80e652']

# Domaine OU IP : deux observations, une seule suffit
[domain-name:value = 'cdn-update.example'] OR [ipv4-addr:value = '203.0.113.45']

# Deux conditions sur le MÊME objet
[file:name = 'upd.dll' AND file:size < 300000]

# Jokers, plages CIDR et expressions régulières
[domain-name:value LIKE '%.cdn-update.example']
[ipv4-addr:value ISSUBSET '203.0.113.0/24']
[process:command_line MATCHES '^powershell.*-enc']

# Séquence + fenêtre de temps : le fichier, puis le domaine, en moins de 5 minutes
([file:hashes.'SHA-256' = 'fb18cd2a74c578b056a81a207cfe4b93d412c707c7f6751c0d4ea32219da4bf2'] FOLLOWEDBY [domain-name:value = 'cdn-update.example']) WITHIN 300 SECONDS

# Répétition : 5 connexions au C2 en 10 minutes
[network-traffic:dst_ref.value = '203.0.113.45' AND network-traffic:dst_port = 443] REPEATS 5 TIMES WITHIN 600 SECONDS
Élément Valeurs
Opérateurs de comparaison= != > < >= <= IN LIKE MATCHES ISSUBSET ISSUPERSET, NOT pour la négation, et EXISTS (préfixe : [EXISTS windows-registry-key:values])
Entre crochetsAND, OR — avec AND, toutes les comparaisons doivent porter sur le même objet
Entre observationsAND, OR, FOLLOWEDBY
QualificateursWITHIN n SECONDS, REPEATS n TIMES, START t'…' STOP t'…'

Le motif n'est pas forcément en STIX. pattern_type peut aussi valoir sigma, yara, snort, suricata ou pcre, ce qui permet de transporter une règle YARA, Sigma ou Suricata dans un indicateur, avec tout son contexte STIX.

4 Bundle complet

Les objets voyagent dans un bundle : une enveloppe avec "type": "bundle", un identifiant et un tableau objects (le bundle n'est pas lui-même un objet STIX et n'a pas de spec_version). Le bundle ci-dessous décrit une campagne de phishing fictive : un acteur, son malware, la technique utilisée, deux indicateurs, les observables, les relations, et un sighting remonté par un SOC. C'est du JSON STIX 2.1 valide.

{
  "type": "bundle",
  "id": "bundle--e558bf9b-eb83-400b-8375-5cc6d2c587e0",
  "objects": [
    {
      "type": "identity",
      "spec_version": "2.1",
      "id": "identity--2ca7f0b5-433d-4e29-9e91-db1d737c4bcb",
      "created": "2026-10-14T09:00:00.000Z",
      "modified": "2026-10-14T09:00:00.000Z",
      "name": "SOC d'exemple (mlab Academy)",
      "identity_class": "organization"
    },
    {
      "type": "marking-definition",
      "spec_version": "2.1",
      "id": "marking-definition--bab4a63c-aed9-4cf5-a766-dfca5abac2bb",
      "created": "2022-10-01T00:00:00.000Z",
      "name": "TLP:GREEN",
      "extensions": {
        "extension-definition--60a3c5c5-0d10-413e-aab3-9e08dde9e88d": {
          "extension_type": "property-extension",
          "tlp_2_0": "green"
        }
      }
    },
    {
      "type": "threat-actor",
      "spec_version": "2.1",
      "id": "threat-actor--ea786151-92a0-45df-a007-f6f8ae65fd23",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "created_by_ref": "identity--2ca7f0b5-433d-4e29-9e91-db1d737c4bcb",
      "name": "Grey Ledger",
      "description": "Acteur fictif à motivation financière, utilisé pour la formation.",
      "threat_actor_types": ["crime-syndicate"],
      "primary_motivation": "personal-gain",
      "object_marking_refs": ["marking-definition--bab4a63c-aed9-4cf5-a766-dfca5abac2bb"]
    },
    {
      "type": "malware",
      "spec_version": "2.1",
      "id": "malware--481ba5c9-2b13-47e5-87d7-c2464ade08ec",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "created_by_ref": "identity--2ca7f0b5-433d-4e29-9e91-db1d737c4bcb",
      "name": "LedgerLoader",
      "is_family": true,
      "malware_types": ["downloader", "backdoor"],
      "object_marking_refs": ["marking-definition--bab4a63c-aed9-4cf5-a766-dfca5abac2bb"]
    },
    {
      "type": "attack-pattern",
      "spec_version": "2.1",
      "id": "attack-pattern--a2b2da60-af37-4e61-b37b-cc0adfd6b0ea",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "name": "Spearphishing Attachment",
      "external_references": [
        {
          "source_name": "mitre-attack",
          "external_id": "T1566.001",
          "url": "https://attack.mitre.org/techniques/T1566/001/"
        }
      ],
      "kill_chain_phases": [
        { "kill_chain_name": "mitre-attack", "phase_name": "initial-access" }
      ]
    },
    {
      "type": "campaign",
      "spec_version": "2.1",
      "id": "campaign--660a8186-7fe0-4645-b44d-2ea1ed3a806a",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "created_by_ref": "identity--2ca7f0b5-433d-4e29-9e91-db1d737c4bcb",
      "name": "Vague de fausses factures - octobre 2026",
      "first_seen": "2026-10-06T00:00:00Z",
      "object_marking_refs": ["marking-definition--bab4a63c-aed9-4cf5-a766-dfca5abac2bb"]
    },
    {
      "type": "indicator",
      "spec_version": "2.1",
      "id": "indicator--18a84965-183d-433e-a90f-79569c6eaf77",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "created_by_ref": "identity--2ca7f0b5-433d-4e29-9e91-db1d737c4bcb",
      "name": "Facture_4471.docm (dropper LedgerLoader)",
      "indicator_types": ["malicious-activity"],
      "pattern": "[file:hashes.'SHA-256' = '9c165ab24690c682be401bdaafca19fd5124eb9b9f08dd495de87d2e0c80e652']",
      "pattern_type": "stix",
      "valid_from": "2026-10-14T09:12:00Z",
      "object_marking_refs": ["marking-definition--bab4a63c-aed9-4cf5-a766-dfca5abac2bb"]
    },
    {
      "type": "indicator",
      "spec_version": "2.1",
      "id": "indicator--11125fd5-ae7d-471a-83f7-9c397123b080",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "created_by_ref": "identity--2ca7f0b5-433d-4e29-9e91-db1d737c4bcb",
      "name": "Serveur de charge utile LedgerLoader",
      "indicator_types": ["malicious-activity"],
      "pattern": "[domain-name:value = 'cdn-update.example'] OR [ipv4-addr:value = '203.0.113.45']",
      "pattern_type": "stix",
      "valid_from": "2026-10-14T09:12:00Z",
      "valid_until": "2026-11-14T09:12:00Z",
      "object_marking_refs": ["marking-definition--bab4a63c-aed9-4cf5-a766-dfca5abac2bb"]
    },
    {
      "type": "domain-name",
      "spec_version": "2.1",
      "id": "domain-name--a584802c-c4fa-5a2d-8623-483171fa04b8",
      "value": "cdn-update.example",
      "resolves_to_refs": ["ipv4-addr--cb9d70c5-d244-531c-9efb-bcae57adc793"]
    },
    {
      "type": "ipv4-addr",
      "spec_version": "2.1",
      "id": "ipv4-addr--cb9d70c5-d244-531c-9efb-bcae57adc793",
      "value": "203.0.113.45"
    },
    {
      "type": "relationship",
      "spec_version": "2.1",
      "id": "relationship--830010b0-0d38-4ea0-87c8-5067c88405f1",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "relationship_type": "indicates",
      "source_ref": "indicator--18a84965-183d-433e-a90f-79569c6eaf77",
      "target_ref": "malware--481ba5c9-2b13-47e5-87d7-c2464ade08ec"
    },
    {
      "type": "relationship",
      "spec_version": "2.1",
      "id": "relationship--4d7b9f9f-a0b0-4729-bd87-4b8545a365ac",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "relationship_type": "uses",
      "source_ref": "threat-actor--ea786151-92a0-45df-a007-f6f8ae65fd23",
      "target_ref": "malware--481ba5c9-2b13-47e5-87d7-c2464ade08ec"
    },
    {
      "type": "relationship",
      "spec_version": "2.1",
      "id": "relationship--58ff3faa-2029-40f9-bf69-03e9905da6ff",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "relationship_type": "uses",
      "source_ref": "campaign--660a8186-7fe0-4645-b44d-2ea1ed3a806a",
      "target_ref": "attack-pattern--a2b2da60-af37-4e61-b37b-cc0adfd6b0ea"
    },
    {
      "type": "relationship",
      "spec_version": "2.1",
      "id": "relationship--11fc53ce-a4f7-47f8-91dc-0a91e714f493",
      "created": "2026-10-14T09:12:00.000Z",
      "modified": "2026-10-14T09:12:00.000Z",
      "relationship_type": "attributed-to",
      "source_ref": "campaign--660a8186-7fe0-4645-b44d-2ea1ed3a806a",
      "target_ref": "threat-actor--ea786151-92a0-45df-a007-f6f8ae65fd23",
      "confidence": 60
    },
    {
      "type": "sighting",
      "spec_version": "2.1",
      "id": "sighting--7c3e9b1a-5d24-4f6e-9a0b-2e8f4c6d1a37",
      "created": "2026-10-15T14:03:00.000Z",
      "modified": "2026-10-15T14:03:00.000Z",
      "created_by_ref": "identity--2ca7f0b5-433d-4e29-9e91-db1d737c4bcb",
      "sighting_of_ref": "indicator--11125fd5-ae7d-471a-83f7-9c397123b080",
      "where_sighted_refs": ["identity--2ca7f0b5-433d-4e29-9e91-db1d737c4bcb"],
      "first_seen": "2026-10-15T13:41:07Z",
      "last_seen": "2026-10-15T13:58:22Z",
      "count": 3
    }
  ]
}

Ce qu'il faut remarquer

1

Identifiants : SDO et SRO utilisent des UUIDv4 aléatoires ; les deux SCO (domain-name, ipv4-addr) utilisent des UUIDv5 dérivés de leur value, si bien qu'un autre producteur qui décrit le même domaine obtient le même ID.

2

Horodatages : en UTC, au format RFC 3339 terminé par Z ; created et modified sont précis à la milliseconde. Pour mettre à jour un objet, on garde son ID et on augmente modified : c'est ainsi que STIX gère les versions.

3

Lien ATT&CK : l'attack-pattern pointe vers T1566.001 via external_references avec source_name: "mitre-attack", la convention que tous les outils comprennent.

4

Durée de vie : l'indicateur réseau a un valid_until un mois plus tard. Une infrastructure est éphémère ; un indicateur de hash peut rester valide bien plus longtemps.

5

Confiance : la relation d'attribution porte "confidence": 60 (échelle de 0 à 100). L'attribution est rarement certaine ; dites-le dans les données.

En production, ne construisez pas vos bundles à la main : des bibliothèques comme le paquet Python stix2 de l'OASIS génèrent identifiants et horodatages et vérifient les propriétés obligatoires.

5 TAXII 2.1

Un serveur TAXII 2.1 expose une API REST réduite et prévisible. Chaque requête doit envoyer l'en-tête Accept: application/taxii+json;version=2.1, et l'authentification se fait généralement en HTTP Basic ou par clé d'API, sur HTTPS.

GET /taxii2/

Discovery : liste les API roots du serveur.

GET {api-root}/collections/

API root : un groupe indépendant de collections (par exemple un par cercle de confiance). Collection : un ensemble nommé d'objets STIX, avec des droits can_read/can_write.

GET {api-root}/collections/{id}/objects/

Objects : renvoie une enveloppe {"more", "next", "objects"}. Filtres : added_after, limit, next, match[type], match[id], match[version], match[spec_version]. Un POST sur la même URL publie des objets (si can_write).

GET {api-root}/collections/{id}/manifest/

Manifest : uniquement les métadonnées (ID, version, date d'ajout), pour voir ce qui a changé avant de télécharger.

En pratique : le serveur TAXII public de MITRE

MITRE publie ATT&CK lui-même en TAXII 2.1, sans authentification : un terrain de jeu idéal. Notez l'option -g (--globoff) : sans elle, curl essaie d'interpréter les crochets de match[type] comme un motif.

# 1. Discovery
curl -s -H 'Accept: application/taxii+json;version=2.1' \
  https://attack-taxii.mitre.org/taxii2/

# 2. Collections de l'API root par défaut
curl -s -H 'Accept: application/taxii+json;version=2.1' \
  https://attack-taxii.mitre.org/api/v21/collections/ | jq -r '.collections[] | "\(.id)  \(.title)"'

# 3. Objets de type intrusion-set (groupes ATT&CK) de la collection Enterprise
curl -g -s -D headers.txt -H 'Accept: application/taxii+json;version=2.1' \
  'https://attack-taxii.mitre.org/api/v21/collections/x-mitre-collection--1f5f1533-f617-4ca8-9ab4-6a02367fa019/objects/?match[type]=intrusion-set&limit=50' \
  | jq -r '.more, .next, (.objects[] | .external_references[0].external_id + "  " + .name)'

Une réponse ressemble à ceci (tronquée) :

{
  "more": true,
  "next": "1",
  "objects": [
    {
      "type": "intrusion-set",
      "spec_version": "2.1",
      "id": "intrusion-set--f29b7c5e-2439-42ad-a86f-9f8984fafae3",
      "created": "2018-10-17T00:14:20.652Z",
      "modified": "2026-07-31T20:48:51.374Z",
      "name": "HEXANE",
      "aliases": [
        "HEXANE",
        "Lyceum",
        "Siamesekitten",
        "Spirlin"
      ],
      "external_references": [
        {
          "source_name": "mitre-attack",
          "url": "https://attack.mitre.org/groups/G1001",
          "external_id": "G1001"
        }
      ]
    },
    {
      "type": "intrusion-set",
      "spec_version": "2.1",
      "id": "intrusion-set--e6db1e55-b199-4b6b-8633-989345ee45e0",
      "created": "2024-08-26T17:39:06.020Z",
      "modified": "2026-07-31T18:48:24.240Z",
      "name": "Moonstone Sleet",
      "aliases": [
        "Moonstone Sleet",
        "Storm-1789"
      ],
      "external_references": [
        {
          "source_name": "mitre-attack",
          "url": "https://attack.mitre.org/groups/G1036",
          "external_id": "G1036"
        }
      ]
    }
  ]
}

Les groupes ATT&CK sont publiés comme intrusion-set et non comme threat-actor : ce sont des ensembles d'activités, pas des identités confirmées. Quand more vaut true, relancez la requête avec next=<valeur> pour obtenir la page suivante. Pour une collecte incrémentale, conservez l'en-tête de réponse X-TAXII-Date-Added-Last et passez-le en added_after la fois suivante. Sur un serveur privé, ajoutez -u "$TAXII_USER:$TAXII_PASS" et gardez les identifiants dans des variables d'environnement, jamais dans les scripts.

6 Marquages TLP

Le Traffic Light Protocol (TLP), maintenu par le FIRST, indique aux destinataires jusqu'où ils peuvent diffuser une information. La version 2.0 (août 2022) a remplacé TLP:WHITE par TLP:CLEAR et ajouté TLP:AMBER+STRICT. En STIX, un marquage est un objet marking-definition référencé dans object_marking_refs. Les marquages TLP 2.0 ont des identifiants fixes publiés par le comité technique CTI de l'OASIS :

Libellé Diffusion autorisée ID du marking-definition STIX
TLP:REDAux seuls destinataires nommés, par exemple les participants à la réunionmarking-definition--e828b379-4e03-4974-9ac4-e53a884c97c1
TLP:AMBER+STRICTÀ l'organisation du destinataire uniquementmarking-definition--939a9414-2ddd-4d32-a0cd-375ea402b003
TLP:AMBERÀ l'organisation du destinataire et à ses clients, selon le besoin d'en connaîtremarking-definition--55d920b0-5e8b-4f79-9ee9-91f868d9b421
TLP:GREENÀ la communauté du destinataire, mais pas publiquementmarking-definition--bab4a63c-aed9-4cf5-a766-dfca5abac2bb
TLP:CLEARÀ tout le monde, publiquement (le droit d'auteur s'applique toujours)marking-definition--94868c89-83c2-464b-929b-a1a8aa3c8487

La spécification STIX 2.1 elle-même ne prédéfinit que les anciens marquages TLP 1.0 (WHITE, GREEN, AMBER, RED). TLP 2.0 est ajouté par une extension-definition, d'où le bloc extensions dans le marquage du bundle ci-dessus. Certains outils ne comprennent encore que TLP 1.0 : vérifiez ce qu'attend votre plateforme.

Le TLP est un contrat social, pas une mesure technique : rien dans STIX n'empêche un destinataire de transférer un objet TLP:RED. Ce sont les plateformes qui l'appliquent, en filtrant ce que chaque utilisateur ou groupe de partage peut voir.

Essayez sur mlab.sh

Avant de transformer un observable en indicateur STIX, vérifiez sa réputation : analysez IP, domaines, URL et hashs de fichiers sur mlab.sh.

Commencer l'analyse sur mlab.sh

7 En pratique

MISP

Plateforme de partage open source, très répandue chez les CERT et les ISAC. Son modèle natif n'est pas STIX : l'information est regroupée en événements contenant des attributs (une IP, un hash), des objets (groupes d'attributs), des tags et taxonomies (dont le TLP) et des galaxies (dont ATT&CK). Les instances MISP se synchronisent directement entre elles, et importent/exportent du STIX 2.1 via la bibliothèque misp-stix. Les conversions sont bonnes mais pas sans perte : vérifiez le résultat.

OpenCTI

Plateforme CTI open source développée par Filigran (à l'origine avec l'ANSSI et le CERT-EU), dont le modèle de données est construit sur STIX 2.1. Tout y est un graphe de SDO, de SCO et de relations. Des connecteurs importent ATT&CK, des événements MISP, des collections TAXII, des données CVE ou des résultats de sandbox, et OpenCTI peut lui-même exposer des collections TAXII et des flux temps réel vers votre SIEM ou votre EDR.

Du flux à la détection

Collecter

Votre TIP interroge régulièrement les collections TAXII et autres flux de threat intel, avec added_after.

Dédoublonner et noter

Le même IOC arrive de plusieurs sources : fusionnez-le, gardez la meilleure confiance, écartez les indicateurs expirés (valid_until).

Pousser vers les contrôles

Les indicateurs partent vers le SIEM (corrélation), l'EDR (blocage de hashs), le proxy/DNS (listes de blocage), dans le respect du TLP.

Faire un retour

Quand un indicateur se déclenche, créez un sighting et partagez-le. Les sightings indiquent aux producteurs quels indicateurs sont réellement utiles.

Des indicateurs sans contexte ni expiration

Un flux d'IP brutes, sans valid_until, sans relation et sans niveau de confiance noiera votre SIEM sous les faux positifs en quelques mois (hébergement mutualisé, IP cloud recyclées).

Du « STIX » qui n'en est pas

spec_version manquant, identifiants qui ne sont pas de la forme type--UUID, horodatages sans Z : passez un validateur (par exemple stix2-validator de l'OASIS) avant de publier.

Modules connexes