O que Análise de Evidências de Atribuição de Campanhas Cibernéticas faz?
Visão Geral
A análise de atribuição de campanhas envolve avaliar sistematicamente evidências para determinar qual ator de ameaça ou grupo é responsável por uma operação cibernética. Esta habilidade abrange a coleta e ponderação de indicadores de atribuição usando o Modelo Diamante e a ACH (Análise de Hipóteses Concorrentes), analisando sobreposições de infraestrutura, consistência de TTPs, similaridades de código de malware, padrões de tempo operacional e artefatos de idioma para construir avaliações de atribuição ponderadas por confiança.
Quando Usar
- Ao investigar incidentes de segurança que exigem análise de evidências de atribuição de campanhas
- Ao construir regras de detecção ou consultas de caça a ameaças para este domínio
- Quando analistas de SOC precisam de procedimentos estruturados para este tipo de análise
- Ao validar a cobertura de monitoramento de segurança para técnicas de ataque relacionadas
Pré-requisitos
- Python 3.9+ com as bibliotecas
attackcti,stix2,networkx - Acesso a plataformas de inteligência de ameaças (MISP, OpenCTI)
- Compreensão do Modelo Diamante de Análise de Intrusão
- Familiaridade com os perfis de grupos de ameaças do MITRE ATT&CK
- Conhecimento de análise de malware e técnicas de rastreamento de infraestrutura
Conceitos Chave
Categorias de Evidências de Atribuição
- Sobreposição de Infraestrutura: Servidores C2, domínios, faixas de IP, provedores de hospedagem compartilhados
- Consistência de TTPs: Correspondência de técnicas e sub-técnicas do ATT&CK entre campanhas
- Similaridade de Código de Malware: Bases de código, compiladores, caminhos PDB, rotinas de criptografia compartilhadas
- Padrões Operacionais: Tempo (horários de trabalho, fusos horários), padrões de segmentação, ritmo operacional
- Artefatos de Idioma: Strings embutidas, nomes de variáveis, mensagens de erro em idiomas específicos
- Vitimologia: Setor alvo, geografia e consistência do perfil organizacional
Níveis de Confiança
- Alta Confiança: Múltiplas categorias de evidências independentes convergem para o mesmo ator
- Confiança Moderada: Várias categorias de evidências coincidem, alguma ambiguidade permanece
- Baixa Confiança: Evidências limitadas, possíveis bandeiras falsas ou ferramentas compartilhadas
Análise de Hipóteses Concorrentes (ACH)
Método analítico estruturado que avalia evidências contra múltiplas hipóteses concorrentes. Cada peça de evidência é pontuada como consistente, inconsistente ou neutra em relação a cada hipótese. A hipótese com menos evidências inconsistentes é favorecida.
Fluxo de Trabalho
Passo 1: Coletar Evidências de Atribuição
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):
"""Avalia a evidência contra uma hipótese: 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):
"""Classifica as hipóteses pela pontuação de atribuição."""
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"
Passo 2: Análise de Sobreposição de Infraestrutura
def analyze_infrastructure_overlap(campaign_a_infra, campaign_b_infra):
"""Compara a infraestrutura entre duas campanhas para atribuição."""
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",
}
Passo 3: Comparação de TTPs entre Campanhas
from attackcti import attack_client
def compare_campaign_ttps(campaign_techniques, known_actor_techniques):
"""Compara as TTPs da campanha com os perfis de atores de ameaça conhecidos."""
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,
}
Passo 4: Gerar Relatório de Atribuição
def generate_attribution_report(analyzer):
"""Gera um relatório estruturado de avaliação de atribuição."""
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
Critérios de Validação
- A coleta de evidências abrange todas as seis categorias de atribuição
- A matriz ACH avalia adequadamente as evidências contra hipóteses concorrentes
- A análise de sobreposição de infraestrutura identifica indicadores compartilhados
- A comparação de TTPs usa IDs de técnicas do ATT&CK para precisão
- Os níveis de confiança de atribuição são devidamente justificados
- O relatório inclui hipóteses alternativas e considerações de bandeiras falsas