Communitygithub.com

construction-d-un-pipeline-de-defanging-et-partage-d-ioc

Construisez un pipeline automatisé qui ingère des IOC brutes (URLs, IPs, domaines, hachages de fichiers), les normalise, les désactive (defang) pour un partage sécurisé, les convertit au format STIX 2.1 et les distribue via MISP, TAXII et rapports email.

Qu'est-ce que construction-d-un-pipeline-de-defanging-et-partage-d-ioc ?

Cette compétence vous guide dans la construction d'un pipeline complet pour la gestion des Indicateurs de Compromission (IOC). Elle permet d'ingérer des IOC depuis des sources texte brutes, de les normaliser et dédupliquer, puis de les désactiver (defanging) afin d'éviter tout clic accidentel lors du partage (en transformant `http://` en `hxxp://` et `.` en `[.]` par exemple). Les indicateurs sont ensuite convertis en format STIX 2.1 standardisé, compatible avec les plateformes de Threat Intelligence. Enfin, le pipeline distribue les IOC via MISP (création d'événements) et TAXII 2.1 (publication de bundles), tout en générant des rapports lisibles. La compétence couvre l'extraction par expressions régulières, la normalisation (minuscules, décodage URL, suppression de slashes), la déduplication, la liste blanche de domaines légitimes, et la gestion des marquages TLP. Elle s'appuie sur Python 3.9+ avec les bibliothèques `defang`, `ioc-fanger`, `stix2`, `requests`, `validators` et nécessite une instance MISP ou un serveur TAXII pour le partage automatisé.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mukul975/Anthropic-Cybersecurity-Skills/tree/main/skills/building-ioc-defanging-and-sharing-pipeline

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Construction d'un pipeline de défanging et de partage d'IOC

Aperçu

Le défanging d'IOC modifie les indicateurs potentiellement malveillants (URLs, adresses IP, domaines, adresses email) pour éviter les clics ou exécutions accidentels, tout en préservant leur lisibilité pour l'analyse et le partage. Cette compétence couvre la construction d'un pipeline automatisé qui ingère des IOC brutes provenant de multiples sources, les normalise et les déduplique, applique un défanging pour une consommation humaine sécurisée, les convertit au format STIX 2.1 pour une consommation machine, et les distribue via des serveurs TAXII, des instances MISP et des rapports email.

Quand l'utiliser

  • Lors du déploiement ou de la configuration de capacités de pipeline de défanging et de partage d'IOC dans votre environnement
  • Lors de l'établissement de contrôles de sécurité alignés sur les exigences de conformité
  • Lors de la construction ou de l'amélioration d'une 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 defang, ioc-fanger, stix2, requests, validators
  • Instance MISP ou serveur TAXII pour le partage automatisé
  • Compréhension des types d'IOC : IPv4/IPv6, domaines, URLs, adresses email, hachages de fichiers
  • Familiarité avec les motifs d'indicateurs STIX 2.1 et les définitions de marquage TLP
  • Accès à des flux de renseignement sur les menaces pour l'ingestion d'IOC

Concepts clés

Normes de défanging d'IOC

Le défanging remplace les composants actifs de protocole et de domaine pour empêcher toute exécution : http:// devient hxxp://, https:// devient hxxps://, les points dans les domaines/IP deviennent [.], @ dans les emails devient [@]. C'est essentiel pour partager des IOC dans des rapports, emails, canaux Slack et sites de partage où l'auto-liaison pourrait déclencher des connexions réseau vers une infrastructure malveillante.

Normalisation des IOC

Les IOC brutes provenant de différentes sources arrivent dans des formats inconsistants. La normalisation consiste à convertir en minuscules, supprimer les slashes et espaces de fin, extraire les domaines des URLs, résoudre l'encodage URL, valider la correction du format et dédupliquer entre les sources.

Motifs d'indicateurs STIX 2.1

Les motifs STIX expriment les IOC dans un format standardisé : [ipv4-addr:value = '203.0.113.1'], [domain-name:value = 'malicious.example.com'], [url:value = 'http://evil.com/payload'], [file:hashes.'SHA-256' = 'abc123...']. Chaque indicateur inclut valid_from, indicator_types, confidence et des marquages TLP optionnels.

Workflow

Étape 1 : Construire l'extraction et la normalisation des IOC

import re
import hashlib
from urllib.parse import urlparse, unquote
from datetime import datetime

class IOCExtractor:
    """Extraire et normaliser les IOC à partir de texte."""

    PATTERNS = {
        "ipv4": r'\b(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\b',
        "domain": r'\b(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}\b',
        "url": r'https?://[^\s<>"{}|\\^`\[\]]+',
        "email": r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
        "md5": r'\b[a-fA-F0-9]{32}\b',
        "sha1": r'\b[a-fA-F0-9]{40}\b',
        "sha256": r'\b[a-fA-F0-9]{64}\b',
    }

    WHITELIST_DOMAINS = {
        "google.com", "microsoft.com", "amazon.com", "github.com",
        "cloudflare.com", "akamai.com", "example.com",
    }

    def extract_from_text(self, text):
        """Extraire tous les types d'IOC d'un texte libre."""
        # Désactiver le défanging des indicateurs déjà défangés en premier
        text = self._refang(text)
        iocs = {"ipv4": set(), "domain": set(), "url": set(),
                "email": set(), "md5": set(), "sha1": set(), "sha256": set()}

        for ioc_type, pattern in self.PATTERNS.items():
            matches = re.findall(pattern, text)
            for match in matches:
                normalized = self._normalize(match, ioc_type)
                if normalized and not self._is_whitelisted(normalized, ioc_type):
                    iocs[ioc_type].add(normalized)

        # Supprimer les domaines qui font partie d'URLs
        url_domains = set()
        for url in iocs["url"]:
            parsed = urlparse(url)
            url_domains.add(parsed.netloc)
        iocs["domain"] -= url_domains

        total = sum(len(v) for v in iocs.values())
        print(f"[+] Extrait {total} IOC uniques du texte")
        return {k: sorted(v) for k, v in iocs.items()}

    def _refang(self, text):
        """Convertir les indicateurs défangés en forme active."""
        text = text.replace("hxxp://", "http://").replace("hxxps://", "https://")
        text = text.replace("[.]", ".").replace("[@]", "@")
        text = text.replace("[:]", ":").replace("[://]", "://").replace("(.)", ".")
        return text

    def _normalize(self, value, ioc_type):
        """Normaliser une valeur d'IOC."""
        value = value.strip().lower()
        if ioc_type == "url":
            value = unquote(value).rstrip("/")
        elif ioc_type == "domain":
            value = value.rstrip(".")
        return value

    def _is_whitelisted(self, value, ioc_type):
        """Vérifier si l'IOC est dans la liste blanche."""
        if ioc_type == "domain":
            return value in self.WHITELIST_DOMAINS
        if ioc_type == "url":
            parsed = urlparse(value)
            return parsed.netloc in self.WHITELIST_DOMAINS
        return False

extractor = IOCExtractor()
sample_text = """
C2 du malware : hxxps://evil-domain[.]com/beacon
Livre la charge utile depuis 192.168.1.100 et contacte 10[.]0[.]0[.]1
SHA256 : 275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
Email de phishing depuis attacker[@]phishing-domain[.]com
"""
iocs = extractor.extract_from_text(sample_text)

Étape 2 : Moteur de défanging

class IOCDefanger:
    """Défanger les IOC pour un partage sécurisé dans les rapports et communications."""

    def defang_url(self, url):
        return url.replace("http://", "hxxp://").replace("https://", "hxxps://").replace(".", "[.]")

    def defang_domain(self, domain):
        return domain.replace(".", "[.]")

    def defang_ip(self, ip):
        return ip.replace(".", "[.]")

    def defang_email(self, email):
        return email.replace("@", "[@]").replace(".", "[.]")

    def defang_all(self, iocs):
        """Défanger toutes les IOC d'un dictionnaire."""
        defanged = {}
        for ioc_type, values in iocs.items():
            if ioc_type == "url":
                defanged[ioc_type] = [self.defang_url(v) for v in values]
            elif ioc_type == "domain":
                defanged[ioc_type] = [self.defang_domain(v) for v in values]
            elif ioc_type == "ipv4":
                defanged[ioc_type] = [self.defang_ip(v) for v in values]
            elif ioc_type == "email":
                defanged[ioc_type] = [self.defang_email(v) for v in values]
            else:
                defanged[ioc_type] = values  # Les hachages n'ont pas besoin de défanging
        return defanged

    def generate_sharing_report(self, iocs, defanged, report_name="Rapport IOC"):
        """Générer un rapport IOC défangé lisible par un humain."""
        report = f"# {report_name}\n"
        report += f"Généré le : {datetime.now().isoformat()}\n\n"

        for ioc_type in ["url", "domain", "ipv4", "email", "sha256", "sha1", "md5"]:
            values = defanged.get(ioc_type, [])
            if values:
                report += f"## {ioc_type.upper()} ({len(values)})\n"
                for v in values:
                    report += f"- `{v}`\n"
                report += "\n"

        return report

defanger = IOCDefanger()
defanged = defanger.defang_all(iocs)
report = defanger.generate_sharing_report(iocs, defanged, "IOC de campagne de malware")
print(report)

Étape 3 : Conversion au format STIX 2.1

from stix2 import Indicator, Bundle, TLP_WHITE, TLP_GREEN, TLP_AMBER
from datetime import datetime

class STIXConverter:
    """Convertir les IOC brutes en objets Indicator STIX 2.1."""

    TLP_MAP = {"white": TLP_WHITE, "green": TLP_GREEN, "amber": TLP_AMBER}

    def iocs_to_stix(self, iocs, tlp="green", confidence=75):
        """Convertir un dictionnaire d'IOC en bundle STIX 2.1."""
        stix_objects = []
        marking = self.TLP_MAP.get(tlp, TLP_GREEN)

        for ip in iocs.get("ipv4", []):
            stix_objects.append(Indicator(
                name=f"IP malveillante : {ip}",
                pattern=f"[ipv4-addr:value = '{ip}']",
                pattern_type="stix",
                valid_from=datetime.now(),
                indicator_types=["malicious-activity"],
                confidence=confidence,
                object_marking_refs=[marking],
            ))

        for domain in iocs.get("domain", []):
            stix_objects.append(Indicator(
                name=f"Domaine malveillant : {domain}",
                pattern=f"[domain-name:value = '{domain}']",
                pattern_type="stix",
                valid_from=datetime.now(),
                indicator_types=["malicious-activity"],
                confidence=confidence,
                object_marking_refs=[marking],
            ))

        for url in iocs.get("url", []):
            escaped = url.replace("'", "\\'")
            stix_objects.append(Indicator(
                name=f"URL malveillante : {url[:60]}",
                pattern=f"[url:value = '{escaped}']",
                pattern_type="stix",
                valid_from=datetime.now(),
                indicator_types=["malicious-activity"],
                confidence=confidence,
                object_marking_refs=[marking],
            ))

        for sha256 in iocs.get("sha256", []):
            stix_objects.append(Indicator(
                name=f"Hachage de fichier malveillant : {sha256[:16]}...",
                pattern=f"[file:hashes.'SHA-256' = '{sha256}']",
                pattern_type="stix",
                valid_from=datetime.now(),
                indicator_types=["malicious-activity"],
                confidence=confidence,
                object_marking_refs=[marking],
            ))

        bundle = Bundle(objects=stix_objects)
        print(f"[+] Bundle STIX créé avec {len(stix_objects)} indicateurs")
        return bundle

converter = STIXConverter()
stix_bundle = converter.iocs_to_stix(iocs, tlp="amber", confidence=80)
with open("iocs_stix_bundle.json", "w") as f:
    f.write(stix_bundle.serialize(pretty=True))

Étape 4 : Distribution via MISP et TAXII

import requests
import json

class IOCDistributor:
    """Distribuer les IOC via différents canaux."""

    def push_to_misp(self, iocs, misp_url, misp_key, event_info):
        """Pousser les IOC vers MISP sous forme d'un nouvel événement."""
        headers = {
            "Authorization": misp_key,
            "Content-Type": "application/json",
            "Accept": "application/json",
        }
        event = {
            "Event": {
                "info": event_info,
                "distribution": "1",  # Cette communauté uniquement
                "threat_level_id": "2",  # Moyen
                "analysis": "2",  # Terminé
                "Attribute": [],
            }
        }

        type_mapping = {
            "ipv4": "ip-dst",
            "domain": "domain",
            "url": "url",
            "email": "email-src",
            "md5": "md5",
            "sha1": "sha1",
            "sha256": "sha256",
        }

        for ioc_type, values in iocs.items():
            misp_type = type_mapping.get(ioc_type)
            if misp_type:
                for value in values:
                    event["Event"]["Attribute"].append({
                        "type": misp_type,
                        "value": value,
                        "category": "Activité réseau" if ioc_type in ("ipv4", "domain", "url") else "Livraison de charge utile",
                        "to_ids": True,
                    })

        resp = requests.post(
            f"{misp_url}/events",
            headers=headers,
            json=event,
            verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true",  # Définir SKIP_TLS_VERIFY=true pour les certificats auto-signés dans les environnements de laboratoire
        )
        if resp.status_code == 200:
            event_id = resp.json().get("Event", {}).get("id", "")
            print(f"[+] Événement MISP créé : {event_id}")
            return event_id
        else:
            print(f"[-] Erreur MISP : {resp.status_code} - {resp.text[:200]}")
            return None

    def push_to_taxii(self, stix_bundle, taxii_url, collection_id, username, password):
        """Pousser un bundle STIX vers une collection TAXII 2.1."""
        from taxii2client.v21 import Collection
        collection = Collection(
            f"{taxii_url}/collections/{collection_id}/",
            user=username, password=password,
        )
        response = collection.add_objects(stix_bundle.serialize())
        print(f"[+] TAXII : Bundle publié, statut : {response.status}")
        return response

distributor = IOCDistributor()
distributor.push_to_misp(
    iocs,
    misp_url="https://misp.organization.com",
    misp_key="VOTRE_CLE_API_MISP",
    event_info="IOC de campagne de malware - 2025",
)

Critères de validation

  • Les IOC sont extraites correctement d'un texte libre avec prise en charge du refanging
  • Le défanging produit des indicateurs sécurisés, non cliquables
  • Le bundle STIX 2.1 contient des motifs d'indicateurs valides
  • Les IOC sont distribuées avec succès vers MISP et TAXII
  • La déduplication empêche les indicateurs en double
  • La liste blanche évite les faux positifs sur les domaines légitimes connus

Références

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

abusing-dpapi-for-credential-access

Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys) online or offline using SharpDPAPI, SharpChrome, Mimikatz, or Impacket

abusing-shadow-credentials-for-privesc

Take over Active Directory accounts by writing attacker-controlled public keys to msDS-KeyCredentialLink (Shadow Credentials) with pyWhisker, Whisker, or Certipy, then authenticate via PKINIT to recover the target

achieving-cmmc-level-2-compliance

>-

acquiring-disk-image-with-dd-and-dcfldd

Create forensically sound bit-for-bit disk images with dd or dcfldd on a Linux forensic workstation, preserving evidence integrity through hash verification (MD5/SHA) during acquisition. Use when imaging a suspect drive, USB device, or memory card for investigation, preserving volatile disk evidence during incident response, or producing a verified copy for legal or law-enforcement proceedings before any destructive analysis.

analyzing-active-directory-acl-abuse

Detect dangerous ACL misconfigurations in Active Directory using ldap3

analyzing-android-malware-with-apktool

Perform static analysis of Android APK malware using apktool for resource decompilation, jadx for Java source recovery, and androguard for manifest inspection, dangerous permission-combination detection, and identification of obfuscated code, dynamic code loading, and reflection-based API calls. Use to statically triage a suspicious APK without executing it or to build mobile malware detection rules.

analyzing-api-gateway-access-logs

Parses API Gateway access logs (AWS API Gateway, Kong, Nginx) to detect

analyzing-apt-group-with-mitre-navigator

Query ATT&CK data with attackcti, mitreattack-python, and stix2, then build MITRE ATT&CK Navigator layers and multi-layer heatmap overlays mapping one or more APT groups

analyzing-azure-activity-logs-for-threats

Queries Azure Monitor activity logs and sign-in logs via azure-monitor-query

analyzing-bootkit-and-rootkit-samples

Analyzes bootkit and advanced rootkit malware infecting the Master

analyzing-browser-forensics-with-hindsight

Parse Chromium-based browser databases with Hindsight to extract and correlate browsing history, downloads, cookies, cached content, autofill data, saved passwords, and extensions from Chrome, Edge, Brave, Opera, and Vivaldi into a unified timeline (XLSX, JSON, or SQLite output). Use during incident response, insider-threat investigations, or criminal cases when you need to reconstruct a user

analyzing-campaign-attribution-evidence

Systematically evaluate cyber-campaign evidence to attribute an operation to a threat actor, using the Diamond Model and Analysis of Competing Hypotheses (ACH) to weigh infrastructure overlaps, TTP consistency, malware code similarity, and timing/language artifacts into confidence-weighted attribution assessments. Use when an incident investigation needs a defensible attribution confidence level.

analyzing-certificate-transparency-for-phishing

Monitor Certificate Transparency logs using crt.sh and Certstream to

analyzing-cloud-storage-access-patterns

Detect abnormal access in AWS S3, GCS, and Azure Blob Storage by analyzing CloudTrail Data Events, GCS audit logs, and Azure Storage Analytics for after-hours bulk downloads, new-IP access, and API-call spikes (e.g. GetObject) via statistical baselines and time-series anomaly detection. Use when investigating suspected cloud data exfiltration or building related detection rules.

analyzing-cobalt-strike-beacon-configuration

Extract and analyze Cobalt Strike beacon configuration from PE files

analyzing-cobaltstrike-malleable-c2-profiles

Parse and analyze Cobalt Strike Malleable C2 profiles with dissect.cobaltstrike (profiles and beacon-payload configs) and pyMalleableC2 (AST parsing) to extract HTTP/DNS transforms, URIs, headers, sleep/jitter, and injection behavior, then generate network detection signatures. Use when reverse-engineering a captured malleable profile or building detections against Cobalt Strike Beacon traffic.

analyzing-command-and-control-communication

Analyzes malware C2 communication over HTTP, HTTPS, DNS, and custom

analyzing-cyber-kill-chain

Analyzes intrusion activity against the Lockheed Martin Cyber Kill Chain

analyzing-disk-image-with-autopsy

Perform comprehensive forensic analysis of raw (dd), E01, or AFF disk images with Autopsy and The Sleuth Kit, recovering deleted files, examining metadata and embedded artifacts, keyword searching, and building investigation timelines with visual reports. Use for structured analysis of a forensic disk image or when stakeholders need visual reports from evidence.

analyzing-dns-logs-for-exfiltration

Analyzes DNS query logs to detect data exfiltration via DNS tunneling,

Skills associés