¿Qué hace Análisis de Evidencia de Atribución de Campañas?
Resumen
El análisis de atribución de campañas implica evaluar sistemáticamente la evidencia para determinar qué actor o grupo de amenaza es responsable de una operación cibernética. Este skill cubre la recopilación y ponderación de indicadores de atribución utilizando el Modelo Diamante y ACH (Análisis de Hipótesis en Competencia), analizando superposiciones de infraestructura, consistencia de TTP, similitudes de código de malware, patrones de tiempo operativos y artefactos de idioma para construir evaluaciones de atribución con niveles de confianza ponderados.
Cuándo Usar
- Al investigar incidentes de seguridad que requieran analizar evidencia de atribución de campañas
- Al construir reglas de detección o consultas de caza de amenazas para este dominio
- Cuando los analistas del SOC necesiten procedimientos estructurados para este tipo de análisis
- Al validar la cobertura de monitoreo de seguridad para técnicas de ataque relacionadas
Prerrequisitos
- Python 3.9+ con las librerías
attackcti,stix2,networkx - Acceso a plataformas de inteligencia de amenazas (MISP, OpenCTI)
- Comprensión del Modelo Diamante de Análisis de Intrusión
- Familiaridad con los perfiles de grupos de amenaza de MITRE ATT&CK
- Conocimiento de análisis de malware y técnicas de seguimiento de infraestructura
Conceptos Clave
Categorías de Evidencia de Atribución
- Superposición de Infraestructura: Servidores C2 compartidos, dominios, rangos de IP, proveedores de hosting
- Consistencia de TTP: Técnicas y sub-técnicas de ATT&CK coincidentes entre campañas
- Similitud de Código de Malware: Bases de código compartidas, compiladores, rutas de PDB, rutinas de cifrado
- Patrones Operativos: Tiempo (horas laborales, zonas horarias), patrones de selección de objetivo, tempo operativo
- Artefactos de Idioma: Cadenas embebidas, nombres de variables, mensajes de error en idiomas específicos
- Victimología: Sector objetivo, geografía y consistencia del perfil organizacional
Niveles de Confianza
- Alta Confianza: Múltiples categorías de evidencia independientes convergen en el mismo actor
- Confianza Moderada: Varias categorías de evidencia coinciden, queda cierta ambigüedad
- Baja Confianza: Evidencia limitada, posibles falsas banderas o herramientas compartidas
Análisis de Hipótesis en Competencia (ACH)
Método analítico estructurado que evalúa la evidencia contra múltiples hipótesis en competencia. Cada pieza de evidencia se califica como consistente, inconsistente o neutral con respecto a cada hipótesis. Se favorece la hipótesis con la menor cantidad de evidencia inconsistente.
Flujo de Trabajo
Paso 1: Recopilar Evidencia de Atribución
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):
"""Evaluar evidencia contra una hipótesis: 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):
"""Clasificar hipótesis por puntuación de atribución."""
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"
Paso 2: Análisis de Superposición de Infraestructura
def analyze_infrastructure_overlap(campaign_a_infra, campaign_b_infra):
"""Comparar infraestructura entre dos campañas para atribución."""
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",
}
Paso 3: Comparación de TTP entre Campañas
from attackcti import attack_client
def compare_campaign_ttps(campaign_techniques, known_actor_techniques):
"""Comparar TTP de campaña contra perfiles de actores de amenaza conocidos."""
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,
}
Paso 4: Generar Informe de Atribución
def generate_attribution_report(analyzer):
"""Generar informe estructurado de evaluación de atribución."""
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
Criterios de Validación
- La recopilación de evidencia cubre las seis categorías de atribución
- La matriz ACH evalúa adecuadamente la evidencia contra hipótesis en competencia
- El análisis de superposición de infraestructura identifica indicadores compartidos
- La comparación de TTP utiliza IDs de técnicas de ATT&CK para precisión
- Los niveles de confianza de atribución están debidamente justificados
- El informe incluye hipótesis alternativas y consideraciones de falsas banderas