Recopila registros de IOC de MISP

Compatible con:

En este documento, se explica cómo transferir registros de IOC de MISP (Malware Information Sharing Platform) a Google Security Operations con Bindplane. El analizador procesa los datos en formatos CSV y JSON. Extrae atributos de IOC, como direcciones IP, dominios, hashes y URLs, y los asigna a un modelo de datos unificado (UDM) junto con detalles de amenazas, como gravedad, confianza y descripciones. El analizador controla las entradas de IOC únicas y múltiples dentro de los datos de entrada, y las normaliza en una salida de UDM coherente.

Antes de comenzar

Asegúrate de cumplir con los siguientes requisitos previos:

  • Es una instancia de Google SecOps.
  • Un host de Linux con systemd.
  • Si se ejecuta detrás de un proxy, asegúrate de que los puertos de firewall estén abiertos según los requisitos del agente de Bindplane.
  • Acceso con privilegios a tu servidor de MISP

Obtén el archivo de autenticación de transferencia de Google SecOps

  1. Accede a la consola de Google SecOps.
  2. Ve a Configuración de SIEM > Agentes de recopilación.
  3. Descarga el archivo de autenticación de transferencia.
    • Guarda el archivo de forma segura en el sistema en el que se instalará BindPlane.

Obtén el ID de cliente de Google SecOps

  1. Accede a la consola de Google SecOps.
  2. Ve a Configuración de SIEM*> Perfil.
  3. Copia y guarda el ID de cliente de la sección Detalles de la organización.

Obtén credenciales de la API de MISP

  1. Accede a la interfaz web de MISP como administrador.
  2. Ve a Administración > List Auth Keys.
  3. Haz clic en Agregar clave de autenticación.
  4. Proporciona los siguientes detalles de configuración:
    • Usuario: Selecciona la cuenta de usuario asociada con la clave.
    • Opcional: IPs permitidas: Especifica las direcciones IP permitidas para la clave.
    • Vencimiento: Deja el campo vacío si no quieres que venza o configúralo según sea necesario.
  5. Haz clic en Enviar.
  6. Copia y guarda la clave de API en una ubicación segura.
  7. Haz clic en Anoté mi clave.

Configura la exportación de datos de MISP

  1. Instala PyMISP en tu servidor de MISP:

    pip3 install pymisp
    
  2. Crea el directorio de exportación:

    sudo mkdir -p /opt/misp/scripts
    sudo mkdir -p /opt/misp/ioc_export
    
  3. Crea el archivo de credenciales /opt/misp/scripts/keys.py:

    misp_url = 'https://<MISP_SERVER_URL>'
    misp_key = '<MISP_API_KEY>'
    misp_verifycert = True
    misp_client_cert = ''
    
    • Reemplaza <MISP_SERVER_URL> por la URL de tu servidor de MISP.
    • Reemplaza <MISP_API_KEY> por la clave de API de los requisitos previos.
  4. Crea la secuencia de comandos de exportación /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. Haz que la secuencia de comandos sea ejecutable:
    sudo chmod +x /opt/misp/scripts/misp_export.py
    

    Programa exportaciones de datos de MISP

    1. Crea exportaciones programadas con crontab:
    sudo crontab -e
    
  5. Agrega las siguientes 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. De manera opcional, programa una extracción de feeds desde 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
    

Instala el agente de BindPlane

Instala el agente de Bindplane en tu sistema operativo Linux según las siguientes instrucciones.

Instalación en Linux

  1. Abre una terminal con privilegios de raíz o sudo.
  2. Ejecuta el siguiente comando:

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

Recursos de instalación adicionales

Configura el agente de BindPlane para que ingiera registros de MISP y los envíe a Google SecOps

  1. Accede al archivo de configuración:

    • Ubica el archivo config.yaml. Por lo general, se encuentra en el directorio /etc/bindplane-agent/ en Linux.
    • Abre el archivo con un editor de texto (por ejemplo, nano, vi).
  2. Edita el archivo config.yaml de la siguiente manera:

    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
    
    • Reemplaza <CUSTOMER_ID> por tu ID de cliente real de los requisitos previos.
    • Actualiza /path/to/ingestion-authentication-file.json a la ruta de acceso en la que se guardó el archivo de autenticación.

Reinicia el agente de Bindplane para aplicar los cambios

  1. Para reiniciar el agente de Bindplane en Linux, ejecuta el siguiente comando:

    sudo systemctl restart observiq-otel-collector
    

Tabla de asignación de UDM

Campo de registro Asignación de UDM Lógica
Attribute.category entity.metadata.threat.category_details Es una asignación directa del campo category en el objeto Attribute.
Attribute.comment entity.metadata.threat.summary Es una asignación directa del campo comment en el objeto Attribute.
Attribute.deleted entity.metadata.threat.detection_fields.value Es una asignación directa del campo deleted en el objeto Attribute. La clave se establece en Attribute deleted.
Attribute.event_id entity.metadata.threat.detection_fields.value Es una asignación directa del campo event_id en el objeto Attribute. La clave se establece en Attribute event_id.
Attribute.first_seen entity.metadata.threat.detection_fields.value Es una asignación directa del campo first_seen en el objeto Attribute. La clave se establece en Attribute first_seen.
Attribute.id entity.metadata.threat.detection_fields.value Es una asignación directa del campo id en el objeto Attribute. La clave se establece en Attribute id o Attribute id $$ según el formato del registro sin procesar.
Attribute.timestamp entity.metadata.threat.detection_fields.value Es una asignación directa del campo timestamp en el objeto Attribute. La clave se establece en Attribute timestamp.
Attribute.to_ids entity.metadata.threat.detection_fields.value Es una asignación directa del campo to_ids en el objeto Attribute. La clave se establece en Attribute to_ids.
Attribute.type entity.metadata.threat.category_details Es una asignación directa del campo type en el objeto Attribute.
Attribute.type log_type Se usa para determinar el tipo de IOC y asignarlo a los campos de UDM correspondientes.
Attribute.uuid entity.metadata.product_entity_id Es una asignación directa del campo uuid en el objeto Attribute.
Attribute.value entity.entity.file.full_path Se asigna si Attribute.type es filename.
Attribute.value entity.entity.file.md5 Se asigna si Attribute.type es md5.
Attribute.value entity.entity.file.sha1 Se asigna si Attribute.type es sha1.
Attribute.value entity.entity.file.sha256 Se asigna si Attribute.type es sha256.
Attribute.value entity.entity.hostname Se asigna si Attribute.type es domain.
Attribute.value entity.entity.ip Se asigna si Attribute.type es ip-dst, ip-dst|port o ip-src. El valor se extrae con un patrón de Grok.
Attribute.value entity.entity.resource.name Se asigna si Attribute.type es mutex.
Attribute.value entity.entity.registry.registry_key Se asigna si Attribute.type es regkey.
Attribute.value entity.entity.url Se asigna si Attribute.type es uri o URL.
column1 entity.metadata.product_entity_id Asignación directa desde la primera columna de los datos CSV.
column14 event_info Se usa para agregar información adicional al campo threat_sr.description.
column16 event_source_org Asignación directa desde la columna 16 en los datos CSV.
column18 threat_level Asignación directa desde la columna 18 en los datos CSV.
column21 descripción Asignación directa desde la columna 21 en los datos CSV.
column3 misp_category Asignación directa de la tercera columna de los datos CSV.
column4 tipo Asignación directa desde la cuarta columna de los datos CSV.
column5 valor Asignación directa desde la quinta columna de los datos CSV.
column6 comentario Asignación directa desde la sexta columna de los datos CSV.
column8 ts1 Asignación directa desde la octava columna de los datos CSV.
descripción ioc.description El valor se genera combinando el campo description con el campo event_info, separados por - additional info:.
descripción entity.metadata.threat.description Asignación directa del campo description.
event_creator_email entity.entity.labels.value Asignación directa del campo event_creator_email. La clave se establece en event_creator_email.
event_source_org ioc.feed_name Asignación directa del campo event_source_org.
event_source_org entity.metadata.threat.threat_feed_name Asignación directa del campo event_source_org.
Feed.publish entity.metadata.threat.detection_fields.value Es una asignación directa del campo publish en el objeto Feed. La clave se establece en Feed publish.
first_seen ioc.active_timerange.start Asignación directa del campo first_seen. El valor se analiza como una fecha.
first_seen entity.metadata.interval.start_time Asignación directa del campo first_seen. El valor se analiza como una fecha.
información entity.metadata.description Asignación directa del campo info.
last_seen ioc.active_timerange.end Asignación directa del campo last_seen. El valor se analiza como una fecha.
log.category ioc.categorization Es una asignación directa del campo category en el objeto log.
log.category entity.metadata.threat.category_details Es una asignación directa del campo category en el objeto log.
log.comment entity.entity.file.full_path Se asigna si log.type es filename y el campo comment no es Artifacts dropped.
log.comment entity.metadata.threat.detection_fields.value Es una asignación directa del campo comment en el objeto log. La clave se establece en Attribute comment.
log.comment entity.metadata.threat.summary Es una asignación directa del campo comment en el objeto log.
log.deleted entity.metadata.threat.detection_fields.value Es una asignación directa del campo deleted en el objeto log. La clave se establece en Attribute deleted.
log.event_id entity.metadata.threat.detection_fields.value Es una asignación directa del campo event_id en el objeto log. La clave se establece en Attribute event_id.
log.first_seen entity.metadata.threat.detection_fields.value Es una asignación directa del campo first_seen en el objeto log. La clave se establece en Attribute first_seen.
log.id entity.metadata.threat.detection_fields.value Es una asignación directa del campo id en el objeto log. La clave se establece en Attribute id.
log.timestamp entity.metadata.threat.detection_fields.value Es una asignación directa del campo timestamp en el objeto log. La clave se establece en Attribute timestamp.
log.to_ids entity.metadata.threat.detection_fields.value Es una asignación directa del campo to_ids en el objeto log. La clave se establece en Attribute to_ids.
log.type ioc.categorization Es una asignación directa del campo type en el objeto log.
log.type log_type Se usa para determinar el tipo de IOC y asignarlo a los campos de UDM correspondientes.
log.uuid entity.metadata.product_entity_id Es una asignación directa del campo uuid en el objeto log.
log.value entity.entity.file.full_path Se asigna si log.type es filename.
log.value entity.entity.file.md5 Se asigna si log.type es md5.
log.value entity.entity.file.sha1 Se asigna si log.type es sha1.
log.value entity.entity.file.sha256 Se asigna si log.type es sha256.
log.value entity.entity.hostname Se asigna si log.type es domain.
log.value entity.entity.ip Se asigna si log.type es ip-dst, ip-dst|port o ip-src. El valor se extrae con un patrón de Grok.
log.value entity.entity.resource.name Se asigna si log.type es mutex.
log.value entity.entity.registry.registry_key Se asigna si log.type es regkey.
log.value entity.entity.url Se asigna si log.type es uri o url.
log.value ioc.domain_and_ports.domain Se asigna si log.type es domain.
log.value entity.entity.user.email_addresses Se asigna si log.type es threat-actor.
misp_category entity.metadata.threat.category_details Asignación directa del campo misp_category.
Org.name entity.metadata.threat.detection_fields.value Es una asignación directa del campo name en el objeto Org. La clave se establece en Org name.
published entity.metadata.threat.detection_fields.value Asignación directa del campo published. La clave se establece en published.
Tag.colour entity.metadata.threat.detection_fields.value Es una asignación directa del campo colour en el objeto Tag. La clave se establece en tag colour.
Tag.exportable entity.metadata.threat.detection_fields.value Es una asignación directa del campo exportable en el objeto Tag. La clave se establece en tag exportable.
Tag.hide_tag entity.metadata.threat.detection_fields.value Es una asignación directa del campo hide_tag en el objeto Tag. La clave se establece en tag hide_tag.
Tag.id entity.metadata.threat.detection_fields.value Es una asignación directa del campo id en el objeto Tag. La clave se establece en tag id.
Tag.is_custom_galaxy entity.metadata.threat.detection_fields.value Es una asignación directa del campo is_custom_galaxy en el objeto Tag. La clave se establece en tag is_custom_galaxy.
Tag.is_galaxy entity.metadata.threat.detection_fields.value Es una asignación directa del campo is_galaxy en el objeto Tag. La clave se establece en tag is_galaxy.
Tag.isinherited entity.metadata.threat.detection_fields.value Es una asignación directa del campo isinherited en el objeto Tag. La clave se establece en tag isinherited.
Tag.name entity.metadata.threat.detection_fields.value Es una asignación directa del campo name en el objeto Tag. La clave se establece en tag name.
Tag.numerical_value entity.metadata.threat.detection_fields.value Es una asignación directa del campo numerical_value en el objeto Tag. La clave se establece en tag numerical_value.
Tag.user_id entity.metadata.threat.detection_fields.value Es una asignación directa del campo user_id en el objeto Tag. La clave se establece en tag user_id.
threat_level ioc.raw_severity Asignación directa del campo threat_level.
threat_level entity.metadata.threat.severity_details Asignación directa del campo threat_level.
threat_level_id entity.entity.labels.value Asignación directa del campo threat_level_id. La clave se establece en threat_level_id.
ts1 ioc.active_timerange.start Asignación directa del campo ts1. El valor se analiza como una fecha.
ts1 entity.metadata.interval.start_time Asignación directa del campo ts1. El valor se analiza como una fecha.
entity.entity.file.full_path Se asigna si type es filename.
entity.entity.file.md5 Se asigna si type es md5.
entity.entity.file.sha1 Se asigna si type es sha1.
entity.entity.file.sha256 Se asigna si type es sha256.
entity.entity.hostname Se asigna si type es domain.
entity.entity.ip Se asigna si type es ip-dst, ip-dst|port o ip-src. El valor se extrae con un patrón de Grok.
entity.entity.port Se asigna si el campo port no está vacío. El valor se convierte en un número entero.
entity.entity.resource.name Se asigna si type es mutex.
entity.entity.resource.resource_subtype Se asigna si type es regkey. El valor se establece en regkey.
entity.entity.resource.resource_type Se asigna si type es mutex o regkey. El valor se establece en MUTEX o STORAGE_OBJECT, respectivamente.
entity.entity.registry.registry_key Se asigna si type es regkey.
entity.entity.url Se asigna si type es uri o url.
entity.metadata.collected_timestamp El valor se establece en la marca de tiempo de la entrada de registro sin procesar.
entity.metadata.description El valor se establece en el campo type si el registro sin procesar está en formato CSV. De lo contrario, se establece en el campo info.
entity.metadata.entity_type El valor se determina según el campo type o log_type. Puede ser DOMAIN_NAME, FILE, IP_ADDRESS, MUTEX, RESOURCE o URL.
entity.metadata.interval.end_time El valor se establece en un valor predeterminado de 253402300799 segundos.
entity.metadata.interval.start_time El valor se establece en el campo first_seen si no está vacío. De lo contrario, se establece en un valor predeterminado de 1 segundo o en la marca de tiempo de la entrada de registro sin procesar.
entity.metadata.product_name El valor se establece en MISP.
entity.metadata.threat.confidence El valor se establece en UNKNOWN_CONFIDENCE si el campo confidence está vacío o es f. De lo contrario, se establece en HIGH_CONFIDENCE, MEDIUM_CONFIDENCE o LOW_CONFIDENCE según el valor del campo confidence.
entity.metadata.threat.confidence_details Asignación directa del campo confidence.
entity.metadata.threat.detection_fields El valor es una lista de pares clave-valor extraídos de varios campos del registro sin procesar.
entity.metadata.vendor_name El valor se establece en MISP.
ioc.active_timerange.end El valor se establece en el campo last_seen si no está vacío.
ioc.active_timerange.start El valor se establece en el campo ts1 o first_seen si no están vacíos. De lo contrario, se establece en un valor predeterminado de 1 segundo.
ioc.categorization El valor se establece en misp_category IOCs si el registro sin procesar está en formato CSV. De lo contrario, se establece en el campo category del objeto Attribute o log.
ioc.confidence_score Asignación directa del campo confidence.
ioc.description El valor se genera combinando el campo description con el campo event_info, separados por - additional info:.
ioc.domain_and_ports.domain Se asigna si type o log_type es domain.
ioc.feed_name El valor se establece en MISP si el campo event_source_org está vacío. De lo contrario, se establece en el campo event_source_org.
ioc.ip_and_ports.ip_address Se asigna si el campo ip no está vacío. El valor se convierte en una dirección IP.
ioc.ip_and_ports.ports Se asigna si el campo port no está vacío. El valor se convierte en un número entero sin signo.
ioc.raw_severity Asignación directa del campo threat_level.
timestamp El valor se establece en la marca de tiempo de la entrada de registro sin procesar.

¿Necesitas más ayuda? Obtén respuestas de miembros de la comunidad y profesionales de Google SecOps.