攻擊歸因證據分析 是做什麼的?
概述
攻擊歸因分析涉及系統性地評估證據,以判斷哪個威脅行為者或組織應對某次網路行動負責。本技能涵蓋了使用鑽石模型和競爭假設分析法 (ACH) 收集並加權歸因指標,分析基礎設施重疊、TTP 一致性、惡意軟體程式碼相似度、操作時間模式及語言跡證,以建立可信度加權的歸因評估。
使用時機
- 調查需要分析攻擊歸因證據的安全事件時
- 為此領域建立偵測規則或威脅獵殺查詢時
- SOC 分析師需要此分析類型的結構化程序時
- 驗證相關攻擊技術的安全監控覆蓋範圍時
先決條件
- Python 3.9+ 及
attackcti、stix2、networkx函式庫 - 可存取威脅情報平台 (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):
"""針對假設評估證據:一致/不一致/中立。"""
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):
"""根據歸因分數對假設進行排序。"""
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):
"""比較兩個戰役之間的基礎設施以進行歸因。"""
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):
"""比較戰役 TTP 與已知威脅行為者簡介。"""
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):
"""產生結構化的歸因評估報告。"""
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
驗證標準
- 證據收集涵蓋全部六個歸因類別
- ACH 矩陣正確地針對競爭假設評估證據
- 基礎設施重疊分析能識別共享指標
- TTP 比較使用 ATT&CK 技術 ID 以確保精確性
- 歸因信心等級有適當的依據
- 報告中包含替代假設與偽旗行動的考量