Recoger registros de Qualys Virtual Scanner
Este analizador transforma los registros sin procesar de Qualys Virtual Scanner en formato JSON en un formato estructurado que se ajusta al UDM de Google Security Operations. Extrae campos relevantes, como la información de los recursos, los detalles de los análisis y las vulnerabilidades detectadas, y los asigna a los campos de UDM correspondientes para que la representación y el análisis sean coherentes.
Antes de empezar
Asegúrate de que cumples los siguientes requisitos previos:
- Instancia de Google Security Operations.
- Acceso privilegiado a Google Cloud.
- Acceso privilegiado a Qualys.
Habilita las APIs obligatorias:
- Inicia sesión en la Google Cloud consola.
- Ve a APIs y servicios > Biblioteca.
- Busca las siguientes APIs y habilítalas:
- Cloud Functions API
- API Scheduler de Cloud
- Cloud Pub/Sub (necesario para que Cloud Scheduler invoque funciones)
Crea un Google Cloud segmento de almacenamiento
- Inicia sesión en la Google Cloud consola.
Ve a la página Segmentos de Cloud Storage.
Haz clic en Crear.
Configure el segmento:
- Nombre: introduzca un nombre único que cumpla los requisitos de nombres de los segmentos (por ejemplo, qualys-vscanner-bucket).
- Elige dónde quieres almacenar los datos: selecciona una ubicación.
- Elige una clase de almacenamiento para tus datos: selecciona una clase de almacenamiento predeterminada para el segmento o Autoclass para gestionar automáticamente la clase de almacenamiento.
- Elige cómo quieres controlar el acceso a los objetos: selecciona no para aplicar la prevención del acceso público y elige un modelo de control de acceso para los objetos del segmento.
- Clase de almacenamiento: elige la que mejor se adapte a tus necesidades (por ejemplo, Standard).
Haz clic en Crear.
Crear una cuenta de servicio de Google Cloud
- Ve a IAM y administración > Cuentas de servicio.
- Crear una nueva cuenta de servicio.
- Asigna un nombre descriptivo (por ejemplo, qualys-user).
- Concede a la cuenta de servicio el rol Administrador de objetos de Storage en el segmento de Cloud Storage que has creado en el paso anterior.
- Asigna a la cuenta de servicio el rol Invocador de Cloud Functions.
- Crea una clave SSH para la cuenta de servicio.
- Descarga un archivo de clave JSON de la cuenta de servicio. Guarda este archivo de forma segura.
Opcional: Crea un usuario de API específico en Qualys
- Inicia sesión en la consola de Qualys.
- Ve a Usuarios.
- Haz clic en Nuevo > Usuario.
- Introduce la información general necesaria del usuario.
- Selecciona la pestaña Rol de usuario.
- Asegúrate de que el rol tenga marcada la casilla Acceso a la API.
- Haz clic en Guardar.
Identificar tu URL de API de Qualys específica
Opción 1
Identifique sus URLs tal como se indica en la sección Identificación de la plataforma.
Opción 2
- Inicia sesión en la consola de Qualys.
- Ve a Ayuda > Información.
- Desplázate para ver esta información en Centro de operaciones de seguridad (SOC).
- Copia la URL de la API de Qualys.
Configurar la función de Cloud
- Ve a Cloud Functions en la Google Cloud consola.
- Haz clic en Crear función.
Configura la función:
- Nombre: introduce un nombre para la función (por ejemplo, fetch-qualys-vscanner).
- Región: selecciona una región cercana a tu contenedor.
- Activador: elige el activador HTTP si es necesario o Cloud Pub/Sub para la ejecución programada.
- Autenticación: protege con autenticación.
- Escribe el código con un editor insertado:
```python from google.cloud import storage import requests import base64 import json # Google Cloud Storage Configuration BUCKET_NAME = "<bucket-name>" FILE_NAME = "qualys_virtual_scanners.json" # Qualys API Credentials QUALYS_USERNAME = "qualys-username" QUALYS_PASSWORD = "<qualys-password>" QUALYS_BASE_URL = "https://<qualys_base_url>" # for example, https://qualysapi.qualys.com def fetch_virtual_scanners(): """Fetch Virtual Scanner details from Qualys.""" auth = base64.b64encode(f"{QUALYS_USERNAME}:{QUALYS_PASSWORD}".encode()).decode() headers = { "Authorization": f"Basic {auth}", "Content-Type": "application/xml" } url = f"{QUALYS_BASE_URL}/api/2.0/fo/scanner/" payload = { "action": "list", "scanner_type": "virtual" } response = requests.post(url, headers=headers, data=payload) response.raise_for_status() return response.text # Qualys API returns XML data def upload_to_gcs(data): """Upload data to Google Cloud Storage.""" client = storage.Client() bucket = client.get_bucket(BUCKET_NAME) blob = bucket.blob(FILE_NAME) blob.upload_from_string(data, content_type="application/xml") def main(request): """Cloud Function entry point.""" try: scanners = fetch_virtual_scanners() upload_to_gcs(scanners) return "Qualys Virtual Scanners data uploaded to Cloud Storage successfully!" except Exception as e: return f"An error occurred: {e}", 500 ```
Haz clic en Implementar después de completar la configuración.
Configurar Cloud Scheduler
- Ve a Cloud Scheduler en la Google Cloud consola.
- Haz clic en Crear trabajo.
Configura el trabajo:
- Nombre: introduce un nombre para el trabajo (por ejemplo, trigger-fetch-qualys-vscanner).
- Frecuencia: usa la sintaxis cron para especificar la programación (por ejemplo, 0 0 * * * para que se ejecute todos los días a medianoche).
- Zona horaria: define tu zona horaria preferida.
- Tipo de activador: elige HTTP.
- URL de activación: introduce la URL de Cloud Functions (que se encuentra en los detalles de la función después de la implementación).
- Método: elige POST.
Crea el trabajo.
Configurar feeds
Para configurar un feed, sigue estos pasos:
- Ve a Configuración de SIEM > Feeds.
- Haz clic en Añadir feed.
- En la página siguiente, haga clic en Configurar un solo feed.
- En el campo Nombre del feed, introduce un nombre para el feed; por ejemplo, Registros del escáner virtual de Qualys.
- Selecciona Google Cloud Storage V2 como Tipo de origen.
- Seleccione Qualys Virtual Scanner como Tipo de registro.
- Haz clic en Siguiente.
Especifique los valores de los siguientes parámetros de entrada:
- URI del segmento de almacenamiento: el Google Cloud URI de origen del segmento de almacenamiento.
- Opción de eliminación de la fuente: selecciona la opción de eliminación que prefieras.
Haz clic en Siguiente.
Revise la configuración de la nueva fuente en la pantalla Finalizar y, a continuación, haga clic en Enviar.
Tabla de asignación de UDM
Campo de registro | Asignación de UDM | Lógica |
---|---|---|
ASSET_ID | entity.entity.asset.asset_id | Asignación directa del campo ASSET_ID . |
CLOUD_PROVIDER_TAGS.CLOUD_TAG.NAME | entity.relations.entity.resource.attribute.labels.key | Asignación directa del campo CLOUD_PROVIDER_TAGS.CLOUD_TAG.NAME . |
CLOUD_PROVIDER_TAGS.CLOUD_TAG.VALUE | entity.relations.entity.resource.attribute.labels.value | Asignación directa del campo CLOUD_PROVIDER_TAGS.CLOUD_TAG.VALUE . |
CLOUD_RESOURCE_ID | entity.relations.entity.resource.id | Asignación directa del campo CLOUD_RESOURCE_ID . |
DETECTION_LIST.DETECTION.FIRST_FOUND_DATETIME | entity.metadata.threat.first_discovered_time | Asignación directa del campo DETECTION_LIST.DETECTION.FIRST_FOUND_DATETIME , convertido a marca de tiempo. |
DETECTION_LIST.DETECTION.FIRST_REOPENED_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.FIRST_REOPENED_DATETIME . La clave se ha codificado de forma fija como "FIRST_REOPENED_DATETIME". |
DETECTION_LIST.DETECTION.IS_DISABLED | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.IS_DISABLED . La clave está codificada como "IS_DISABLED". |
DETECTION_LIST.DETECTION.LAST_FIXED_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_FIXED_DATETIME . La clave está codificada como "LAST_FIXED_DATETIME". |
DETECTION_LIST.DETECTION.LAST_FOUND_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_FOUND_DATETIME . La clave está codificada como "LAST_FOUND_DATETIME". |
DETECTION_LIST.DETECTION.LAST_PROCESSED_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_PROCESSED_DATETIME . La clave se codifica de forma fija como "LAST_PROCESSED_DATETIME". |
DETECTION_LIST.DETECTION.LAST_REOPENED_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_REOPENED_DATETIME . La clave se ha codificado de forma fija como "LAST_REOPENED_DATETIME". |
DETECTION_LIST.DETECTION.LAST_TEST_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_TEST_DATETIME . La clave está codificada como "LAST_TEST_DATETIME". |
DETECTION_LIST.DETECTION.LAST_UPDATE_DATETIME | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.LAST_UPDATE_DATETIME . La clave se ha codificado como "LAST_UPDATE_DATETIME". |
DETECTION_LIST.DETECTION.PORT | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.PORT . La clave está codificada como "PORT". |
DETECTION_LIST.DETECTION.PROTOCOL | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.PROTOCOL . La clave se codifica como "PROTOCOL". |
DETECTION_LIST.DETECTION.QID | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.QID . La clave está codificada como "QID". |
DETECTION_LIST.DETECTION.RESULTS | entity.metadata.threat.summary | Asignación directa del campo DETECTION_LIST.DETECTION.RESULTS . |
DETECTION_LIST.DETECTION.SEVERITY | entity.metadata.threat.severity_details | Asignación directa del campo DETECTION_LIST.DETECTION.SEVERITY . |
DETECTION_LIST.DETECTION.SSL | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.SSL . La clave está codificada como "SSL". |
DETECTION_LIST.DETECTION.STATUS | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.STATUS . La clave está codificada como "STATUS". |
DETECTION_LIST.DETECTION.TIMES_FOUND | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.TIMES_FOUND . La clave está codificada como "TIMES_FOUND". |
DETECTION_LIST.DETECTION.TIMES_REOPENED | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.TIMES_REOPENED . La clave está codificada como "TIMES_REOPENED". |
DETECTION_LIST.DETECTION.TYPE | entity.metadata.threat.severity | Asignado desde el campo DETECTION_LIST.DETECTION.TYPE . Si el valor es "info" (sin distinguir entre mayúsculas y minúsculas), se asigna a "INFORMATIONAL". De lo contrario, se añade como campo de detección con la clave "TYPE". |
DETECTION_LIST.DETECTION.UNIQUE_VULN_ID | entity.metadata.threat.detection_fields.value | Asignación directa del campo DETECTION_LIST.DETECTION.UNIQUE_VULN_ID . La clave se codifica como "UNIQUE_VULN_ID". |
DNS | entity.entity.asset.hostname | Se asigna desde el campo DNS si DNS_DATA.HOSTNAME está vacío. |
DNS_DATA.HOSTNAME | entity.entity.asset.hostname | Asignación directa del campo DNS_DATA.HOSTNAME . |
EC2_INSTANCE_ID | entity.relations.entity.resource.product_object_id | Asignación directa del campo EC2_INSTANCE_ID . |
ID | entity.entity.asset.product_object_id | Asignación directa del campo ID . |
ID | entity.metadata.product_entity_id | Asignación directa del campo ID . |
IP | entity.entity.ip | Asignación directa del campo IP . |
LAST_SCAN_DATETIME | entity.metadata.interval.start_time | Asignación directa del campo LAST_SCAN_DATETIME , convertido a marca de tiempo. |
METADATA.AZURE.ATTRIBUTE.NAME | entity.relations.entity.resource.attribute.labels.key | Asignación directa del campo METADATA.AZURE.ATTRIBUTE.NAME . |
METADATA.AZURE.ATTRIBUTE.VALUE | entity.relations.entity.resource.attribute.labels.value | Asignación directa del campo METADATA.AZURE.ATTRIBUTE.VALUE . |
SO | entity.entity.asset.platform_software.platform | Asignado desde el campo OS . Si el valor contiene "windows" (sin distinguir entre mayúsculas y minúsculas), se asigna a "WINDOWS". Si contiene "Linux" (sin distinguir entre mayúsculas y minúsculas), se asigna a "LINUX". |
TAGS.TAG.NAME | entity.relations.entity.resource.attribute.labels.key | Asignación directa del campo TAGS.TAG.NAME . |
TAGS.TAG.TAG_ID | entity.relations.entity.resource.attribute.labels.value | Asignado desde el campo TAGS.TAG.TAG_ID . El valor tiene el prefijo "TAG_ID: ". |
entity.metadata.collected_timestamp | Marca de tiempo de la entrada de registro. | |
entity.metadata.entity_type | Se determina en función de la presencia del campo IP . Si IP está presente, se le asigna el valor "IP_ADDRESS". De lo contrario, se le asigna el valor "ASSET". |
|
entity.metadata.interval.end_time | Se ha codificado de forma rígida con un valor de marca de tiempo muy grande (253402300799 segundos). | |
entity.metadata.product_name | Codificado como "QUALYS_VIRTUAL_SCANNER". | |
entity.metadata.vendor_name | Codificado como "QUALYS_VIRTUAL_SCANNER". | |
entity.relations.entity.resource.resource_type | Si CLOUD_SERVICE es "VM", se asigna el valor "VIRTUAL_MACHINE". |
|
entity.relations.entity_type | Codificado como "RESOURCE". | |
entity.relations.relationship | Codificado como "MEMBER". |
¿Necesitas más ayuda? Recibe respuestas de los miembros de la comunidad y de los profesionales de Google SecOps.