Recolha registos do Qualys Virtual Scanner
Este analisador transforma registos do Qualys Virtual Scanner formatados em JSON não processado num formato estruturado em conformidade com o UDM do Google Security Operations. Extrai campos relevantes, como informações de recursos, detalhes de análise e vulnerabilidades detetadas, mapeando-os para os campos da UDM correspondentes para uma representação e uma análise consistentes.
Antes de começar
Certifique-se de que tem os seguintes pré-requisitos:
- Instância do Google Security Operations.
- Acesso privilegiado a Google Cloud.
- Acesso privilegiado ao Qualys.
Ative as APIs necessárias:
- Inicie sessão na Google Cloud consola.
- Aceda a APIs e serviços > Biblioteca.
- Pesquise as seguintes APIs e ative-as:
- Cloud Functions API
- API do Cloud Scheduler
- Cloud Pub/Sub (necessário para o Cloud Scheduler invocar funções)
Crie um Google Cloud contentor de armazenamento
- Inicie sessão na Google Cloud consola.
Aceda à página Contentores do Cloud Storage.
Clique em Criar.
Configure o contentor:
- Nome: introduza um nome exclusivo que cumpra os requisitos de nome do contentor (por exemplo, qualys-vscanner-bucket).
- Escolha onde quer armazenar os seus dados: selecione uma localização.
- Escolha uma classe de armazenamento para os seus dados: selecione uma classe de armazenamento predefinida para o contentor ou selecione Autoclass para a gestão automática da classe de armazenamento.
- Escolha como controlar o acesso aos objetos: selecione não para aplicar a prevenção de acesso público e selecione um modelo de controlo de acesso para os objetos do seu contentor.
- Classe de armazenamento: escolha com base nas suas necessidades (por exemplo, Standard).
Clique em Criar.
Crie uma conta de serviço do Google Cloud
- Aceda a IAM e administrador > Contas de serviço.
- Crie uma nova conta de serviço.
- Atribua-lhe um nome descritivo (por exemplo, qualys-user).
- Conceda à conta de serviço a função de administrador de objetos de armazenamento no contentor do Cloud Storage que criou no passo anterior.
- Conceda à conta de serviço a função de invocador do Cloud Functions.
- Crie uma chave SSH para a conta de serviço.
- Transfira um ficheiro de chave JSON para a conta de serviço. Mantenha este ficheiro seguro.
Opcional: crie um utilizador da API dedicado no Qualys
- Inicie sessão na consola do Qualys.
- Aceda a Utilizadores.
- Clique em Novo > Utilizador.
- Introduza as informações gerais necessárias para o utilizador.
- Selecione o separador Função do utilizador.
- Certifique-se de que a caixa de verificação Acesso à API está selecionada para a função.
- Clique em Guardar.
Identifique o URL da API Qualys específico
Opção 1
Identifique os seus URLs conforme mencionado na identificação da plataforma.
Opção 2
- Inicie sessão na consola do Qualys.
- Aceda a Ajuda > Acerca de.
- Desloque a página para ver estas informações em Centro de operações de segurança (SOC).
- Copie o URL da API Qualys.
Configure a função do Google Cloud
- Aceda ao Cloud Functions na Google Cloud consola.
- Clique em Criar função.
Configure a função:
- Nome: introduza um nome para a sua função (por exemplo, fetch-qualys-vscanner).
- Região: selecione uma região próxima do seu contentor.
- Acionador: escolha o acionador HTTP, se necessário, ou o Cloud Pub/Sub para execução agendada.
- Autenticação: proteja com autenticação.
- Escreva o código com um editor inline:
```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 ```
Clique em Implementar após concluir a configuração.
Configure o Cloud Scheduler
- Aceda ao Cloud Scheduler na Google Cloud consola.
- Clique em Criar tarefa.
Configure a tarefa:
- Nome: introduza um nome para a tarefa (por exemplo, trigger-fetch-qualys-vscanner).
- Frequência: use a sintaxe cron para especificar o agendamento (por exemplo, 0 0 * * * para diariamente à meia-noite).
- Fuso horário: defina o seu fuso horário preferido.
- Tipo de acionador: escolha HTTP.
- URL do acionador: introduza o URL da Cloud Function (encontrado nos detalhes da função após a implementação).
- Método: escolha POST.
Crie o trabalho.
Configure feeds
Para configurar um feed, siga estes passos:
- Aceda a Definições do SIEM > Feeds.
- Clique em Adicionar novo feed.
- Na página seguinte, clique em Configurar um único feed.
- No campo Nome do feed, introduza um nome para o feed; por exemplo, Registos do analisador virtual da Qualys.
- Selecione Google Cloud Storage V2 como Tipo de origem.
- Selecione Qualys Virtual Scanner como o Tipo de registo.
- Clicar em Seguinte.
Especifique valores para os seguintes parâmetros de entrada:
- URI do contentor de armazenamento: o Google Cloud URI de origem do contentor de armazenamento.
- Opção de eliminação da origem: selecione a opção de eliminação de acordo com a sua preferência.
Clicar em Seguinte.
Reveja a nova configuração do feed no ecrã Finalizar e, de seguida, clique em Enviar.
Tabela de mapeamento da UDM
Campo de registo | Mapeamento de UDM | Lógica |
---|---|---|
ASSET_ID | entity.entity.asset.asset_id | Mapeamento direto do campo ASSET_ID . |
CLOUD_PROVIDER_TAGS.CLOUD_TAG.NAME | entity.relations.entity.resource.attribute.labels.key | Mapeamento direto do campo CLOUD_PROVIDER_TAGS.CLOUD_TAG.NAME . |
CLOUD_PROVIDER_TAGS.CLOUD_TAG.VALUE | entity.relations.entity.resource.attribute.labels.value | Mapeamento direto do campo CLOUD_PROVIDER_TAGS.CLOUD_TAG.VALUE . |
CLOUD_RESOURCE_ID | entity.relations.entity.resource.id | Mapeamento direto do campo CLOUD_RESOURCE_ID . |
DETECTION_LIST.DETECTION.FIRST_FOUND_DATETIME | entity.metadata.threat.first_discovered_time | Mapeamento direto do campo DETECTION_LIST.DETECTION.FIRST_FOUND_DATETIME , convertido em indicação de tempo. |
DETECTION_LIST.DETECTION.FIRST_REOPENED_DATETIME | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.FIRST_REOPENED_DATETIME . A chave está codificada como "FIRST_REOPENED_DATETIME". |
DETECTION_LIST.DETECTION.IS_DISABLED | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.IS_DISABLED . A chave está codificada como "IS_DISABLED". |
DETECTION_LIST.DETECTION.LAST_FIXED_DATETIME | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.LAST_FIXED_DATETIME . A chave está codificada como "LAST_FIXED_DATETIME". |
DETECTION_LIST.DETECTION.LAST_FOUND_DATETIME | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.LAST_FOUND_DATETIME . A chave está codificada como "LAST_FOUND_DATETIME". |
DETECTION_LIST.DETECTION.LAST_PROCESSED_DATETIME | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.LAST_PROCESSED_DATETIME . A chave está codificada como "LAST_PROCESSED_DATETIME". |
DETECTION_LIST.DETECTION.LAST_REOPENED_DATETIME | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.LAST_REOPENED_DATETIME . A chave está codificada como "LAST_REOPENED_DATETIME". |
DETECTION_LIST.DETECTION.LAST_TEST_DATETIME | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.LAST_TEST_DATETIME . A chave está codificada como "LAST_TEST_DATETIME". |
DETECTION_LIST.DETECTION.LAST_UPDATE_DATETIME | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.LAST_UPDATE_DATETIME . A chave está codificada como "LAST_UPDATE_DATETIME". |
DETECTION_LIST.DETECTION.PORT | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.PORT . A chave está codificada como "PORT". |
DETECTION_LIST.DETECTION.PROTOCOL | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.PROTOCOL . A chave está codificada como "PROTOCOL". |
DETECTION_LIST.DETECTION.QID | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.QID . A chave está codificada como "QID". |
DETECTION_LIST.DETECTION.RESULTS | entity.metadata.threat.summary | Mapeamento direto do campo DETECTION_LIST.DETECTION.RESULTS . |
DETECTION_LIST.DETECTION.SEVERITY | entity.metadata.threat.severity_details | Mapeamento direto do campo DETECTION_LIST.DETECTION.SEVERITY . |
DETECTION_LIST.DETECTION.SSL | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.SSL . A chave está codificada como "SSL". |
DETECTION_LIST.DETECTION.STATUS | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.STATUS . A chave está codificada como "STATUS". |
DETECTION_LIST.DETECTION.TIMES_FOUND | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.TIMES_FOUND . A chave está codificada como "TIMES_FOUND". |
DETECTION_LIST.DETECTION.TIMES_REOPENED | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.TIMES_REOPENED . A chave está codificada como "TIMES_REOPENED". |
DETECTION_LIST.DETECTION.TYPE | entity.metadata.threat.severity | Mapeado a partir do campo DETECTION_LIST.DETECTION.TYPE . Se o valor for "info" (sem distinção entre maiúsculas e minúsculas), é mapeado para "INFORMATIONAL". Caso contrário, é adicionado como um campo de deteção com a chave "TYPE". |
DETECTION_LIST.DETECTION.UNIQUE_VULN_ID | entity.metadata.threat.detection_fields.value | Mapeamento direto do campo DETECTION_LIST.DETECTION.UNIQUE_VULN_ID . A chave está codificada como "UNIQUE_VULN_ID". |
DNS | entity.entity.asset.hostname | Mapeado a partir do campo DNS se DNS_DATA.HOSTNAME estiver vazio. |
DNS_DATA.HOSTNAME | entity.entity.asset.hostname | Mapeamento direto do campo DNS_DATA.HOSTNAME . |
EC2_INSTANCE_ID | entity.relations.entity.resource.product_object_id | Mapeamento direto do campo EC2_INSTANCE_ID . |
ID | entity.entity.asset.product_object_id | Mapeamento direto do campo ID . |
ID | entity.metadata.product_entity_id | Mapeamento direto do campo ID . |
PI | entity.entity.ip | Mapeamento direto do campo IP . |
LAST_SCAN_DATETIME | entity.metadata.interval.start_time | Mapeamento direto do campo LAST_SCAN_DATETIME , convertido em indicação de tempo. |
METADATA.AZURE.ATTRIBUTE.NAME | entity.relations.entity.resource.attribute.labels.key | Mapeamento direto do campo METADATA.AZURE.ATTRIBUTE.NAME . |
METADATA.AZURE.ATTRIBUTE.VALUE | entity.relations.entity.resource.attribute.labels.value | Mapeamento direto do campo METADATA.AZURE.ATTRIBUTE.VALUE . |
SO | entity.entity.asset.platform_software.platform | Mapeado a partir do campo OS . Se o valor contiver "windows" (sem distinção entre maiúsculas e minúsculas), é mapeado para "WINDOWS". Se contiver "Linux" (não é sensível a maiúsculas e minúsculas), é mapeado para "LINUX". |
TAGS.TAG.NAME | entity.relations.entity.resource.attribute.labels.key | Mapeamento direto do campo TAGS.TAG.NAME . |
TAGS.TAG.TAG_ID | entity.relations.entity.resource.attribute.labels.value | Mapeado a partir do campo TAGS.TAG.TAG_ID . O valor tem o prefixo "TAG_ID: ". |
entity.metadata.collected_timestamp | A data/hora da entrada do registo. | |
entity.metadata.entity_type | Determinado com base na presença do campo IP . Se IP estiver presente, é definido como "IP_ADDRESS". Caso contrário, é definido como "ASSET". |
|
entity.metadata.interval.end_time | Codificado de forma rígida para um valor de data/hora muito grande (253402300799 segundos). | |
entity.metadata.product_name | Codificado de forma rígida como "QUALYS_VIRTUAL_SCANNER". | |
entity.metadata.vendor_name | Codificado de forma rígida como "QUALYS_VIRTUAL_SCANNER". | |
entity.relations.entity.resource.resource_type | Se CLOUD_SERVICE for "VM", é definido como "VIRTUAL_MACHINE". |
|
entity.relations.entity_type | Codificado de forma rígida para "RESOURCE". | |
entity.relations.relationship | Codificado de forma rígida como "MEMBER". |
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais da Google SecOps.