analyzing-campaign-attribution-evidence について
SOC 分析者や脅威インテリジェンス調査者向けに、複数の証拠カテゴリからサイバーキャンペーンと候補アクターを比較するスキルです。Diamond Model と ACH を用いて、代替仮説や偽装の可能性を考慮した確信度付き評価を支援します。
主な機能
- 016 種類の帰属証拠を収集
- 02インフラの重複を分析
- 03ATT&CK TTP を比較
- 04ACH で競合仮説を評価
- 05確信度付きレポートを作成
活用シーン
- 01インシデント調査で関与アクターを評価
- 02検知ルールや脅威ハンティングクエリを作成
- 03関連技術の監視範囲を検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill analyzing-campaign-attribution-evidenceインストール後、Claude Code で/analyzing-campaign-attribution-evidenceを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEassets/template.mdreferences/api-reference.mdstandards.mdworkflows.mdscripts/agent.pyprocess.py詳細
キャンペーン帰属の証拠分析
概要
キャンペーン帰属分析では、サイバー作戦の責任者である脅威アクターまたはグループを特定するため、証拠を体系的に評価します。このスキルでは、ダイヤモンドモデルとACH(競合仮説分析)を用いた帰属指標の収集と重み付け、インフラストラクチャの重複、TTPの一貫性、マルウェアコードの類似性、活動タイミングのパターン、言語的特徴の分析を通じて、信頼度を付与した帰属評価を行います。
使用する場面
- キャンペーン帰属の証拠分析が必要なセキュリティインシデントを調査する場合
- この領域の検知ルールや脅威ハンティングクエリを作成する場合
- SOC アナリストがこの種の分析に向けた体系的な手順を必要とする場合
- 関連する攻撃手法に対するセキュリティ監視のカバレッジを検証する場合
前提条件
attackcti、stix2、networkxライブラリを含む Python 3.9+- 脅威インテリジェンスプラットフォーム(MISP、OpenCTI)へのアクセス
- 侵入分析のダイヤモンドモデルの理解
- MITRE ATT&CK の脅威グループプロファイルに関する知識
- マルウェア分析とインフラストラクチャ追跡手法に関する知識
主な概念
帰属証拠のカテゴリ
- インフラストラクチャの重複:共有される C2 サーバー、ドメイン、IP 範囲、ホスティングプロバイダー
- TTP の一貫性:キャンペーン間で一致する ATT&CK のテクニックとサブテクニック
- マルウェアコードの類似性:共有されるコードベース、コンパイラー、PDB パス、暗号化ルーチン
- 活動パターン:タイミング(勤務時間、タイムゾーン)、標的のパターン、活動のペース
- 言語的特徴:特定の言語による埋め込み文字列、変数名、エラーメッセージ
- 被害者の特徴:標的セクター、地域、組織プロファイルの一貫性
信頼度レベル
- 高い信頼度:複数の独立した証拠カテゴリが同じアクターを示している
- 中程度の信頼度:複数の証拠カテゴリが一致しているが、いくらかの曖昧さが残る
- 低い信頼度:証拠が限られており、偽の手がかりや共有ツールの可能性がある
競合仮説分析(ACH)
複数の競合仮説に照らして証拠を評価する、体系的な分析手法です。各証拠を、それぞれの仮説に対して整合、不整合、中立のいずれかに分類して評価します。不整合な証拠が最も少ない仮説が有力と判断されます。
ワークフロー
ステップ 1:帰属証拠を収集する
from stix2 import MemoryStore, Filter
from collections import defaultdict
class AttributionAnalyzer:
def __init__(self):
self.evidence = []
self.hypotheses = {}
def add_evidence(self, category, description, value, confidence):
self.evidence.append({
"category": category,
"description": description,
"value": value,
"confidence": confidence,
"timestamp": None,
})
def add_hypothesis(self, actor_name, actor_id=""):
self.hypotheses[actor_name] = {
"actor_id": actor_id,
"consistent_evidence": [],
"inconsistent_evidence": [],
"neutral_evidence": [],
"score": 0,
}
def evaluate_evidence(self, evidence_idx, actor_name, assessment):
"""Assess evidence against a hypothesis: consistent/inconsistent/neutral."""
if assessment == "consistent":
self.hypotheses[actor_name]["consistent_evidence"].append(evidence_idx)
self.hypotheses[actor_name]["score"] += self.evidence[evidence_idx]["confidence"]
elif assessment == "inconsistent":
self.hypotheses[actor_name]["inconsistent_evidence"].append(evidence_idx)
self.hypotheses[actor_name]["score"] -= self.evidence[evidence_idx]["confidence"] * 2
else:
self.hypotheses[actor_name]["neutral_evidence"].append(evidence_idx)
def rank_hypotheses(self):
"""Rank hypotheses by attribution score."""
ranked = sorted(
self.hypotheses.items(),
key=lambda x: x[1]["score"],
reverse=True,
)
return [
{
"actor": name,
"score": data["score"],
"consistent": len(data["consistent_evidence"]),
"inconsistent": len(data["inconsistent_evidence"]),
"confidence": self._score_to_confidence(data["score"]),
}
for name, data in ranked
]
def _score_to_confidence(self, score):
if score >= 80:
return "HIGH"
elif score >= 40:
return "MODERATE"
else:
return "LOW"
ステップ 2:インフラストラクチャの重複を分析する
def analyze_infrastructure_overlap(campaign_a_infra, campaign_b_infra):
"""Compare infrastructure between two campaigns for attribution."""
overlap = {
"shared_ips": set(campaign_a_infra.get("ips", [])).intersection(
campaign_b_infra.get("ips", [])
),
"shared_domains": set(campaign_a_infra.get("domains", [])).intersection(
campaign_b_infra.get("domains", [])
),
"shared_asns": set(campaign_a_infra.get("asns", [])).intersection(
campaign_b_infra.get("asns", [])
),
"shared_registrars": set(campaign_a_infra.get("registrars", [])).intersection(
campaign_b_infra.get("registrars", [])
),
}
overlap_score = 0
if overlap["shared_ips"]:
overlap_score += 30
if overlap["shared_domains"]:
overlap_score += 25
if overlap["shared_asns"]:
overlap_score += 15
if overlap["shared_registrars"]:
overlap_score += 10
return {
"overlap": {k: list(v) for k, v in overlap.items()},
"overlap_score": overlap_score,
"assessment": "STRONG" if overlap_score >= 40 else "MODERATE" if overlap_score >= 20 else "WEAK",
}
ステップ 3:キャンペーン間の TTP を比較する
from attackcti import attack_client
def compare_campaign_ttps(campaign_techniques, known_actor_techniques):
"""Compare campaign TTPs against known threat actor profiles."""
campaign_set = set(campaign_techniques)
actor_set = set(known_actor_techniques)
common = campaign_set.intersection(actor_set)
unique_campaign = campaign_set - actor_set
unique_actor = actor_set - campaign_set
jaccard = len(common) / len(campaign_set.union(actor_set)) if campaign_set.union(actor_set) else 0
return {
"common_techniques": sorted(common),
"common_count": len(common),
"unique_to_campaign": sorted(unique_campaign),
"unique_to_actor": sorted(unique_actor),
"jaccard_similarity": round(jaccard, 3),
"overlap_percentage": round(len(common) / len(campaign_set) * 100, 1) if campaign_set else 0,
}
ステップ 4:帰属レポートを作成する
def generate_attribution_report(analyzer):
"""Generate structured attribution assessment report."""
rankings = analyzer.rank_hypotheses()
report = {
"assessment_date": "2026-02-23",
"total_evidence_items": len(analyzer.evidence),
"hypotheses_evaluated": len(analyzer.hypotheses),
"rankings": rankings,
"primary_attribution": rankings[0] if rankings else None,
"evidence_summary": [
{
"index": i,
"category": e["category"],
"description": e["description"],
"confidence": e["confidence"],
}
for i, e in enumerate(analyzer.evidence)
],
}
return report
検証基準
- 証拠の収集で、帰属に関する6つのカテゴリすべてを網羅している
- ACH マトリックスで、競合仮説に照らして証拠を適切に評価している
- インフラストラクチャの重複分析で、共有される指標を特定している
- TTP の比較で、精度を高めるために ATT&CK のテクニック ID を使用している
- 帰属の信頼度レベルが適切に正当化されている
- レポートに代替仮説と偽の手がかりに関する考慮事項が含まれている
参考資料
コメント
Markdown 対応