Recopila registros de inteligencia sobre amenazas de ESET

Compatible con:

En este documento, se explica cómo transferir registros de ESET Threat Intelligence a Google Security Operations con Google Cloud Storage V2, una función de Cloud Run y Cloud Scheduler.

ESET Threat Intelligence (ETI) proporciona información basada en evidencia y consejos prácticos sobre amenazas existentes o emergentes. Los servicios de la ETI te advierten sobre software o actividad maliciosos que podrían amenazar a tu organización o a sus clientes. El servicio entrega datos de inteligencia sobre amenazas a través de feeds de TAXII 2.1 en formato STIX 2.1, incluidos los IoC de APT, los C&C y los objetivos de botnets, los dominios maliciosos, las IPs, las URLs, los archivos, las URLs de phishing, el ransomware y las amenazas para Android.

Antes de comenzar

Asegúrate de cumplir con los siguientes requisitos previos:

  • Una instancia de Google SecOps
  • Un proyecto de Google Cloud con las siguientes APIs habilitadas:
    • API de Cloud Storage
    • API de funciones de Cloud Run
    • API de Cloud Scheduler
    • API de Cloud Pub/Sub
  • Permisos para crear y administrar buckets de Google Cloud Storage, funciones de Cloud Run, temas de Pub/Sub y trabajos de Cloud Scheduler
  • Permisos para administrar políticas de IAM en buckets de Google Cloud Storage
  • Una suscripción activa a ESET Threat Intelligence
  • Acceso al portal de ESET Threat Intelligence en https://eti.eset.com

Crear un bucket de Google Cloud Storage

  1. Ve a la consola de Google Cloud.
  2. Selecciona tu proyecto o crea uno nuevo.
  3. En el menú de navegación, ve a Cloud Storage > Buckets.
  4. Haz clic en Crear bucket.
  5. Proporciona los siguientes detalles de configuración:

    Configuración Valor
    Asigna un nombre a tu bucket Ingresa un nombre global único (por ejemplo, eset-ti-logs).
    Tipo de ubicación Elige según tus necesidades (región, birregional, multirregional)
    Ubicación Selecciona la ubicación (por ejemplo, us-central1).
    Clase de almacenamiento Estándar (recomendado para los registros a los que se accede con frecuencia)
    Control de acceso Uniforme (recomendado)
    Herramientas de protección Opcional: Habilita el control de versiones de objetos o la política de retención
  6. Haz clic en Crear.

Recopila las credenciales de TAXII de ESET Threat Intelligence

Para habilitar la función de Cloud Run para recuperar datos de inteligencia sobre amenazas, debes activar los feeds de TAXII y generar credenciales de TAXII desde el portal de ETI.

Activa los feeds de TAXII

  1. Accede al portal de ESET Threat Intelligence en https://eti.eset.com.
  2. Ve a Feeds de datos en el menú principal.
  3. Haz clic en el ícono de tres puntos junto al feed de datos que deseas activar.
  4. Selecciona Habilitar feed.
  5. Repite los pasos 3 y 4 para cada feed que desees transferir a Google SecOps.

Cómo generar credenciales de TAXII

  1. En el portal de ESET Threat Intelligence, ve a Admin Settings > Access Credentials.
  2. Haz clic en Generate TAXII Credentials.
  3. En el diálogo que aparece, copia y guarda los siguientes valores:

    • Nombre de usuario: Tu nombre de usuario de TAXII
    • Contraseña: Tu contraseña de TAXII

Registra los detalles del feed de TAXII

Después de activar los feeds y generar las credenciales, registra la siguiente información para cada feed que desees transferir:

  1. En el portal de ESET Threat Intelligence, ve a Feeds de datos.
  2. Haz clic en el ícono de tres puntos junto a un feed activado.
  3. Selecciona Show Data Feed detail.
  4. En el panel lateral, anota los siguientes valores:

    • Nombre del feed de TAXII: Es el identificador del feed (por ejemplo, botnet stix 2.1).
    • ID de TAXII 2: Es el ID de la colección (por ejemplo, 0abb06690b0b47e49cd7794396b76b20).
    • URL del feed de TAXII 2: Es la URL completa de la colección.

Feeds de TAXII disponibles

  • ESET Threat Intelligence proporciona los siguientes feeds de TAXII 2.1:

    Nombre del feed Nombre del feed de TAXII ID de la colección
    Feed de robo de información de Android androidinfostealer stix 2.1 9ee501cde0c44d6db4ae995fead1a7c8
    Feeds de amenazas de Android androidthreats stix 2.1 daf3de8fab144552a1cb5af054ed07ee
    IoC de APT apt stix 2.1 97e3eb74ae5f46dd9e22f677a6938ee7
    Feed de botnets botnet stix 2.1 0abb06690b0b47e49cd7794396b76b20
    Botnet - C&C botnet.cc stix 2.1 d1923a526e8f400dbb301259240ee3d5
    Botnet - Target botnet.target stix 2.1 61b6e4f9153e411ca7a9982a2c6ae788
    Feed de estafas de criptomonedas cryptoscam stix 2.1 2c183ce9551a43338c6cc2ed7c2a704d
    Feed de dominio dominio stix 2.1 a34aa0a4f9de419582a883863503f9c4
    Feed de IoC de delitos electrónicos ecrime stix 2.1 08059376eac84ec4a076cfd682493f91
    Feeds de IP ip stix 2.1 baaed2a92335418aa753fe944e13c23a
    Archivos adjuntos maliciosos de correos electrónicos emailattachments stix 2.1 c0d56cf7f81d482eb97fd46beaa4bae0
    Feed de archivos maliciosos archivo stix 2.1 ee6a153ed77e4ec3ab21e76cc2074b9f
    Feeds de URLs de phishing phishingurl stix 2.1 d0a6c0f962dd4dd2b3eeb96b18612584
    Feed de archivos de adware de PUA puaadware stix 2.1 d1bfc81202fc4c6599326771ec2da41d
    Feed de archivos de apps de doble uso de la PUA puadualapps stix 2.1 970a7d0039ac4668addf058cd9feb953
    Feed de ransomware ransomware stix 2.1 8d3490d688ce4a989aee9af5c680d8bf
    Feeds de URLs de estafas scamurl stix 2.1 2130adc3c67c43f9a3664b187931375e
    Feed de smishing smishing stix 2.1 330ad7d0c736476babe5e49077b96c95
    Feed de estafas por SMS smsscam stix 2.1 6e20217a2e1246b8ab11be29f759f716
    Feed de URLs url stix 2.1 1d3208c143be49da8130f5a66fd3a0fa

Crea una cuenta de servicio para la función de Cloud Run

  1. En la consola de Google Cloud, ve a IAM y administración > Cuentas de servicio.
  2. Haz clic en Crear cuenta de servicio.
  3. Proporciona los siguientes detalles de configuración:

    • Nombre de la cuenta de servicio: Ingresa eset-ti-collector.
    • Descripción de la cuenta de servicio: Ingresa Service account for ESET Threat Intelligence Cloud Run function to write STIX objects to GCS.
  4. Haz clic en Crear y continuar.

  5. En la sección Otorga a esta cuenta de servicio acceso al proyecto, agrega los siguientes roles:

    1. Haz clic en Seleccionar un rol, busca Administrador de objetos de Storage y selecciónalo.
    2. Haz clic en Agregar otro rol, busca Invocador de Cloud Run y selecciónalo.
  6. Haz clic en Continuar.

  7. Haz clic en Listo.

Otorga permisos de IAM en el bucket de Google Cloud Storage

  1. Ve a Cloud Storage > Buckets.
  2. Haz clic en el nombre de tu bucket (por ejemplo, eset-ti-logs).
  3. Ve a la pestaña Permisos.
  4. Haz clic en Otorgar acceso.
  5. Proporciona los siguientes detalles de configuración:

    • Agregar principales: Ingresa el correo electrónico de la cuenta de servicio (por ejemplo, eset-ti-collector@PROJECT_ID.iam.gserviceaccount.com).
    • Asignar roles: Selecciona Administrador de objetos de almacenamiento.
  6. Haz clic en Guardar.

Crear tema de Pub/Sub

El tema de Pub/Sub activa la función de Cloud Run cuando Cloud Scheduler publica un mensaje.

  1. En la consola de Google Cloud, ve a Pub/Sub > Temas.
  2. Haz clic en Crear tema.
  3. Proporciona los siguientes detalles de configuración:
    • ID del tema: Ingresa eset-ti-trigger.
    • Agregar una suscripción predeterminada: Deja seleccionada esta opción.
  4. Haz clic en Crear.

Crea la función de Cloud Run

  1. En la consola de Google Cloud, ve a Cloud Run functions.
  2. Haz clic en Crear función.
  3. Proporciona los siguientes detalles de configuración:

    Configuración Valor
    Entorno 2ª gen.
    Nombre de la función eset-ti-collector
    Región Selecciona la misma región que tu bucket de GCS.
    Tipo de activador Cloud Pub/Sub
    Tema de Pub/Sub eset-ti-trigger
    Memoria asignada 512 MiB
    Tiempo de espera 540 segundos
    Cuenta de servicio del entorno de ejecución eset-ti-collector
  4. Haz clic en Siguiente.

  5. Establece Entorno de ejecución en Python 3.12.

  6. Establece el Punto de entrada como main.

  7. En el archivo requirements.txt, agrega las siguientes dependencias:

    functions-framework==3.*
    google-cloud-storage==2.*
    urllib3==2.*
    
  8. En el archivo main.py, pega el siguiente código:

    import functions_framework
    import json
    import os
    import logging
    import time
    import urllib3
    from datetime import datetime, timedelta, timezone
    from google.cloud import storage
    
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    
    HTTP = urllib3.PoolManager(retries=False)
    storage_client = storage.Client()
    
    API_ROOT = "https://taxii.eset.com/taxii2/643f4eb5-f8b7-46a3-a606-6d61d5ce223a"
    TAXII_CONTENT_TYPE = "application/taxii+json;version=2.1"
    
    def _load_state(bucket_name: str, state_key: str, lookback_hours: int) -> str:
        """Return ISO8601 checkpoint (UTC)."""
        try:
            bucket = storage_client.bucket(bucket_name)
            blob = bucket.blob(state_key)
            if blob.exists():
                state_data = blob.download_as_text()
                state = json.loads(state_data)
                ts = state.get("last_poll_time")
                if ts:
                    logger.info(f"Loaded state: {ts}")
                    return ts
        except Exception as e:
            logger.warning(f"State read error: {e}")
        default_ts = (
            datetime.now(timezone.utc) - timedelta(hours=lookback_hours)
        ).strftime("%Y-%m-%dT%H:%M:%S.000Z")
        logger.info(f"No previous state found, using lookback: {default_ts}")
        return default_ts
    
    def _save_state(bucket_name: str, state_key: str, ts: str) -> None:
        """Persist the checkpoint to GCS."""
        bucket = storage_client.bucket(bucket_name)
        blob = bucket.blob(state_key)
        blob.upload_from_string(
            json.dumps({"last_poll_time": ts}),
            content_type="application/json",
        )
        logger.info(f"Saved state: {ts}")
    
    def _fetch_objects(
        username: str,
        password: str,
        collection_id: str,
        added_after: str,
        max_records: int,
    ) -> list:
        """Query TAXII 2.1 collection objects with pagination."""
        url = f"{API_ROOT}/collections/{collection_id}/objects/"
        headers = urllib3.make_headers(basic_auth=f"{username}:{password}")
        headers["Accept"] = TAXII_CONTENT_TYPE
        headers["User-Agent"] = "Chronicle-ESET-TI-GCS/1.0"
    
        all_objects = []
        params = {"added_after": added_after}
    
        while True:
            qs = "&".join(f"{k}={v}" for k, v in params.items())
            request_url = f"{url}?{qs}" if qs else url
    
            for attempt in range(3):
                try:
                    resp = HTTP.request("GET", request_url, headers=headers)
                    break
                except Exception as e:
                    wait = 2 ** (attempt + 1)
                    logger.warning(f"Request error: {e}, retrying in {wait}s")
                    time.sleep(wait)
            else:
                raise RuntimeError("Exceeded retry budget for TAXII API")
    
            if resp.status == 401:
                raise RuntimeError("Authentication failed: check TAXII credentials")
            if resp.status == 404:
                raise RuntimeError(
                    f"Collection not found: {collection_id}"
                )
            if resp.status not in (200, 206):
                raise RuntimeError(
                    f"TAXII API error {resp.status}: {resp.data[:500]}"
                )
    
            body = json.loads(resp.data.decode("utf-8"))
            objects = body.get("objects", [])
            all_objects.extend(objects)
            logger.info(
                f"Fetched {len(objects)} objects (total: {len(all_objects)})"
            )
    
            if len(all_objects) >= max_records:
                logger.info(f"Reached max_records limit: {max_records}")
                all_objects = all_objects[:max_records]
                break
    
            more = body.get("more", False)
            next_param = body.get("next")
            if more and next_param:
                params = {"added_after": added_after, "next": next_param}
            else:
                break
    
        return all_objects
    
    @functions_framework.cloud_event
    def main(cloud_event):
        """Cloud Run function entry point triggered by Pub/Sub."""
        bucket_name = os.environ["GCS_BUCKET"]
        prefix = os.environ.get("GCS_PREFIX", "eset-ti")
        state_key = os.environ.get("STATE_KEY", "eset-ti/state.json")
        username = os.environ["TAXII_USERNAME"]
        password = os.environ["TAXII_PASSWORD"]
        collection_id = os.environ["COLLECTION_ID"]
        max_records = int(os.environ.get("MAX_RECORDS", "10000"))
        lookback_hours = int(os.environ.get("LOOKBACK_HOURS", "48"))
    
        try:
            last_poll = _load_state(bucket_name, state_key, lookback_hours)
            objects = _fetch_objects(
                username, password, collection_id, last_poll, max_records
            )
    
            if not objects:
                logger.info("No new STIX objects found")
                return "No new objects", 200
    
            now_str = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
            blob_path = (
                f"{prefix}/eset_ti_{collection_id}_{now_str}.json"
            )
            ndjson_body = "\n".join(
                json.dumps(obj, separators=(",", ":")) for obj in objects
            )
    
            bucket = storage_client.bucket(bucket_name)
            blob = bucket.blob(blob_path)
            blob.upload_from_string(
                ndjson_body, content_type="application/x-ndjson"
            )
    
            new_poll_time = datetime.now(timezone.utc).strftime(
                "%Y-%m-%dT%H:%M:%S.000Z"
            )
            _save_state(bucket_name, state_key, new_poll_time)
    
            msg = (
                f"Wrote {len(objects)} STIX objects to "
                f"gs://{bucket_name}/{blob_path}"
            )
            logger.info(msg)
            return msg, 200
    
        except Exception as e:
            logger.error(f"Error collecting ESET TI: {e}")
            raise
    
  9. Haz clic en Implementar.

  10. Espera a que se implemente la función. El estado cambia a una marca de verificación verde cuando se completa la implementación.

Configure las variables de entorno

  1. Después de implementar la función, ve a Cloud Run Functions > eset-ti-collector.
  2. Haz clic en Editar e implementar una nueva revisión.
  3. Haz clic en la pestaña Variables y secretos (o expande Configuración del entorno de ejecución, la compilación, las conexiones y la seguridad para la 1ª gen.).
  4. Agrega las siguientes variables de entorno:

    Clave Valor de ejemplo
    GCS_BUCKET eset-ti-logs
    GCS_PREFIX eset-ti
    STATE_KEY eset-ti/state.json
    TAXII_USERNAME Tu nombre de usuario de TAXII del portal de ETI
    TAXII_PASSWORD Tu contraseña de TAXII del portal de ETI
    COLLECTION_ID 0abb06690b0b47e49cd7794396b76b20
    MAX_RECORDS 10000
    LOOKBACK_HOURS 48
  5. Haz clic en Implementar.

Crea un trabajo de Cloud Scheduler

Cloud Scheduler publica un mensaje en el tema de Pub/Sub según una programación, lo que activa la función de Cloud Run para sondear ESET Threat Intelligence en busca de nuevos objetos STIX.

  1. En la consola de Google Cloud, ve a Cloud Scheduler.
  2. Haz clic en Crear trabajo.
  3. Proporciona los siguientes detalles de configuración:

    Configuración Valor
    Nombre eset-ti-poll
    Región Selecciona la misma región que tu función.
    Frecuencia 0 */1 * * * (cada hora)
    Zona horaria Selecciona tu zona horaria (por ejemplo, UTC).
  4. Haz clic en Continuar.

  5. En la sección Configura la ejecución, haz lo siguiente:

    • Tipo de destino: Selecciona Pub/Sub.
    • Tema: Selecciona eset-ti-trigger.
    • Cuerpo del mensaje: Ingresa {"poll": true}.
  6. Haz clic en Crear.

Verifica la función de Cloud Run

  1. En Cloud Scheduler, busca el trabajo eset-ti-poll.
  2. Haz clic en Forzar ejecución para activar una ejecución inmediata.
  3. Ve a Cloud Run Functions > eset-ti-collector > Registros.
  4. Verifica que la función se haya ejecutado correctamente. Para ello, busca entradas de registro como las siguientes:

    Fetched 250 objects (total: 250)
    Wrote 250 STIX objects to gs://eset-ti-logs/eset-ti/eset_ti_0abb06690b0b47e49cd7794396b76b20_20250115_103000.json
    
  5. Ve a Cloud Storage > Buckets > eset-ti-logs.

  6. Navega al prefijo eset-ti/.

  7. Verifica que se creen archivos NDJSON con objetos STIX.

Recupera la cuenta de servicio de Google SecOps y configura el feed

Las Operaciones de seguridad de Google usan una cuenta de servicio única para leer datos de tu bucket de GCS. Debes otorgar acceso a tu bucket a esta cuenta de servicio.

Obtén el correo electrónico de la cuenta de servicio

  1. Ve a Configuración de SIEM > Feeds.
  2. Haz clic en Agregar feed nuevo.
  3. Haz clic en Configura un feed único.
  4. En el campo Nombre del feed, ingresa un nombre para el feed (por ejemplo, ESET Threat Intelligence - Botnet).
  5. Selecciona Google Cloud Storage V2 como el Tipo de fuente.
  6. Selecciona ESET Threat Intelligence como el Tipo de registro.
  7. Haz clic en Obtener cuenta de servicio. Se mostrará un correo electrónico único de la cuenta de servicio, por ejemplo:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. Copia esta dirección de correo electrónico para usarla en el siguiente paso.

  9. Haz clic en Siguiente.

  10. Especifica valores para los siguientes parámetros de entrada:

    • URL del bucket de almacenamiento: Ingresa el URI del bucket de GCS con la ruta de acceso del prefijo:

      gs://eset-ti-logs/eset-ti/
      
    • Opción de borrado de la fuente: Selecciona la opción de borrado según tu preferencia:

      • Nunca: Nunca borra ningún archivo después de las transferencias (se recomienda para las pruebas).
      • Borrar archivos transferidos: Borra los archivos después de la transferencia exitosa.
      • Borrar los archivos transferidos y los directorios vacíos: Borra los archivos y los directorios vacíos después de la transferencia exitosa.

    • Antigüedad máxima del archivo: Incluye los archivos modificados en la cantidad de días más reciente (el valor predeterminado es 180 días).

    • Espacio de nombres del recurso: Es el espacio de nombres del recurso.

    • Etiquetas de transferencia: Es la etiqueta que se aplicará a los eventos de este feed (por ejemplo, ESET_IOC).

  11. Haz clic en Siguiente.

  12. Revisa la nueva configuración del feed en la pantalla Finalizar y, luego, haz clic en Enviar.

Otorga permisos de IAM a la cuenta de servicio de Google SecOps

La cuenta de servicio de Google SecOps necesita el rol de visualizador de objetos de Storage en tu bucket de Google Cloud Storage.

  1. Ve a Cloud Storage > Buckets.
  2. Haz clic en el nombre de tu bucket (por ejemplo, eset-ti-logs).
  3. Ve a la pestaña Permisos.
  4. Haz clic en Otorgar acceso.
  5. Proporciona los siguientes detalles de configuración:
    • Agregar principales: Pega el correo electrónico de la cuenta de servicio de Google SecOps.
    • Asignar roles: Selecciona Visualizador de objetos de Storage.
  6. Haz clic en Guardar.

Tabla de asignación de UDM

Campo de registro Asignación de UDM Lógica
cuando metadata.event_timestamp Marca de tiempo en la que ocurrió el evento
metadata.event_type Tipo de evento (por ejemplo, USER_LOGIN, NETWORK_CONNECTION)
messageid metadata.id Identificador único para el evento
protocolo network.ip_protocol Protocolo IP (por ejemplo, TCP o UDP)
deviceName principal.hostname Nombre de host de origen
srcAddr principal.ip Dirección IP de origen de la conexión
srcPort principal.port Número de puerto de origen
acción security_result.action Acción que realiza el producto de seguridad (por ejemplo, ALLOW, BLOCK)
dstAddr target.ip Dirección IP de destino
dstPort target.port Número de puerto de destino
metadata.product_name Nombre del producto
metadata.vendor_name Nombre del proveedor o la empresa

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