Coletar registros de IOC do MISP

Compatível com:

Este documento explica como ingerir registros de IOC (indicadores de comprometimento) do MISP (Malware Information Sharing Platform) no Google Security Operations usando o Bindplane. O analisador processa os dados nos formatos CSV e JSON. Ele extrai atributos de IOC, como endereços IP, domínios, hashes e URLs, mapeando-os para um modelo de dados unificado (UDM) com detalhes de ameaças, como gravidade, confiança e descrições. O analisador processa entradas de IOC únicas e múltiplas nos dados de entrada, normalizando-as em uma saída UDM consistente.

Antes de começar

Verifique se você tem os pré-requisitos a seguir:

  • Uma instância do Google SecOps.
  • Um host Linux com systemd.
  • Se você estiver executando um proxy, verifique se as portas do firewall estão abertas de acordo com os requisitos do agente do Bindplane.
  • Acesso privilegiado ao seu servidor MISP.

Receber o arquivo de autenticação de ingestão do Google SecOps

  1. Faça login no console do Google SecOps.
  2. Acesse Configurações do SIEM > Agentes de coleta.
  3. Baixe o arquivo de autenticação de ingestão.
    • Salve o arquivo de forma segura no sistema em que o Bindplane será instalado.

Receber o ID do cliente do Google SecOps

  1. Faça login no console do Google SecOps.
  2. Acesse Configurações do SIEM*> Perfil.
  3. Copie e salve o ID do cliente na seção Detalhes da organização.

Receber credenciais da API MISP

  1. Faça login na interface da Web do MISP como administrador.
  2. Acesse Administração > Listar chaves de autenticação.
  3. Clique em Adicionar chave de autenticação.
  4. Informe os seguintes detalhes de configuração:
    • Usuário: selecione a conta de usuário associada à chave.
    • Opcional: IPs permitidos: especifique os endereços IP permitidos para a chave.
    • Validade: deixe em branco se não quiser definir uma data de validade ou defina conforme necessário.
  5. Clique em Enviar.
  6. Copie e salve a chave de API em um local seguro.
  7. Clique em Anotei minha chave.

Configurar a exportação de dados do MISP

  1. Instale o PyMISP no seu servidor MISP:

    pip3 install pymisp
    
  2. Crie o diretório de exportação:

    sudo mkdir -p /opt/misp/scripts
    sudo mkdir -p /opt/misp/ioc_export
    
  3. Crie o arquivo de credenciais /opt/misp/scripts/keys.py:

    misp_url = 'https://<MISP_SERVER_URL>'
    misp_key = '<MISP_API_KEY>'
    misp_verifycert = True
    misp_client_cert = ''
    
    • Substitua <MISP_SERVER_URL> pelo URL do servidor MISP.
    • Substitua <MISP_API_KEY> pela chave de API dos pré-requisitos.
  4. Crie o script de exportação /opt/misp/scripts/misp_export.py:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    import argparse
    from pymisp import ExpandedPyMISP
    from keys import misp_url, misp_key, misp_verifycert
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser(description='Export MISP IOCs to CSV format.')
        parser.add_argument("--controller", default='attributes',
                            help="Controller to use for search (events, objects, attributes)")
        parser.add_argument("--event_id",
                            help="Event ID to fetch. Without it, fetches recent data.")
        parser.add_argument("--attributes", nargs='*',
                            help="Requested attributes for CSV export")
        parser.add_argument("--misp_types", nargs='+',
                            help="MISP types to fetch (ip-src, hostname, domain, etc.)")
        parser.add_argument("--context", action='store_true',
                            help="Add event level context (tags, metadata)")
        parser.add_argument("--outfile", required=True,
                            help="Output file to write the CSV data")
        parser.add_argument("--last", required=True,
                            help="Time period: days (d), hours (h), minutes (m) - e.g., 1d, 12h, 30m")
    
        args = parser.parse_args()
    
        api = ExpandedPyMISP(misp_url, misp_key, misp_verifycert, debug=False)
    
        response = api.search(
            controller=args.controller,
            return_format='csv',
            type_attribute=args.misp_types,
            publish_timestamp=args.last,
            include_context=args.context,
            requested_attributes=args.attributes or None
        )
    
        with open(args.outfile, 'w') as response_file:
            response_file.write(response)
    
    1. Torne o script executável:
    sudo chmod +x /opt/misp/scripts/misp_export.py
    

    Programar exportações de dados do MISP

    1. Crie exportações programadas usando crontab:
    sudo crontab -e
    
  5. Adicione as seguintes entradas de cron:

    # Export different IOC types daily with context
    0 0 * * * python3 /opt/misp/scripts/misp_export.py --outfile /opt/misp/ioc_export/domains.csv --misp_types domain --last 1d --context --attributes uuid event_id category type value comment to_ids date attribute_tag event_info
    0 1 * * * python3 /opt/misp/scripts/misp_export.py --outfile /opt/misp/ioc_export/ip-src.csv --misp_types ip-src --last 1d --context --attributes uuid event_id category type value comment to_ids date attribute_tag event_info
    0 2 * * * python3 /opt/misp/scripts/misp_export.py --outfile /opt/misp/ioc_export/ip-dst.csv --misp_types ip-dst --last 1d --context --attributes uuid event_id category type value comment to_ids date attribute_tag event_info
    0 3 * * * python3 /opt/misp/scripts/misp_export.py --outfile /opt/misp/ioc_export/urls.csv --misp_types url --last 1d --context --attributes uuid event_id category type value comment to_ids date attribute_tag event_info
    0 4 * * * python3 /opt/misp/scripts/misp_export.py --outfile /opt/misp/ioc_export/sha256.csv --misp_types sha256 --last 1d --context --attributes uuid event_id category type value comment to_ids date attribute_tag event_info
    0 5 * * * python3 /opt/misp/scripts/misp_export.py --outfile /opt/misp/ioc_export/filenames.csv --misp_types filename --last 1d --context --attributes uuid event_id category type value comment to_ids date attribute_tag event_info
    0 6 * * * python3 /opt/misp/scripts/misp_export.py --outfile /opt/misp/ioc_export/registries.csv --misp_types regkey --last 1d --context --attributes uuid event_id category type value comment to_ids date attribute_tag event_info
    0 7 * * * python3 /opt/misp/scripts/misp_export.py --outfile /opt/misp/ioc_export/mutexes.csv --misp_types mutex --last 1d --context --attributes uuid event_id category type value comment to_ids date attribute_tag event_info
    
  6. Se quiser, programe uma extração de feeds do MISP:

    23 0 * * * curl --insecure --header "Authorization: <MISP_API_KEY>" --header "Accept: application/json" --header "Content-Type: application/json" https://<MISP_SERVER_URL>/feeds/fetchFromAllFeeds
    

Instalar o agente do Bindplane

Instale o agente do Bindplane no sistema operacional Linux de acordo com as instruções a seguir.

Instalação do Linux

  1. Abra um terminal com privilégios de root ou sudo.
  2. Execute este comando:

    sudo sh -c "$(curl -fsSlL https://github.com/observiq/bindplane-otel-collector/releases/latest/download/install_unix.sh)" install_unix.sh
    

Outros recursos de instalação

Configurar o agente do Bindplane para ingerir registros do MISP e enviar ao Google SecOps

  1. Acesse o arquivo de configuração:

    • Localize o arquivo config.yaml. Normalmente, ele fica no diretório /etc/bindplane-agent/ no Linux.
    • Abra o arquivo usando um editor de texto (por exemplo, nano, vi).
  2. Edite o arquivo config.yaml da seguinte forma:

    receivers:
        filelog:
            file_path: /opt/misp/ioc_export/*.log
    
    exporters:
        chronicle/chronicle_w_labels:
            compression: gzip
            # Adjust the path to the credentials file you downloaded in Step 1
            creds_file_path: '/path/to/ingestion-authentication-file.json'
            # Replace with your actual customer ID from Step 2
            customer_id: <customer_id>
            endpoint: malachiteingestion-pa.googleapis.com
            # Add optional ingestion labels for better organization
            ingestion_labels:
                log_type: 'MISP_IOC'
                raw_log_field: body
    
    service:
        pipelines:
            logs/source0__chronicle_w_labels-0:
                receivers:
                  - filelog
                exporters:
                    - chronicle/chronicle_w_labels
    
    • Substitua <CUSTOMER_ID> pelo ID de cliente real dos pré-requisitos.
    • Atualize /path/to/ingestion-authentication-file.json para o caminho em que o arquivo de autenticação foi salvo.

Reinicie o agente do Bindplane para aplicar as mudanças

  1. Para reiniciar o agente do Bindplane em Linux, execute o seguinte comando:

    sudo systemctl restart observiq-otel-collector
    

Tabela de mapeamento do UDM

Campo de registro Mapeamento do UDM Lógica
Attribute.category entity.metadata.threat.category_details Mapeamento direto do campo category no objeto Attribute.
Attribute.comment entity.metadata.threat.summary Mapeamento direto do campo comment no objeto Attribute.
Attribute.deleted entity.metadata.threat.detection_fields.value Mapeamento direto do campo deleted no objeto Attribute. A chave está definida como Attribute deleted.
Attribute.event_id entity.metadata.threat.detection_fields.value Mapeamento direto do campo event_id no objeto Attribute. A chave está definida como Attribute event_id.
Attribute.first_seen entity.metadata.threat.detection_fields.value Mapeamento direto do campo first_seen no objeto Attribute. A chave está definida como Attribute first_seen.
Attribute.id entity.metadata.threat.detection_fields.value Mapeamento direto do campo id no objeto Attribute. A chave é definida como Attribute id ou Attribute id $$, dependendo do formato do registro bruto.
Attribute.timestamp entity.metadata.threat.detection_fields.value Mapeamento direto do campo timestamp no objeto Attribute. A chave está definida como Attribute timestamp.
Attribute.to_ids entity.metadata.threat.detection_fields.value Mapeamento direto do campo to_ids no objeto Attribute. A chave está definida como Attribute to_ids.
Attribute.type entity.metadata.threat.category_details Mapeamento direto do campo type no objeto Attribute.
Attribute.type log_type Usado para determinar o tipo de IOC e mapeá-lo para os campos de UDM adequados.
Attribute.uuid entity.metadata.product_entity_id Mapeamento direto do campo uuid no objeto Attribute.
Attribute.value entity.entity.file.full_path Mapeado se o Attribute.type for filename.
Attribute.value entity.entity.file.md5 Mapeado se o Attribute.type for md5.
Attribute.value entity.entity.file.sha1 Mapeado se o Attribute.type for sha1.
Attribute.value entity.entity.file.sha256 Mapeado se o Attribute.type for sha256.
Attribute.value entity.entity.hostname Mapeado se o Attribute.type for domain.
Attribute.value entity.entity.ip Mapeado se o Attribute.type for ip-dst, ip-dst|port ou ip-src. O valor é extraído usando um padrão grok.
Attribute.value entity.entity.resource.name Mapeado se o Attribute.type for mutex.
Attribute.value entity.entity.registry.registry_key Mapeado se o Attribute.type for regkey.
Attribute.value entity.entity.url Mapeado se o Attribute.type for uri ou URL.
column1 entity.metadata.product_entity_id Mapeamento direto da primeira coluna nos dados CSV.
column14 event_info Usado para anexar mais informações ao campo threat_sr.description.
column16 event_source_org Mapeamento direto da 16ª coluna nos dados CSV.
column18 threat_level Mapeamento direto da 18ª coluna nos dados CSV.
column21 descrição Mapeamento direto da 21ª coluna nos dados CSV.
column3 misp_category Mapeamento direto da terceira coluna nos dados CSV.
column4 tipo Mapeamento direto da quarta coluna nos dados CSV.
column5 valor Mapeamento direto da quinta coluna nos dados CSV.
column6 comentário Mapeamento direto da sexta coluna nos dados CSV.
column8 ts1 Mapeamento direto da oitava coluna nos dados CSV.
descrição ioc.description O valor é gerado combinando os campos description e event_info, separados por - additional info:.
descrição entity.metadata.threat.description Mapeamento direto do campo description.
event_creator_email entity.entity.labels.value Mapeamento direto do campo event_creator_email. A chave está definida como event_creator_email.
event_source_org ioc.feed_name Mapeamento direto do campo event_source_org.
event_source_org entity.metadata.threat.threat_feed_name Mapeamento direto do campo event_source_org.
Feed.publish entity.metadata.threat.detection_fields.value Mapeamento direto do campo publish no objeto Feed. A chave está definida como Feed publish.
first_seen ioc.active_timerange.start Mapeamento direto do campo first_seen. O valor é analisado como uma data.
first_seen entity.metadata.interval.start_time Mapeamento direto do campo first_seen. O valor é analisado como uma data.
informações entity.metadata.description Mapeamento direto do campo info.
last_seen ioc.active_timerange.end Mapeamento direto do campo last_seen. O valor é analisado como uma data.
log.category ioc.categorization Mapeamento direto do campo category no objeto log.
log.category entity.metadata.threat.category_details Mapeamento direto do campo category no objeto log.
log.comment entity.entity.file.full_path Mapeado se log.type for filename e o campo comment não for Artifacts dropped.
log.comment entity.metadata.threat.detection_fields.value Mapeamento direto do campo comment no objeto log. A chave está definida como Attribute comment.
log.comment entity.metadata.threat.summary Mapeamento direto do campo comment no objeto log.
log.deleted entity.metadata.threat.detection_fields.value Mapeamento direto do campo deleted no objeto log. A chave está definida como Attribute deleted.
log.event_id entity.metadata.threat.detection_fields.value Mapeamento direto do campo event_id no objeto log. A chave está definida como Attribute event_id.
log.first_seen entity.metadata.threat.detection_fields.value Mapeamento direto do campo first_seen no objeto log. A chave está definida como Attribute first_seen.
log.id entity.metadata.threat.detection_fields.value Mapeamento direto do campo id no objeto log. A chave está definida como Attribute id.
log.timestamp entity.metadata.threat.detection_fields.value Mapeamento direto do campo timestamp no objeto log. A chave está definida como Attribute timestamp.
log.to_ids entity.metadata.threat.detection_fields.value Mapeamento direto do campo to_ids no objeto log. A chave está definida como Attribute to_ids.
log.type ioc.categorization Mapeamento direto do campo type no objeto log.
log.type log_type Usado para determinar o tipo de IOC e mapeá-lo para os campos de UDM adequados.
log.uuid entity.metadata.product_entity_id Mapeamento direto do campo uuid no objeto log.
log.value entity.entity.file.full_path Mapeado se o log.type for filename.
log.value entity.entity.file.md5 Mapeado se o log.type for md5.
log.value entity.entity.file.sha1 Mapeado se o log.type for sha1.
log.value entity.entity.file.sha256 Mapeado se o log.type for sha256.
log.value entity.entity.hostname Mapeado se o log.type for domain.
log.value entity.entity.ip Mapeado se o log.type for ip-dst, ip-dst|port ou ip-src. O valor é extraído usando um padrão grok.
log.value entity.entity.resource.name Mapeado se o log.type for mutex.
log.value entity.entity.registry.registry_key Mapeado se o log.type for regkey.
log.value entity.entity.url Mapeado se o log.type for uri ou url.
log.value ioc.domain_and_ports.domain Mapeado se o log.type for domain.
log.value entity.entity.user.email_addresses Mapeado se o log.type for threat-actor.
misp_category entity.metadata.threat.category_details Mapeamento direto do campo misp_category.
Org.name entity.metadata.threat.detection_fields.value Mapeamento direto do campo name no objeto Org. A chave está definida como Org name.
publicado entity.metadata.threat.detection_fields.value Mapeamento direto do campo published. A chave está definida como published.
Tag.colour entity.metadata.threat.detection_fields.value Mapeamento direto do campo colour no objeto Tag. A chave está definida como tag colour.
Tag.exportable entity.metadata.threat.detection_fields.value Mapeamento direto do campo exportable no objeto Tag. A chave está definida como tag exportable.
Tag.hide_tag entity.metadata.threat.detection_fields.value Mapeamento direto do campo hide_tag no objeto Tag. A chave está definida como tag hide_tag.
Tag.id entity.metadata.threat.detection_fields.value Mapeamento direto do campo id no objeto Tag. A chave está definida como tag id.
Tag.is_custom_galaxy entity.metadata.threat.detection_fields.value Mapeamento direto do campo is_custom_galaxy no objeto Tag. A chave está definida como tag is_custom_galaxy.
Tag.is_galaxy entity.metadata.threat.detection_fields.value Mapeamento direto do campo is_galaxy no objeto Tag. A chave está definida como tag is_galaxy.
Tag.isinherited entity.metadata.threat.detection_fields.value Mapeamento direto do campo isinherited no objeto Tag. A chave está definida como tag isinherited.
Tag.name entity.metadata.threat.detection_fields.value Mapeamento direto do campo name no objeto Tag. A chave está definida como tag name.
Tag.numerical_value entity.metadata.threat.detection_fields.value Mapeamento direto do campo numerical_value no objeto Tag. A chave está definida como tag numerical_value.
Tag.user_id entity.metadata.threat.detection_fields.value Mapeamento direto do campo user_id no objeto Tag. A chave está definida como tag user_id.
threat_level ioc.raw_severity Mapeamento direto do campo threat_level.
threat_level entity.metadata.threat.severity_details Mapeamento direto do campo threat_level.
threat_level_id entity.entity.labels.value Mapeamento direto do campo threat_level_id. A chave está definida como threat_level_id.
ts1 ioc.active_timerange.start Mapeamento direto do campo ts1. O valor é analisado como uma data.
ts1 entity.metadata.interval.start_time Mapeamento direto do campo ts1. O valor é analisado como uma data.
entity.entity.file.full_path Mapeado se o type for filename.
entity.entity.file.md5 Mapeado se o type for md5.
entity.entity.file.sha1 Mapeado se o type for sha1.
entity.entity.file.sha256 Mapeado se o type for sha256.
entity.entity.hostname Mapeado se o type for domain.
entity.entity.ip Mapeado se o type for ip-dst, ip-dst|port ou ip-src. O valor é extraído usando um padrão grok.
entity.entity.port Mapeado se o campo port não estiver vazio. O valor é convertido em um número inteiro.
entity.entity.resource.name Mapeado se o type for mutex.
entity.entity.resource.resource_subtype Mapeado se o type for regkey. O valor é definido como regkey.
entity.entity.resource.resource_type Mapeado se o type for mutex ou regkey. O valor é definido como MUTEX ou STORAGE_OBJECT, respectivamente.
entity.entity.registry.registry_key Mapeado se o type for regkey.
entity.entity.url Mapeado se o type for uri ou url.
entity.metadata.collected_timestamp O valor é definido como o carimbo de data/hora da entrada de registro bruta.
entity.metadata.description O valor é definido como o campo type se o registro bruto estiver no formato CSV. Caso contrário, ele será definido como o campo info.
entity.metadata.entity_type O valor é determinado com base no campo type ou log_type. Pode ser DOMAIN_NAME, FILE, IP_ADDRESS, MUTEX, RESOURCE ou URL.
entity.metadata.interval.end_time O valor é definido como um padrão de 253402300799 segundos.
entity.metadata.interval.start_time O valor é definido como o campo first_seen se não estiver vazio. Caso contrário, ele será definido como um valor padrão de 1 segundo ou o carimbo de data/hora da entrada de registro bruta.
entity.metadata.product_name O valor é definido como MISP.
entity.metadata.threat.confidence O valor é definido como UNKNOWN_CONFIDENCE se o campo confidence estiver vazio ou for f. Caso contrário, ele será definido como HIGH_CONFIDENCE, MEDIUM_CONFIDENCE ou LOW_CONFIDENCE com base no valor do campo confidence.
entity.metadata.threat.confidence_details Mapeamento direto do campo confidence.
entity.metadata.threat.detection_fields O valor é uma lista de pares de chave-valor extraídos de vários campos no registro bruto.
entity.metadata.vendor_name O valor é definido como MISP.
ioc.active_timerange.end O valor é definido como o campo last_seen se não estiver vazio.
ioc.active_timerange.start O valor é definido como o campo ts1 ou first_seen se eles não estiverem vazios. Caso contrário, ele será definido como um valor padrão de 1 segundo.
ioc.categorization O valor é definido como misp_category IOCs se o registro bruto estiver no formato CSV. Caso contrário, ele será definido como o campo category no objeto Attribute ou log.
ioc.confidence_score Mapeamento direto do campo confidence.
ioc.description O valor é gerado combinando os campos description e event_info, separados por - additional info:.
ioc.domain_and_ports.domain Mapeado se o type ou log_type for domain.
ioc.feed_name O valor é definido como MISP se o campo event_source_org estiver vazio. Caso contrário, ele será definido como o campo event_source_org.
ioc.ip_and_ports.ip_address Mapeado se o campo ip não estiver vazio. O valor é convertido em um endereço IP.
ioc.ip_and_ports.ports Mapeado se o campo port não estiver vazio. O valor é convertido em um número inteiro sem sinal.
ioc.raw_severity Mapeamento direto do campo threat_level.
timestamp O valor é definido como o carimbo de data/hora da entrada de registro bruta.

Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.