Coletar registros do framework de verificação de arquivos
Versão do analisador:3.0
Este documento explica como ingerir registros do File Scanning Framework no Google Security Operations usando o Google Cloud Storage V2.
O File Scanning Framework (FSF) é uma solução de verificação de arquivos recursiva, modular e de código aberto desenvolvida pela Emerson Electric Co. O FSF usa uma arquitetura cliente-servidor para analisar arquivos e gerar resultados detalhados de verificação em JSON, incluindo metadados de arquivos, correspondências de assinatura YARA, subobjetos extraídos e metadados específicos do módulo.
Antes de começar
Verifique se você atende aos seguintes pré-requisitos:
- Uma instância do Google SecOps
- Um projeto do GCP com a API Storage do Cloud ativada
- Permissões para criar e gerenciar intervalos do GCS
- Permissões para gerenciar políticas do IAM em buckets do GCS
- Uma instância de servidor FSF implantada com acesso de gravação ao diretório de registros
- Acesso root ou sudo ao host do servidor FSF
Criar um bucket do Google Cloud Storage
- Acesse o Console do Google Cloud.
- Selecione ou crie um projeto.
- No menu de navegação, acesse Cloud Storage > Buckets.
- Clique em Criar bucket.
Informe os seguintes detalhes de configuração:
Configuração Valor Nomeie seu bucket Insira um nome globalmente exclusivo (por exemplo, fsf-logs-secops).Tipo de local Escolha de acordo com suas necessidades (região, birregional, multirregional). Local Selecione o local (por exemplo, us-central1).Classe de armazenamento Padrão (recomendado para registros acessados com frequência). Controle de acesso Uniforme (recomendado). Ferramentas de proteção Opcional: ative o controle de versões de objetos ou a política de retenção. Clique em Criar.
Configurar o diretório de saída de registros do FSF
O FSF grava os resultados da verificação JSON em um diretório de registros configurável. Configure um diretório dedicado para a ingestão do Google SecOps.
- Conecte-se ao host do servidor FSF via SSH.
Abra o arquivo de configuração do servidor FSF:
sudo nano /opt/fsf/fsf-server/conf/config.pyLocalize o dicionário
SCANNER_CONFIG.Atualize o parâmetro
LOG_PATHpara um diretório dedicado:SCANNER_CONFIG = { 'LOG_PATH': '/var/log/fsf', 'YARA_PATH': '/opt/fsf/fsf-server/yara/rules.yara', 'PID_PATH': '/tmp/scanner.pid', 'EXPORT_PATH': '/tmp', 'TIMEOUT': 60, 'MAX_DEPTH': 10 }Salve e feche o arquivo.
Crie o diretório de registros com as permissões adequadas:
sudo mkdir -p /var/log/fsf sudo chown -R fsf:fsf /var/log/fsf sudo chmod 755 /var/log/fsfReinicie o servidor FSF para aplicar as mudanças:
sudo systemctl restart fsfVerifique se o FSF está gravando registros no novo diretório:
ls -lh /var/log/fsf/
Instalar e configurar o Fluentd
O Fluentd vai rastrear os arquivos de registro do FSF e enviá-los para o Google Cloud Storage.
Instalar o Fluentd
No host do servidor FSF, instale o Fluentd (td-agent):
curl -fsSL https://toolbelt.treasuredata.com/sh/install-ubuntu-jammy-td-agent4.sh | shInstale o plug-in de saída do GCS:
sudo td-agent-gem install fluent-plugin-gcsVerifique a instalação do plug-in:
td-agent-gem list | grep fluent-plugin-gcs
Criar uma conta de serviço do GCP para o Fluentd
- No console do GCP, acesse IAM e administrador > Contas de serviço.
- Clique em Criar conta de serviço.
- Informe os seguintes detalhes de configuração:
- Nome da conta de serviço: insira
fsf-fluentd-shipper. - Descrição da conta de serviço: insira
Service account for Fluentd to ship FSF logs to GCS.
- Nome da conta de serviço: insira
- Clique em Criar e continuar.
- Na seção Conceder a essa conta de serviço acesso ao projeto:
- Clique em Selecionar papel.
- Pesquise e selecione Administrador de objetos do Storage.
- Clique em Continuar.
- Clique em Concluído.
Criar chave da conta de serviço
- Na lista Contas de serviço, clique na conta de serviço (
fsf-fluentd-shipper). - Acesse a guia Chaves.
- Clique em Adicionar chave > Criar nova chave.
- Selecione JSON como o tipo de chave.
- Clique em Criar.
- O arquivo de chave JSON será baixado no seu computador.
Transfira o arquivo de chave para o host do servidor FSF:
scp /path/to/downloaded-key.json user@fsf-server:/etc/td-agent/gcp-key.jsonDefina as permissões adequadas no arquivo de chave:
sudo chown td-agent:td-agent /etc/td-agent/gcp-key.json sudo chmod 600 /etc/td-agent/gcp-key.json
Conceder permissões do IAM no bucket do GCS
- Acesse Cloud Storage > Buckets.
- Clique no nome do bucket (
fsf-logs-secops). - Acesse a guia Permissões.
- Clique em Conceder acesso.
- Informe os seguintes detalhes de configuração:
- Adicionar principais: insira o e-mail da conta de serviço (por exemplo,
fsf-fluentd-shipper@PROJECT_ID.iam.gserviceaccount.com). - Atribuir papéis: selecione Administrador de objetos do Storage.
- Adicionar principais: insira o e-mail da conta de serviço (por exemplo,
- Clique em Salvar.
Configurar o Fluentd
No host do servidor FSF, crie um arquivo de configuração do Fluentd:
sudo nano /etc/td-agent/td-agent.confAdicione a seguinte configuração:
# Tail FSF JSON logs <source> @type tail path /var/log/fsf/*.log pos_file /var/log/td-agent/fsf.log.pos tag fsf.scan read_from_head true <parse> @type json time_key timestamp time_format %Y-%m-%dT%H:%M:%S.%L%z </parse> </source> # Ship to Google Cloud Storage <match fsf.scan> @type gcs project YOUR_GCP_PROJECT_ID keyfile /etc/td-agent/gcp-key.json bucket fsf-logs-secops object_key_format %{path}%{time_slice}_%{index}.%{file_extension} path fsf-logs/ <buffer tag,time> @type file path /var/log/td-agent/buffer/gcs timekey 3600 timekey_wait 10m timekey_use_utc true chunk_limit_size 10MB </buffer> <format> @type json </format> store_as json auto_create_bucket false </match>Substitua
YOUR_GCP_PROJECT_IDpelo ID do projeto do GCP.Salve e feche o arquivo.
Crie o diretório de buffer:
sudo mkdir -p /var/log/td-agent/buffer/gcs sudo chown -R td-agent:td-agent /var/log/td-agent/bufferReinicie o Fluentd para aplicar a configuração:
sudo systemctl restart td-agentAtive o Fluentd para iniciar na inicialização:
sudo systemctl enable td-agentVerifique se o Fluentd está em execução:
sudo systemctl status td-agent
Verificar o envio de registros
Verifique se há erros nos registros do Fluentd:
sudo tail -f /var/log/td-agent/td-agent.logAcione uma verificação de FSF de teste para gerar registros:
echo "test content" > /tmp/test.txt /opt/fsf/fsf-client/fsf_client.py /tmp/test.txt --suppress-reportAguarde de 1 a 2 minutos para que o Fluentd processe e envie os registros.
No console do GCP, acesse Cloud Storage > Buckets.
Clique no nome do bucket (
fsf-logs-secops).Navegue até o prefixo
fsf-logs/.Verifique se os arquivos JSON estão sendo criados com carimbos de data/hora.
Faça o download e inspecione um arquivo para confirmar se ele contém resultados da verificação do FSF no formato JSON.
Recuperar a conta de serviço do Google SecOps
O Google SecOps usa uma conta de serviço exclusiva para ler dados do seu bucket do GCS. Você precisa conceder a essa conta de serviço acesso ao seu bucket.
Receber o e-mail da conta de serviço
- Acesse Configurações do SIEM > Feeds.
- Clique em Adicionar novo feed.
- Clique em Configurar um único feed.
- No campo Nome do feed, insira um nome para o feed (por exemplo,
FSF File Scanning Logs). - Selecione Google Cloud Storage V2 como o Tipo de origem.
- Selecione Estrutura de verificação de arquivos como o Tipo de registro.
Clique em Receber conta de serviço. Um e-mail exclusivo da conta de serviço será exibido, por exemplo:
secops-12345678@secops-gcp-prod.iam.gserviceaccount.comCopie o endereço de e-mail para usar na próxima etapa.
Clique em Próxima.
Especifique valores para os seguintes parâmetros de entrada:
URL do bucket de armazenamento: insira o URI do bucket do GCS com o caminho do prefixo:
gs://fsf-logs-secops/fsf-logs/Opção de exclusão da fonte: selecione a opção de exclusão de acordo com sua preferência:
- Nunca: nunca exclui arquivos após as transferências (recomendado para testes).
- Excluir arquivos transferidos: exclui os arquivos após a transferência.
Excluir arquivos transferidos e diretórios vazios: exclui arquivos e diretórios vazios após a transferência.
Idade máxima do arquivo: inclua arquivos modificados no último número de dias (o padrão é 180 dias).
Namespace do recurso: o namespace do recurso.
Rótulos de ingestão: o rótulo a ser aplicado aos eventos deste feed.
Clique em Próxima.
Revise a nova configuração do feed na tela Finalizar e clique em Enviar.
Conceder permissões do IAM à conta de serviço do Google SecOps
A conta de serviço do Google SecOps precisa do papel Leitor de objetos do Storage no seu bucket do GCS.
- Acesse Cloud Storage > Buckets.
- Clique no nome do bucket (
fsf-logs-secops). - Acesse a guia Permissões.
- Clique em Conceder acesso.
- Informe os seguintes detalhes de configuração:
- Adicionar participantes: cole o e-mail da conta de serviço do Google SecOps.
- Atribuir papéis: selecione Leitor de objetos do Storage.
- Clique em Salvar.
Verificar a ingestão
- Aguarde de 10 a 15 minutos para que a ingestão inicial seja concluída.
- No Google SecOps, acesse Configurações do SIEM > Feeds.
- Localize o feed (
FSF File Scanning Logs). - Verifique se o Status aparece como Ativo.
- Clique no nome do feed para conferir as métricas de ingestão.
- Verifique se a contagem de Eventos ingeridos está aumentando.
- Acesse Pesquisar no Google SecOps.
Execute uma consulta de pesquisa para verificar se os registros do FSF estão sendo ingeridos:
metadata.log_type = "FILE_SCANNING_FRAMEWORK"Verifique se os resultados da verificação do FSF aparecem nos resultados da pesquisa.
Solução de problemas
Nenhum registro aparece no GCS
Verifique se o FSF está gravando registros em
/var/log/fsf/:ls -lh /var/log/fsf/ tail -f /var/log/fsf/*.logVerifique se há erros nos registros do Fluentd:
sudo tail -f /var/log/td-agent/td-agent.logVerifique se a chave da conta de serviço do GCP é válida e tem as permissões corretas.
Confira se o nome do bucket na configuração do Fluentd corresponde ao nome real do bucket.
Erros de permissão do Fluentd
- Verifique se a conta de serviço (
fsf-fluentd-shipper) tem o papel Administrador de objetos do Storage no bucket. - Verifique se o caminho da chave na configuração do Fluentd está correto.
Verifique se o arquivo de chave tem a propriedade e as permissões corretas:
ls -l /etc/td-agent/gcp-key.json
O Google SecOps não está ingerindo registros
- Verifique se a conta de serviço do Google SecOps tem o papel Leitor de objetos do Storage no bucket.
- Verifique se o URI do bucket na configuração do feed está correto e inclui a barra à direita.
- Verifique se os arquivos existem no bucket do GCS no caminho de prefixo especificado.
- Verifique o status do feed em Configurações do SIEM > Feeds para encontrar mensagens de erro.
Registros do FSF não estão no formato esperado
- Verifique se o FSF está configurado para gravar a saída JSON (comportamento padrão).
- Verifique se a seção
<parse>do Fluentd está configurada com@type json. Inspecione um arquivo de registro manualmente para verificar se ele contém JSON válido:
head -n 1 /var/log/fsf/*.log | jq .
Tabela de mapeamento de UDM
| Campo de registro | Mapeamento de UDM | Lógica |
|---|---|---|
| CompressType_label, compressed_parents | about.labels | Mesclado de CompressType_label (chave "Tipo de compactação", valor de Object.EXTRACT_ZIP.Object_0.Compress Type se a mensagem contiver "Tipo de compactação") e compressed_parents (chave "Arquivos principais compactados", concatenados de Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.additional_info.compressed_parents) |
| Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.MD5, Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.MD5, Object.EXTRACT_SWF.META_BASIC_INFO.MD5, Object.EXTRACT_GZIP.META_BASIC_INFO.MD5, Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.MD5 | intermediary.file.md5 | Valor de Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.MD5 se EXTRACT_EMBEDDED estiver presente. Caso contrário, Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.MD5 se EXTRACT_ZIP estiver presente. Caso contrário, Object.EXTRACT_SWF.META_BASIC_INFO.MD5 se EXTRACT_SWF estiver presente. Caso contrário, Object.EXTRACT_GZIP.META_BASIC_INFO.MD5 se EXTRACT_GZIP estiver presente. Caso contrário, Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.MD5. |
| Object.EXTRACT_EMBEDDED.Object_0.Description | intermediary.file.mime_type | Valor copiado diretamente |
| Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.SHA1, Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.SHA1, Object.EXTRACT_SWF.META_BASIC_INFO.SHA1, Object.EXTRACT_GZIP.META_BASIC_INFO.SHA1, Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.SHA1 | intermediary.file.sha1 | Valor de Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.SHA1 se EXTRACT_EMBEDDED estiver presente. Caso contrário, Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.SHA1 se EXTRACT_ZIP estiver presente. Caso contrário, Object.EXTRACT_SWF.META_BASIC_INFO.SHA1 se EXTRACT_SWF estiver presente. Caso contrário, Object.EXTRACT_GZIP.META_BASIC_INFO.SHA1 se EXTRACT_GZIP estiver presente. Caso contrário, Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.SHA1. |
| Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.SHA256, Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.SHA256, Object.EXTRACT_SWF.META_BASIC_INFO.SHA256, Object.EXTRACT_GZIP.META_BASIC_INFO.SHA256, Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.SHA256 | intermediary.file.sha256 | Valor de Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.SHA256 se EXTRACT_EMBEDDED estiver presente. Caso contrário, Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.SHA256 se EXTRACT_ZIP estiver presente. Caso contrário, Object.EXTRACT_SWF.META_BASIC_INFO.SHA256 se EXTRACT_SWF estiver presente. Caso contrário, Object.EXTRACT_GZIP.META_BASIC_INFO.SHA256 se EXTRACT_GZIP estiver presente. Caso contrário, Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.SHA256. |
| Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.Size, Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.Size, Object.EXTRACT_SWF.META_BASIC_INFO.Size, Object.EXTRACT_GZIP.META_BASIC_INFO.Size, Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.Size | intermediary.file.size | Valor de Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.Size se EXTRACT_EMBEDDED estiver presente, caso contrário, Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.Size se EXTRACT_ZIP estiver presente, caso contrário, Object.EXTRACT_SWF.META_BASIC_INFO.Size se EXTRACT_SWF estiver presente, caso contrário, Object.EXTRACT_GZIP.META_BASIC_INFO.Size se EXTRACT_GZIP estiver presente, caso contrário, Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.Size; sem o " .*" final e convertido para uinteger |
| Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.scan_id | intermediary.resource.id | Valor copiado diretamente |
| Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.permalink | intermediary.url | Valor copiado diretamente |
| Object.META_EMERSON_INFO.results | intermediary.user.email_addresses | Mesclado de "matched_email" na matriz de resultados |
| Summary.Observations | metadata.description | Concatenado de matriz com separador ", ", vírgula inicial removida |
| Tempo de verificação | metadata.event_timestamp | Convertido usando o filtro de data com o formato aaaa-MM-dd HH:mm:ss |
| Origem | metadata.event_type | Definido como "SCAN_FILE" se a origem não estiver vazia. Caso contrário, "GENERIC_EVENT". |
| Object.META_VT_CACHE._id | metadata.product_log_id | Valor copiado diretamente |
| result.ad_data.message | network.http.response_code | Extraído como um número inteiro usando o padrão grok INT de result.ad_data.message |
| Origem | principal.hostname | Valor copiado diretamente |
| Object.META_EMERSON_INFO.result_summary, Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.verbose_msg | security_result.summary | Definido como Object.META_EMERSON_INFO.result_summary, se presente. Caso contrário, Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.verbose_msg |
| Filename | target.file.full_path | Valor copiado diretamente |
| Object.META_BASIC_INFO.MD5 | target.file.md5 | Valor copiado diretamente |
| Summary.Yara | target.file.mime_type | Extraído do primeiro índice de Summary.Yara, convertido para maiúsculas e "FT_" removido se Yara estiver presente. Caso contrário, definido como "ZIP" se EXTRACT_ZIP estiver presente, "SWF" se EXTRACT_SWF estiver presente, "GZIP" se EXTRACT_GZIP estiver presente e "CAB" se EXTRACT_CAB estiver presente. |
| Object.META_BASIC_INFO.SHA1, Object.META_VT_CACHE.SHA1 | target.file.sha1 | Valor de Object.META_BASIC_INFO.SHA1 se não estiver vazio. Caso contrário, Object.META_VT_CACHE.SHA1. |
| Object.META_BASIC_INFO.SHA256 | target.file.sha256 | Valor copiado diretamente |
| Object.META_BASIC_INFO.Size | target.file.size | Removido o " .*" final e convertido para uinteger |
| metadata.vendor_name | Definido como "EMERSON" | |
| metadata.product_name | Defina como "FILE SCANNING FRAMEWORK" |
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.