mcpField
T
tracking-threat-actor-infrastructure

tracking-threat-actor-infrastructure

github.com/mukul975セキュリティ35.2k102 回インストール8 週間前に更新
リポジトリ

tracking-threat-actor-infrastructure について

脅威アクターが管理するインフラの発見と追跡を支援する脅威インテリジェンス向けスキルです。パッシブ DNS、証明書透明性、スキャンサービス、WHOIS、ネットワークフィンガープリントを用いた関連付け、時系列化、STIX 2.1 オブジェクトへのエクスポートを扱います。

主な機能

  1. 01パッシブ DNS による関連付け
  2. 02証明書透明性ログの監視
  3. 03Shodan と Censys による発見
  4. 04WHOIS とネットワーク指紋の分析
  5. 05インフラの時系列と STIX 2.1 エクスポート

活用シーン

  1. 01既知の C2 IP に関連するドメインの発見
  2. 02証明書記録による不審なドメインの特定
  3. 03インフラの経時変化の追跡

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill tracking-threat-actor-infrastructure

インストール後、Claude Code で/tracking-threat-actor-infrastructureを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

LICENSE
assets/
template.md
references/
api-reference.md
standards.md
workflows.md
scripts/
agent.py
process.py

詳細

脅威アクターのインフラストラクチャの追跡

概要

脅威アクターのインフラストラクチャの追跡では、コマンド&コントロール(C2)サーバー、フィッシングドメイン、エクスプロイトキットのホスト、弾丸防御ホスティング、ステージングサーバーなど、敵対者が管理する資産を監視し、マッピングします。このスキルでは、パッシブ DNS、証明書の透明性ログ、Shodan/Censys によるスキャン、WHOIS 分析、ネットワークフィンガープリンティングを使用して、脅威アクターのインフラストラクチャを発見・追跡し、時間の経過に伴って関連先をたどる方法を扱います。

使用する場面

  • 脅威アクターのインフラストラクチャの追跡が必要なセキュリティ運用を管理する場合
  • セキュリティプログラムの成熟度と運用プロセスを向上させる場合
  • セキュリティチームのワークフローに標準手順を確立する場合
  • 脅威インテリジェンスまたは脆弱性データを運用に統合する場合

前提条件

  • shodan、censys、requests、stix2 ライブラリを含む Python 3.9+
  • API キー:Shodan、Censys、VirusTotal、SecurityTrails、PassiveTotal
  • DNS、TLS/SSL 証明書、IP 割り当て、ASN 構造に関する理解
  • パッシブ DNS と証明書の透明性の概念に関する知識
  • ドメイン登録情報(WHOIS)検索サービスへのアクセス

主な概念

インフラストラクチャのピボット

ピボットとは、既知のインジケーターを使って、関連するインフラストラクチャを発見する手法です。既知の C2 IP アドレスから始める場合、アナリストはパッシブ DNS(ドメインの検索)、逆 WHOIS(関連する登録情報の検索)、SSL 証明書(共通の証明書の検索)、SSH キーのフィンガープリント、HTTP 応答のフィンガープリント、JARM/JA3S ハッシュ、WHOIS 登録者データを利用してピボットできます。

パッシブ DNS

パッシブ DNS データベースには、再帰リゾルバーで観測された DNS クエリと応答のデータが記録されます。これにより、アナリストは過去のドメインと IP の対応関係を調べたり、既知の C2 IP でホストされているドメインを発見したり、高速フラックスやドメイン生成アルゴリズム(DGA)の挙動を特定したりできます。

証明書の透明性

証明書の透明性(CT)ログには、認証局が発行したすべての SSL/TLS 証明書が公開記録されます。CT ログを監視することで、不審なドメインに新しく登録された証明書を把握し、フィッシングサイトや C2 インフラストラクチャが活動を開始する前に特定できます。

ネットワークフィンガープリンティング
  • JARM:アクティブな TLS サーバーのフィンガープリント(TLS ハンドシェイク応答のハッシュ)
  • JA3S:パッシブな TLS サーバーのフィンガープリント(Server Hello のハッシュ)
  • HTTP ヘッダー:サーバーバナー、カスタムヘッダー、応答パターン
  • ファビコンハッシュ:サーバー識別に使用する HTTP ファビコンのハッシュ

ワークフロー

ステップ 1:Shodan によるインフラストラクチャの発見
import shodan

api = shodan.Shodan("YOUR_SHODAN_API_KEY")

def discover_infrastructure(ip_address):
    """Discover services and metadata for a target IP."""
    try:
        host = api.host(ip_address)
        return {
            "ip": host["ip_str"],
            "org": host.get("org", ""),
            "asn": host.get("asn", ""),
            "isp": host.get("isp", ""),
            "country": host.get("country_name", ""),
            "city": host.get("city", ""),
            "os": host.get("os"),
            "ports": host.get("ports", []),
            "vulns": host.get("vulns", []),
            "hostnames": host.get("hostnames", []),
            "domains": host.get("domains", []),
            "tags": host.get("tags", []),
            "services": [
                {
                    "port": svc.get("port"),
                    "transport": svc.get("transport"),
                    "product": svc.get("product", ""),
                    "version": svc.get("version", ""),
                    "ssl_cert": svc.get("ssl", {}).get("cert", {}).get("subject", {}),
                    "jarm": svc.get("ssl", {}).get("jarm", ""),
                }
                for svc in host.get("data", [])
            ],
        }
    except shodan.APIError as e:
        print(f"[-] Shodan error: {e}")
        return None

def search_c2_framework(framework_name):
    """Search Shodan for known C2 framework signatures."""
    c2_queries = {
        "cobalt-strike": 'product:"Cobalt Strike Beacon"',
        "metasploit": 'product:"Metasploit"',
        "covenant": 'http.html:"Covenant" http.title:"Covenant"',
        "sliver": 'ssl.cert.subject.cn:"multiplayer" ssl.cert.issuer.cn:"operators"',
        "havoc": 'http.html_hash:-1472705893',
    }

    query = c2_queries.get(framework_name.lower(), framework_name)
    results = api.search(query, limit=100)

    hosts = []
    for match in results.get("matches", []):
        hosts.append({
            "ip": match["ip_str"],
            "port": match["port"],
            "org": match.get("org", ""),
            "country": match.get("location", {}).get("country_name", ""),
            "asn": match.get("asn", ""),
            "timestamp": match.get("timestamp", ""),
        })

    return hosts
ステップ 2:パッシブ DNS によるピボット
import requests

def passive_dns_lookup(indicator, api_key, indicator_type="ip"):
    """Query SecurityTrails for passive DNS records."""
    base_url = "https://api.securitytrails.com/v1"
    headers = {"APIKEY": api_key, "Accept": "application/json"}

    if indicator_type == "ip":
        url = f"{base_url}/search/list"
        payload = {
            "filter": {"ipv4": indicator}
        }
        resp = requests.post(url, json=payload, headers=headers, timeout=30)
    else:
        url = f"{base_url}/domain/{indicator}/subdomains"
        resp = requests.get(url, headers=headers, timeout=30)

    if resp.status_code == 200:
        return resp.json()
    return None


def query_passive_total(indicator, user, api_key):
    """Query PassiveTotal for passive DNS and WHOIS data."""
    base_url = "https://api.passivetotal.org/v2"
    auth = (user, api_key)

    # Passive DNS
    pdns_resp = requests.get(
        f"{base_url}/dns/passive",
        params={"query": indicator},
        auth=auth,
        timeout=30,
    )

    # WHOIS
    whois_resp = requests.get(
        f"{base_url}/whois",
        params={"query": indicator},
        auth=auth,
        timeout=30,
    )

    results = {}
    if pdns_resp.status_code == 200:
        results["passive_dns"] = pdns_resp.json().get("results", [])
    if whois_resp.status_code == 200:
        results["whois"] = whois_resp.json()

    return results
ステップ 3:証明書の透明性の監視
import requests

def search_ct_logs(domain):
    """Search Certificate Transparency logs via crt.sh."""
    resp = requests.get(
        f"https://crt.sh/?q=%.{domain}&output=json",
        timeout=30,
    )

    if resp.status_code == 200:
        certs = resp.json()
        unique_domains = set()
        cert_info = []

        for cert in certs:
            name_value = cert.get("name_value", "")
            for name in name_value.split("\n"):
                unique_domains.add(name.strip())

            cert_info.append({
                "id": cert.get("id"),
                "issuer": cert.get("issuer_name", ""),
                "common_name": cert.get("common_name", ""),
                "name_value": name_value,
                "not_before": cert.get("not_before", ""),
                "not_after": cert.get("not_after", ""),
                "serial_number": cert.get("serial_number", ""),
            })

        return {
            "domain": domain,
            "total_certificates": len(certs),
            "unique_domains": sorted(unique_domains),
            "certificates": cert_info[:50],
        }
    return None


def monitor_new_certs(domains, interval_hours=1):
    """Monitor for newly issued certificates for a list of domains."""
    from datetime import datetime, timedelta

    cutoff = (datetime.utcnow() - timedelta(hours=interval_hours)).isoformat()
    new_certs = []

    for domain in domains:
        result = search_ct_logs(domain)
        if result:
            for cert in result.get("certificates", []):
                if cert.get("not_before", "") > cutoff:
                    new_certs.append({
                        "domain": domain,
                        "cert": cert,
                    })

    return new_certs
ステップ 4:インフラストラクチャの相関付けとタイムライン
from datetime import datetime

def build_infrastructure_timeline(indicators):
    """Build a timeline of infrastructure changes."""
    timeline = []

    for ind in indicators:
        if "passive_dns" in ind:
            for record in ind["passive_dns"]:
                timeline.append({
                    "timestamp": record.get("firstSeen", ""),
                    "event": "dns_resolution",
                    "source": record.get("resolve", ""),
                    "target": record.get("value", ""),
                    "record_type": record.get("recordType", ""),
                })

        if "certificates" in ind:
            for cert in ind["certificates"]:
                timeline.append({
                    "timestamp": cert.get("not_before", ""),
                    "event": "certificate_issued",
                    "domain": cert.get("common_name", ""),
                    "issuer": cert.get("issuer", ""),
                })

    timeline.sort(key=lambda x: x.get("timestamp", ""))
    return timeline

検証基準

  • Shodan/Censys のクエリで、対象 IP のインフラストラクチャの詳細が返される
  • パッシブ DNS から過去のドメインと IP の対応関係が明らかになる
  • 証明書の透明性検索で、関連ドメインが見つかる
  • インフラストラクチャのピボットによって、新たな関連インジケーターが発見される
  • インフラストラクチャの経時的な変化がタイムラインに示される
  • 結果を STIX 2.1 の Infrastructure オブジェクトとしてエクスポートできる

参考資料

コメント