Communitygithub.com

建置 IOC 去活化與分享管道

建立自動化管線,從多個來源擷取原始 IOC(URL、IP、網域),進行正規化、去重、去活化(defanging),並轉換為 STIX 2.1 格式,透過 TAXII、MISP 及電子郵件報告進行安全分享。

建置 IOC 去活化與分享管道 是什麼?

此技能指導使用者建置一個端到端的自動化 IOC(威脅指標)處理與分享管道。它能從任意文字中提取 URL、IP 位址、網域名稱、電子郵件及檔案雜湊值,並自動進行去活化(例如將 `http://` 轉為 `hxxp://`、`.` 轉為 `[.]`),以防止誤觸或執行惡意連結。 管道包含四個階段:步驟一為從文字中提取 IOC 並正規化(去重、白名單過濾);步驟二為產生適合人類閱讀的去活化報告;步驟三(選擇性)將 IOC 轉換為 STIX 2.1 標準格式,便於機器自動化處理;步驟四將結果推送到 MISP 事件平台或 TAXII 2.1 伺服器進行共享。 此技能適用於部署或設定 IOC 分享管線、建立符合合規需求的安全控管、以及改善威脅情資分析架構。支援 Python 3.9+ 環境,依賴 `defang`、`ioc-fanger`、`stix2`、`requests` 等函式庫,並需具備 MISP 或 TAXII 伺服器用於自動化分享。

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

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

建置 IOC 去活化與分享管道 是做什麼的?

概述

IOC 去活化(defanging)可修改潛在的惡意指標(URL、IP 位址、網域、電子郵件地址),以防止意外點擊或執行,同時保留可讀性,便於分析與分享。此技能涵蓋建置自動化管線,從多個來源擷取原始 IOC、進行正規化與去重、套用去活化以安全地供人類閱讀、轉換為 STIX 2.1 格式以利機器讀取,並透過 TAXII 伺服器、MISP 實例與電子郵件報告進行分發。

使用時機

  • 當需要在您的環境中部署或設定 IOC 去活化與分享管線功能時
  • 當建立符合合規要求的安全控管時
  • 當為此領域建置或改善安全架構時
  • 當進行需要此實作的安全評估時

先決條件

  • Python 3.9+ 並安裝 defang、ioc-fanger、stix2、requests、validators 函式庫
  • 用於自動化分享的 MISP 實例或 TAXII 伺服器
  • 了解 IOC 類型:IPv4/IPv6、網域、URL、電子郵件地址、檔案雜湊
  • 熟悉 STIX 2.1 Indicator 模式與 TLP 標記定義
  • 可存取威脅情資來源以擷取 IOC

關鍵概念

IOC 去活化標準

去活化會取代活動中的協定與網域元件,以防止執行:http:// 變成 hxxp://,https:// 變成 hxxps://,網域/IP 中的點號變成 [.],電子郵件中的 @ 變成 [@]。這對於在報告、電子郵件、Slack 頻道以及貼文網站中分享 IOC 至關重要,因為自動連結可能觸發與惡意基礎設施的網路連線。

IOC 正規化

不同來源的原始 IOC 格式不一致。正規化包括轉換為小寫、移除尾部斜線與空白、從 URL 中提取網域、解析 URL 編碼、驗證格式正確性,以及跨來源去重。

STIX 2.1 Indicator 模式

STIX 模式以標準化格式表達 IOC:[ipv4-addr:value = '203.0.113.1']、[domain-name:value = 'malicious.example.com']、[url:value = 'http://evil.com/payload']、[file:hashes.'SHA-256' = 'abc123...']。每個 Indicator 包含 valid_from、indicator_types、confidence 以及可選的 TLP 標記。

工作流程

步驟 1:建置 IOC 提取與正規化

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

class IOCExtractor:
    """從文字中提取並正規化 IOC。"""

    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):
        """從自由文字中提取所有 IOC 類型。"""
        # 先對任何已去活化的指標進行復原
        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)

        # 移除屬於 URL 一部分的網域
        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"[+] 從文字中提取了 {total} 個唯一 IOC")
        return {k: sorted(v) for k, v in iocs.items()}

    def _refang(self, text):
        """將去活化的指標轉換回作用形式。"""
        text = text.replace("hxxp://", "http://").replace("hxxps://", "https://")
        text = text.replace("[.]", ".").replace("[@]", "@")
        text = text.replace("[://]", "://").replace("(.)", ".")
        return text

    def _normalize(self, value, ioc_type):
        """正規化 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):
        """檢查 IOC 是否在白名單中。"""
        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:hxxps://evil-domain[.]com/beacon
從 192.168.1.100 下載惡意載入,並聯絡 10[.]0[.]0[.]1
SHA256:275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
來自 attacker[@]phishing-domain[.]com 的釣魚郵件
"""
iocs = extractor.extract_from_text(sample_text)

步驟 2:去活化引擎

class IOCDefanger:
    """將 IOC 去活化,以便在報告與通訊中安全分享。"""

    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):
        """將字典中的所有 IOC 去活化。"""
        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  # 雜湊不需要去活化
        return defanged

    def generate_sharing_report(self, iocs, defanged, report_name="IOC 報告"):
        """產生人類可讀的去活化 IOC 報告。"""
        report = f"# {report_name}\n"
        report += f"產生時間:{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")
print(report)

步驟 3:轉換為 STIX 2.1 格式

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

class STIXConverter:
    """將原始 IOC 轉換為 STIX 2.1 Indicator 物件。"""

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

    def iocs_to_stix(self, iocs, tlp="green", confidence=75):
        """將 IOC 字典轉換為 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:{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"惡意網域:{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:{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"惡意檔案雜湊:{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"[+] 已建立包含 {len(stix_objects)} 個 Indicator 的 STIX 套件")
        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))

步驟 4:透過 MISP 和 TAXII 分發

import requests
import json

class IOCDistributor:
    """透過多種管道分發 IOC。"""

    def push_to_misp(self, iocs, misp_url, misp_key, event_info):
        """將 IOC 以新事件形式推送到 MISP。"""
        headers = {
            "Authorization": misp_key,
            "Content-Type": "application/json",
            "Accept": "application/json",
        }
        event = {
            "Event": {
                "info": event_info,
                "distribution": "1",  # 僅限此社群
                "threat_level_id": "2",  # 中
                "analysis": "2",  # 已完成
                "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": "Network activity" if ioc_type in ("ipv4", "domain", "url") else "Payload delivery",
                        "to_ids": True,
                    })

        resp = requests.post(
            f"{misp_url}/events",
            headers=headers,
            json=event,
            verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true",  # 在實驗室環境中使用自簽憑證時,設定 SKIP_TLS_VERIFY=true 以跳過 TLS 驗證
        )
        if resp.status_code == 200:
            event_id = resp.json().get("Event", {}).get("id", "")
            print(f"[+] MISP 事件已建立:{event_id}")
            return event_id
        else:
            print(f"[-] MISP 錯誤:{resp.status_code} - {resp.text[:200]}")
            return None

    def push_to_taxii(self, stix_bundle, taxii_url, collection_id, username, password):
        """將 STIX 套件推送到 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:已發布套件,狀態:{response.status}")
        return response

distributor = IOCDistributor()
distributor.push_to_misp(
    iocs,
    misp_url="https://misp.organization.com",
    misp_key="YOUR_MISP_API_KEY",
    event_info="惡意軟體活動 IOC - 2025",
)

驗證標準

  • 從自由文字中正確提取 IOC,並支援復原(refanging)
  • 去活化產生安全、不可點擊的指標
  • STIX 2.1 套件包含有效的 Indicator 模式
  • IOC 成功分發至 MISP 和 TAXII
  • 去重功能防止重複的 Indicator
  • 白名單功能防止已知良好網域產生誤報

參考資料

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,

相關技能