Recolha registos de IOCs do MISP

Compatível com:

Este documento explica como carregar registos de IOCs (Indicadores de comprometimento) da MISP (Malware Information Sharing Platform) para o Google Security Operations através do Bindplane. O analisador processa os dados nos formatos CSV e JSON. Extrai atributos de IOCs, como endereços IP, domínios, hashes e URLs, mapeando-os para um modelo de dados unificado (UDM) juntamente com detalhes de ameaças, como gravidade, confiança e descrições. O analisador processa entradas de IOCs únicas e múltiplas nos dados de entrada, normalizando-as numa saída de UDM consistente.

Antes de começar

Certifique-se de que tem os seguintes pré-requisitos:

  • Uma instância do Google SecOps.
  • Um anfitrião Linux com systemd.
  • Se estiver a ser executado através de um proxy, certifique-se de que as portas da firewall estão abertas de acordo com os requisitos do agente Bindplane.
  • Acesso privilegiado ao seu servidor MISP.

Obtenha o ficheiro de autenticação de carregamento do Google SecOps

  1. Inicie sessão na consola Google SecOps.
  2. Aceda a Definições do SIEM > Agentes de recolha.
  3. Transfira o ficheiro de autenticação de carregamento.
    • Guarde o ficheiro de forma segura no sistema onde o Bindplane vai ser instalado.

Obtenha o ID de cliente do Google SecOps

  1. Inicie sessão na consola Google SecOps.
  2. Aceda a Definições do SIEM*> Perfil.
  3. Copie e guarde o ID do cliente da secção Detalhes da organização.

Obtenha credenciais da API MISP

  1. Inicie sessão na interface Web do MISP como administrador.
  2. Aceda a Administração > Listar chaves de autorização.
  3. Clique em Adicionar chave de autenticação.
  4. Indique os seguintes detalhes de configuração:
    • Utilizador: selecione a conta de utilizador associada à chave.
    • Opcional: IPs permitidos: especifique os endereços IP permitidos para a chave.
    • Validade: deixe vazio para não ter validade ou defina conforme necessário.
  5. Clique em Enviar.
  6. Copie e guarde a chave da API num local seguro.
  7. Clique em Tomei nota da minha chave.

Configure 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 ficheiro 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 seu servidor MISP.
    • Substitua <MISP_API_KEY> pela chave 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
    

    Agende exportações de dados do MISP

    1. Crie exportações agendadas com o crontab:
    sudo crontab -e
    
  5. Adicione as seguintes entradas 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. Opcionalmente, agende uma obtenção de feeds a partir 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
    

Instale o agente do Bindplane

Instale o agente Bindplane no seu sistema operativo Linux de acordo com as seguintes instruções.

Instalação do Linux

  1. Abra um terminal com privilégios de raiz ou sudo.
  2. Execute o seguinte comando:

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

Recursos de instalação adicionais

Configure o agente Bindplane para carregar registos MISP e enviá-los para o Google SecOps

  1. Aceda ao ficheiro de configuração:

    • Localize o ficheiro config.yaml. Normalmente, encontra-se no diretório /etc/bindplane-agent/ no Linux.
    • Abra o ficheiro com um editor de texto (por exemplo, nano ou vi).
  2. Edite o ficheiro 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 seu ID de cliente real dos pré-requisitos.
    • Atualize /path/to/ingestion-authentication-file.json para o caminho onde o ficheiro de autenticação foi guardado.

Reinicie o agente do Bindplane para aplicar as alterações

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

    sudo systemctl restart observiq-otel-collector
    

Tabela de mapeamento do UDM

Campo de registo 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 tecla está definida como Attribute deleted.
Attribute.event_id entity.metadata.threat.detection_fields.value Mapeamento direto do campo event_id no objeto Attribute. A tecla 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 tecla está definida como Attribute first_seen.
Attribute.id entity.metadata.threat.detection_fields.value Mapeamento direto do campo id no objeto Attribute. A chave está definida como Attribute id ou Attribute id $$, consoante o formato do registo não processado.
Attribute.timestamp entity.metadata.threat.detection_fields.value Mapeamento direto do campo timestamp no objeto Attribute. A tecla está definida como Attribute timestamp.
Attribute.to_ids entity.metadata.threat.detection_fields.value Mapeamento direto do campo to_ids no objeto Attribute. A tecla 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 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 através de 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 elemento Attribute.type for uri ou URL.
coluna1 entity.metadata.product_entity_id Mapeamento direto a partir da primeira coluna nos dados CSV.
column14 event_info Usado para anexar informações adicionais 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.
coluna3 misp_category Mapeamento direto a partir da terceira coluna nos dados CSV.
column4 escrever Mapeamento direto da quarta coluna nos dados CSV.
column5 valor Mapeamento direto a partir da quinta coluna nos dados CSV.
column6 comentário Mapeamento direto a partir da sexta coluna nos dados CSV.
column8 ts1 Mapeamento direto a partir da oitava coluna nos dados CSV.
descrição ioc.description O valor é gerado combinando o campo description com o campo 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 tecla 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 tecla 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ção 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 o campo 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 tecla 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 tecla está definida como Attribute deleted.
log.event_id entity.metadata.threat.detection_fields.value Mapeamento direto do campo event_id no objeto log. A tecla 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 tecla está definida como Attribute first_seen.
log.id entity.metadata.threat.detection_fields.value Mapeamento direto do campo id no objeto log. A tecla está definida como Attribute id.
log.timestamp entity.metadata.threat.detection_fields.value Mapeamento direto do campo timestamp no objeto log. A tecla está definida como Attribute timestamp.
log.to_ids entity.metadata.threat.detection_fields.value Mapeamento direto do campo to_ids no objeto log. A tecla 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 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 através de 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 elemento 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 tecla está definida como Org name.
publicados entity.metadata.threat.detection_fields.value Mapeamento direto do campo published. A tecla está definida como published.
Tag.colour entity.metadata.threat.detection_fields.value Mapeamento direto do campo colour no objeto Tag. A tecla está definida como tag colour.
Tag.exportable entity.metadata.threat.detection_fields.value Mapeamento direto do campo exportable no objeto Tag. A tecla está definida como tag exportable.
Tag.hide_tag entity.metadata.threat.detection_fields.value Mapeamento direto do campo hide_tag no objeto Tag. A tecla está definida como tag hide_tag.
Tag.id entity.metadata.threat.detection_fields.value Mapeamento direto do campo id no objeto Tag. A tecla 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 tecla 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 tecla está definida como tag is_galaxy.
Tag.isinherited entity.metadata.threat.detection_fields.value Mapeamento direto do campo isinherited no objeto Tag. A tecla está definida como tag isinherited.
Tag.name entity.metadata.threat.detection_fields.value Mapeamento direto do campo name no objeto Tag. A tecla está definida como tag name.
Tag.numerical_value entity.metadata.threat.detection_fields.value Mapeamento direto do campo numerical_value no objeto Tag. A tecla 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 tecla 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 tecla 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 através de um padrão grok.
entity.entity.port Mapeado se o campo port não estiver vazio. O valor é convertido num 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 elemento type for mutex ou regkey. O valor é definido como MUTEX ou STORAGE_OBJECT, respetivamente.
entity.entity.registry.registry_key Mapeado se o type for regkey.
entity.entity.url Mapeado se o elemento type for uri ou url.
entity.metadata.collected_timestamp O valor é definido como a data/hora da entrada do registo não processado.
entity.metadata.description O valor é definido como o campo type se o registo não processado estiver no formato CSV. Caso contrário, é definido para 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 está definido para um valor predefinido de 253402300799 segundos.
entity.metadata.interval.start_time O valor é definido para o campo first_seen se não estiver vazio. Caso contrário, é definido como um valor predefinido de 1 segundo ou a data/hora da entrada do registo não processado.
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, é 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 registo não processado.
entity.metadata.vendor_name O valor é definido como MISP.
ioc.active_timerange.end O valor é definido para o campo last_seen se não estiver vazio.
ioc.active_timerange.start O valor é definido como o campo ts1 ou first_seen, se não estiverem vazios. Caso contrário, é definido um valor predefinido de 1 segundo.
ioc.categorization O valor é definido como misp_category IOCs se o registo não processado estiver no formato CSV. Caso contrário, é definido para o campo category no objeto Attribute ou log.
ioc.confidence_score Mapeamento direto do campo confidence.
ioc.description O valor é gerado combinando o campo description com o campo event_info, separados por - additional info:.
ioc.domain_and_ports.domain Mapeado se o elemento 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, é definido para o campo event_source_org.
ioc.ip_and_ports.ip_address Mapeado se o campo ip não estiver vazio. O valor é convertido num endereço IP.
ioc.ip_and_ports.ports Mapeado se o campo port não estiver vazio. O valor é convertido num número inteiro sem sinal.
ioc.raw_severity Mapeamento direto do campo threat_level.
timestamp O valor é definido como a data/hora da entrada do registo não processado.

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