Threat Intelligence: MITRE ATT&CK, STIX, TAXII e Feeds de IOCs na Prática Já leu

Threat Intelligence: Fundações e Contexto Threat Intelligence (TI) é a coleta, análise e disseminação de informações sobre ameaças cibernéticas com o objetivo de reduzir risco e tomar decisões informadas em segurança. Não é apenas dados brutos sobre ataques: é inteligência acionável que permite a uma organização antecipar, prevenir ou responder a incidentes. A diferença crucial está em que TI transforma indicadores técnicos em narrativas que explicam quem ataca, como atacam e por quê. Em um mundo onde novos malwares surgem diariamente e técnicas de ataque evoluem rapidamente, padronizar como compartilhamos e consumimos inteligência é crítico. É aqui que entram frameworks como MITRE ATT&CK, protocolos como STIX e TAXII, e a necessidade de gerenciar feeds de IOCs (Indicators of Compromise). Compreender como essas peças se encaixam é fundamental para qualquer profissional de segurança que queira construir ou integrar um programa robusto de TI. MITRE ATT&CK: Mapeando Táticas e Técnicas de Adversários O que é MITRE ATT&CK? MITRE ATT&CK é uma base

Threat Intelligence: Fundações e Contexto

Threat Intelligence (TI) é a coleta, análise e disseminação de informações sobre ameaças cibernéticas com o objetivo de reduzir risco e tomar decisões informadas em segurança. Não é apenas dados brutos sobre ataques: é inteligência acionável que permite a uma organização antecipar, prevenir ou responder a incidentes. A diferença crucial está em que TI transforma indicadores técnicos em narrativas que explicam quem ataca, como atacam e por quê.

Em um mundo onde novos malwares surgem diariamente e técnicas de ataque evoluem rapidamente, padronizar como compartilhamos e consumimos inteligência é crítico. É aqui que entram frameworks como MITRE ATT&CK, protocolos como STIX e TAXII, e a necessidade de gerenciar feeds de IOCs (Indicators of Compromise). Compreender como essas peças se encaixam é fundamental para qualquer profissional de segurança que queira construir ou integrar um programa robusto de TI.

MITRE ATT&CK: Mapeando Táticas e Técnicas de Adversários

O que é MITRE ATT&CK?

MITRE ATT&CK é uma base de conhecimento gratuita, mantida pelo MITRE, que documenta táticas e técnicas conhecidas usadas por adversários em ataques do mundo real. Não é uma ferramenta: é um modelo de referência que categoriza comportamentos maliciosos de forma consistente. A estrutura é organizada em níveis hierárquicos: Tática (o objetivo do adversário, como "Reconnaissance" ou "Execution") e Técnica (como o adversário alcança esse objetivo, como "Phishing" ou "Malware").

O valor do ATT&CK reside em sua baseação em dados reais. Cada técnica é respaldada por exemplos de grupos de ameaças, campanhas e malwares que as utilizaram. Isso torna a estrutura não apenas uma lista arbitrária, mas um reflexo do que adversários realmente fazem. Quando você alinha sua defesa a ATT&CK, você não está seguindo teoria abstrata: está se protegendo contra padrões comprovados.

Estrutura Prática do MITRE ATT&CK

ATT&CK define 14 táticas principais (em Windows/Linux). Para cada tática, existem várias técnicas e, muitas vezes, subtécnicas que refinam ainda mais o comportamento. Por exemplo:

  • Tática: Execution — objetivo do adversário é executar código malicioso
  • Técnica: Command and Scripting Interpreter — usar interpretadores como cmd.exe ou PowerShell
    • Subtécnica: PowerShell — especificamente usar PowerShell

Uma matriz completa pode ser consultada em attack.mitre.org. O importante é que essa estrutura permite que você mapeie suas defesas contra técnicas reais. Se você detecta o uso de PowerShell suspeito, você pode imediatamente correlacionar isso à técnica T1059.001 e, a partir daí, pesquisar quais grupos conhecidos usam essa técnica e que outras técnicas costumam aparecer em campanhas associadas.

STIX e TAXII: Padronizando Compartilhamento de Inteligência

STIX: Structured Threat Information Expression

STIX é um padrão aberto, desenvolvido em colaboração entre MITRE, DHS e comunidade de segurança, que define uma linguagem estruturada para expressar inteligência de ameaças. Em essência, STIX fornece um vocabulário padronizado para descrever indicadores, adversários, campanhas, malwares, tools e relacionamentos entre eles. Sem STIX, cada organização usaria formatos proprietários diferentes, tornando impossível compartilhar inteligência de forma consistente.

STIX é implementado em JSON e segue um modelo orientado a objetos. Existem várias tipos de objetos STIX (chamados de "Domain Objects" e "Relationship Objects"), mas os mais relevantes para TI são: Indicator (IOCs), Malware, Attack-Pattern, Campaign, Identity, Threat-Actor e Tool. Cada objeto tem propriedades padronizadas e pode estar relacionado a outros através de relacionamentos.

TAXII: Trusted Automated Exchange of Intelligence Information

Se STIX define o que você compartilha, TAXII define como você compartilha. TAXII é um protocolo baseado em HTTP/HTTPS que permite o compartilhamento automatizado de conteúdo STIX entre servidores. Funciona em um modelo cliente-servidor onde "TAXII Servers" (provedores de inteligência, como threat feeds comerciais ou centros de coordenação governamentais) disponibilizam conteúdo em "Collections", e "TAXII Clients" (sua organização) consomem esse conteúdo.

A estrutura básica do TAXII 2.1 (versão atual) é simples: um servidor TAXII hospeda collections de objetos STIX. Um cliente pode se conectar, autenticar (usando chaves API ou OAuth) e fazer poll de novos objetos ou estabelecer uma subscrição push. Isso permite que você automaticamente receba atualizações de inteligência de múltiplas fontes sem intervenção manual.

Exemplo Prático: Consumindo STIX de um Servidor TAXII

Aqui está um exemplo real de como consumir dados STIX de um servidor TAXII usando Python:

import requests
from stix2 import parse

# Configurar conexão ao servidor TAXII
TAXII_SERVER = "https://cti-taxii.mitre.org"
API_ROOT = f"{TAXII_SERVER}/taxii"
COLLECTION_ID = "95ecc61d-22a3-47c5-bbbb-a2e697751666"  # Enterprise ATT&CK
API_KEY = "sua_chave_aqui"

# Buscar todos os objetos de uma collection
def fetch_stix_objects():
    headers = {
        "Accept": "application/taxii+json;version=2.1",
    }

    # Se a API requer autenticação
    if API_KEY:
        headers["Authorization"] = f"Bearer {API_KEY}"

    # Montar URL para acessar os objetos
    url = f"{API_ROOT}/collections/{COLLECTION_ID}/objects"

    response = requests.get(url, headers=headers, verify=True)

    if response.status_code == 200:
        data = response.json()
        print(f"Total de objetos: {data.get('more', False)}")

        # Iterar sobre objetos STIX retornados
        for obj in data.get('objects', []):
            stix_obj = parse(obj)
            print(f"ID: {stix_obj.id}")
            print(f"Tipo: {stix_obj.type}")
            print(f"Criado em: {stix_obj.created}")
            print("---")
    else:
        print(f"Erro: {response.status_code}")
        print(response.text)

# Executar
fetch_stix_objects()

Neste exemplo, estamos nos conectando ao servidor TAXII público mantido pelo MITRE (que hospeda dados ATT&CK). O cliente faz uma requisição GET para a collection e recebe um conjunto de objetos STIX em JSON. Cada objeto pode ser parsing usando a biblioteca stix2 e processado conforme necessário.

Criando um Objeto STIX Manualmente

Você também pode criar objetos STIX para representar suas próprias descobertas. Aqui está um exemplo de criação de um Indicator STIX:

from stix2 import Indicator, Malware, parse_into_datetime
from datetime import datetime

# Criar um indicador (IOC) para um hash malicioso
indicator = Indicator(
    pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
    labels=["malicious-activity"],
    description="Hash MD5 de malware detectado em campanha APT-XYZ",
    created=parse_into_datetime(datetime.utcnow()),
    valid_from=parse_into_datetime(datetime.utcnow())
)

print(indicator.serialize(pretty=True))

# Também criar um objeto Malware relacionado
malware = Malware(
    name="Trojan.Generic.APT",
    description="Trojan genérico usado por grupo APT-XYZ",
    labels=["trojan"],
    is_family=False
)

print(malware.serialize(pretty=True))

O padrão STIX exige que indicadores usem a "Pattern" language, que é uma sintaxe específica para expressar IOCs. O exemplo acima mostra um padrão para detectar um arquivo com um hash específico. Você pode criar padrões muito mais complexos combinando múltiplas propriedades.

IOCs e Feeds: Operacionalizando Inteligência

O que são IOCs (Indicators of Compromise)?

IOCs são artefatos técnicos específicos que indicam a presença de atividade maliciosa. Exemplos incluem: hashes de arquivos maliciosos, endereços IP de servidores C&C, domínios maliciosos, URLs de phishing, regras YARA que detectam padrões, e até comportamentos específicos de processos. A diferença entre um "indicator" genérico e um "IOC" é que o IOC é altamente específico e acionável — você pode colocá-lo em suas ferramentas de detecção (SIEM, antivírus, firewall) e usá-lo imediatamente.

Um IOC tem um ciclo de vida. Inicialmente, quando descoberto, é altamente relevante. Conforme o tempo passa, especialmente se a campanha foi interrompida ou o malware foi amplamente detectado, o IOC pode perder relevância. Além disso, IOCs podem gerar falsos positivos (especialmente IPs, que podem ser compartilhados por serviços legítimos). Por isso, gerenciar feeds de IOCs com práticas rigorosas de confiança e contexto é essencial.

Estrutura de um Feed de IOC

Um "feed de IOC" é uma fonte automatizada de indicadores, geralmente em formato estruturado (JSON, CSV, ou STIX). Feeds podem vir de múltiplas fontes: agências governamentais (CISA), plataformas comerciais (Recorded Future, Anomali, Mandiant), comunidades de segurança (abuse.ch, OpenPhish), ou seu próprio SOC. A chave é que um bom feed deve incluir não apenas o indicador, mas contexto: qual tipo de ameaça representa, quando foi descoberto, qual o nível de confiança, e em qual tática/técnica do ATT&CK se encaixa.

Um exemplo de estrutura de feed robusto em JSON:

{
  "feed_metadata": {
    "name": "APT28_IOC_Feed",
    "source": "CISA",
    "last_updated": "2024-01-15T10:30:00Z",
    "confidence_level": "high"
  },
  "indicators": [
    {
      "type": "ipv4",
      "value": "192.0.2.1",
      "description": "C&C server for APT28 Sofacy campaign",
      "detected_date": "2024-01-10",
      "tags": ["apt28", "c2", "phishing"],
      "mitre_technique": "T1071.001",
      "confidence": "high",
      "ttl_days": 30
    },
    {
      "type": "domain",
      "value": "suspicious-update.com",
      "description": "Phishing domain spoofing Microsoft updates",
      "detected_date": "2024-01-12",
      "tags": ["phishing", "credential-theft"],
      "mitre_technique": "T1566.002",
      "confidence": "medium",
      "ttl_days": 60
    },
    {
      "type": "md5",
      "value": "a4c7f6d3e2b1c9a8f7e6d5c4b3a2f1e0",
      "description": "Trojan downloader variant",
      "detected_date": "2024-01-08",
      "tags": ["trojan", "downloader"],
      "mitre_technique": "T1105",
      "confidence": "high",
      "ttl_days": 90
    }
  ]
}

Consumindo e Processando Feeds de IOC

Aqui está um exemplo prático de como consumir um feed de IOC, validá-lo e carregá-lo em um SIEM ou ferramenta de detecção:

import requests
import json
from datetime import datetime, timedelta
from typing import List, Dict
import hashlib

class IOCFeedProcessor:
    """Processa feeds de IOC e aplica validações"""

    def __init__(self, feed_url: str, api_key: str = None):
        self.feed_url = feed_url
        self.api_key = api_key
        self.iocs = []
        self.expired_iocs = []

    def fetch_feed(self) -> bool:
        """Baixa o feed de IOC da fonte"""
        headers = {}
        if self.api_key:
            headers["Authorization"] = f"Bearer {self.api_key}"

        try:
            response = requests.get(self.feed_url, headers=headers, timeout=30)
            response.raise_for_status()

            data = response.json()
            self.iocs = data.get('indicators', [])
            print(f"✓ Feed carregado: {len(self.iocs)} IOCs")
            return True
        except Exception as e:
            print(f"✗ Erro ao buscar feed: {e}")
            return False

    def validate_ioc(self, ioc: Dict) -> bool:
        """Valida estrutura e campos obrigatórios do IOC"""
        required_fields = ['type', 'value', 'confidence']

        if not all(field in ioc for field in required_fields):
            return False

        # Validar tipo
        valid_types = ['ipv4', 'ipv6', 'domain', 'md5', 'sha1', 'sha256', 'url']
        if ioc['type'] not in valid_types:
            return False

        # Validar confiança
        valid_confidence = ['high', 'medium', 'low']
        if ioc.get('confidence') not in valid_confidence:
            return False

        return True

    def filter_expired(self) -> None:
        """Remove IOCs cuja TTL expirou"""
        now = datetime.utcnow()
        active_iocs = []

        for ioc in self.iocs:
            if 'detected_date' in ioc and 'ttl_days' in ioc:
                detected = datetime.fromisoformat(ioc['detected_date'])
                expiry = detected + timedelta(days=ioc['ttl_days'])

                if expiry < now:
                    self.expired_iocs.append(ioc)
                    continue

            active_iocs.append(ioc)

        self.iocs = active_iocs
        print(f"✓ IOCs ativos: {len(active_iocs)}, expirados removidos: {len(self.expired_iocs)}")

    def filter_by_confidence(self, min_confidence: str = 'medium') -> List[Dict]:
        """Filtra IOCs por nível de confiança"""
        confidence_map = {'low': 1, 'medium': 2, 'high': 3}
        min_level = confidence_map.get(min_confidence, 2)

        return [
            ioc for ioc in self.iocs 
            if confidence_map.get(ioc.get('confidence'), 0) >= min_level
        ]

    def export_for_siem(self, output_file: str) -> None:
        """Exporta IOCs em formato compatível com SIEM (JSON)"""
        siem_format = {
            "feed_info": {
                "exported_at": datetime.utcnow().isoformat(),
                "total_iocs": len(self.iocs)
            },
            "indicators": []
        }

        for ioc in self.iocs:
            siem_format["indicators"].append({
                "indicator": ioc['value'],
                "indicator_type": ioc['type'],
                "severity": ioc.get('confidence', 'unknown').upper(),
                "description": ioc.get('description', ''),
                "tags": ioc.get('tags', []),
                "source": "TI_Feed"
            })

        with open(output_file, 'w') as f:
            json.dump(siem_format, f, indent=2)

        print(f"✓ IOCs exportados para: {output_file}")

    def process(self, output_file: str = "iocs_processed.json") -> None:
        """Pipeline completo: buscar, validar, filtrar, exportar"""
        print("\n=== Processamento de Feed de IOC ===")

        if not self.fetch_feed():
            return

        # Validar
        valid_iocs = [ioc for ioc in self.iocs if self.validate_ioc(ioc)]
        invalid_count = len(self.iocs) - len(valid_iocs)
        if invalid_count > 0:
            print(f"⚠ IOCs inválidos descartados: {invalid_count}")
        self.iocs = valid_iocs

        # Filtrar expirados
        self.filter_expired()

        # Filtrar por confiança
        high_confidence = self.filter_by_confidence('high')
        print(f"✓ IOCs com alta confiança: {len(high_confidence)}")

        # Exportar
        self.export_for_siem(output_file)
        print("\n=== Processamento concluído ===\n")

# Uso
if __name__ == "__main__":
    # Usando um feed fictício (em produção seria uma URL real)
    processor = IOCFeedProcessor(
        feed_url="https://feeds.seu-provider.com/iocs.json",
        api_key="sua_chave_api"
    )

    processor.process()

Este código implementa um pipeline robusto de processamento: baixa o feed, valida cada IOC, remove expirados, filtra por confiança e exporta em formato pronto para consumo. Em um ambiente real, você executaria isso em um job agendado (cron ou task scheduler) e alimentaria os IOCs em seu SIEM, firewall ou antivírus via API.

Integrando IOCs com ATT&CK

Um aspecto crucial é mapear seus IOCs de volta ao framework MITRE ATT&CK. Quando você detecta um IOC, você não quer apenas bloqueá-lo — você quer entender em qual contexto ofensivo ele se encaixa. No exemplo anterior, incluímos o campo mitre_technique. Aqui está como usar isso:

import json

class ThreatIntelligenceAnalyzer:
    """Correlaciona IOCs com ATT&CK framework"""

    def __init__(self):
        # Mapeamento simplificado de tipos de IOC para táticas/técnicas comuns
        self.ioc_to_attack = {
            'ipv4': {
                'tactics': ['Command and Control', 'Exfiltration'],
                'techniques': ['T1071', 'T1041']
            },
            'domain': {
                'tactics': ['Initial Access', 'Command and Control'],
                'techniques': ['T1566', 'T1071']
            },
            'md5': {
                'tactics': ['Execution', 'Defense Evasion'],
                'techniques': ['T1204', 'T1140']
            },
            'url': {
                'tactics': ['Initial Access'],
                'techniques': ['T1566.002']
            }
        }

    def analyze_ioc(self, ioc: Dict) -> Dict:
        """Enriquece IOC com contexto ATT&CK"""
        ioc_type = ioc.get('type')

        enriched = ioc.copy()

        # Adicionar mapeamento genérico
        if ioc_type in self.ioc_to_attack:
            enriched['likely_tactics'] = self.ioc_to_attack[ioc_type]['tactics']
            enriched['likely_techniques'] = self.ioc_to_attack[ioc_type]['techniques']

        # Se o feed já tem técnica específica, manter
        if 'mitre_technique' not in enriched:
            enriched['mitre_technique'] = self.ioc_to_attack.get(ioc_type, {}).get('techniques', [])[0]

        return enriched

    def generate_threat_report(self, iocs: List[Dict]) -> Dict:
        """Gera relatório que correlaciona IOCs com adversários conhecidos"""
        report = {
            "timestamp": datetime.utcnow().isoformat(),
            "summary": {},
            "by_tactic": {},
            "indicators": []
        }

        for ioc in iocs:
            enriched = self.analyze_ioc(ioc)
            report['indicators'].append(enriched)

            # Contar por tática
            for tactic in enriched.get('likely_tactics', []):
                report['by_tactic'][tactic] = report['by_tactic'].get(tactic, 0) + 1

        report['summary'] = {
            "total_indicators": len(iocs),
            "tactics_covered": len(report['by_tactic']),
            "high_confidence": len([i for i in iocs if i.get('confidence') == 'high'])
        }

        return report

# Uso
analyzer = ThreatIntelligenceAnalyzer()
sample_iocs = [
    {
        "type": "ipv4",
        "value": "10.0.0.1",
        "confidence": "high",
        "mitre_technique": "T1071.001"
    },
    {
        "type": "domain",
        "value": "malware.com",
        "confidence": "medium"
    }
]

report = analyzer.generate_threat_report(sample_iocs)
print(json.dumps(report, indent=2))

Este exemplo mostra como você correlaciona IOCs com técnicas ATT&CK conhecidas, permitindo não apenas detectar ameaças, mas entender como elas se encaixam no comportamento de adversários conhecidos.

Arquitetura Integrada: Juntando Tudo

Uma plataforma de Threat Intelligence robusta integra todos esses componentes: você consome feeds de IOCs em STIX via TAXII, mapeia cada IOC para técnicas MITRE ATT&CK, armazena em um banco centralizado, e alimenta suas ferramentas de detecção. A arquitetura básica seria:

[Feeds TAXII] → [Parser STIX] → [Validação + Enriquecimento] → [Mapeamento ATT&CK]
                                                                        ↓
                                                        [SIEM/SOAR/Antivírus]
                                                                        ↓
                                                            [Resposta a Incidentes]

Na prática, você implementaria isso com ferramentas como: Threat Intelligence Platform (TIP) comerciais (Anomali, Recorded Future), ou soluções open-source (MISP, OpenCTI). Essas plataformas abstraem a complexidade de consumir múltiplas fontes, normalizar formatos, evitar duplicação, e redistribuir para suas ferramentas operacionais.

Conclusão

Os três aprendizados principais que você deve reter:

  1. MITRE ATT&CK é seu mapa: Não é uma ferramenta que você instala, mas um framework conceitual que padroniza como você entende ofensivas. Todo IOC que você processa, toda técnica que você detecta, deve ser mapeada de volta ao ATT&CK. Isso transforma dados brutos em inteligência contextualizada.

  2. STIX e TAXII resolvem o problema de linguagem comum: Sem eles, cada organização teria seu próprio formato. STIX fornece a estrutura de dados, TAXII fornece o protocolo de transporte. Juntos, eles permitem que feeds de múltiplas fontes sejam consumidos de forma automatizada e consistente.

  3. IOCs sem contexto são apenas ruído: Um hash ou IP isolado é inútil se você não souber por quanto tempo usá-lo, qual seu nível de confiança, ou qual tática ofensiva ele representa. Um feed bem estruturado inclui metadados, TTL e mapeamento ATT&CK — transformando dados em inteligência operacionalizável.

Referências

  • MITRE ATT&CK Framework: https://attack.mitre.org/ — documentação oficial, matrizes e técnicas
  • OASIS STIX 2.1 Specification: https://docs.oasis-open.org/cti/stix/v2.1/stix-v2.1.html — padrão técnico completo de STIX
  • OASIS TAXII 2.1 Specification: https://docs.oasis-open.org/cti/taxii/v2.1/taxii-v2.1.html — protocolo TAXII oficial
  • python-stix2 Library: https://github.com/oasis-open/cti-python-stix2 — biblioteca Python para trabalhar com STIX
  • CISA Threat Intelligence Sharing: https://www.cisa.gov/secureourshared — feeds de IOC governamentais em STIX/TAXII

Artigos relacionados