Artigo desenvolvido pelo Paulo Deolindo, Consultor da Unirede.
Introdução
Zabbix, enquanto ferramenta open source de monitoramento, sempre foi visto como um software indispensável para observar métricas de infraestrutura de Tecnologia da Informação e Comunicação (TIC), porém, apesar de sua capacidade para além disso, tal como o monitoramento de aplicações e negócios, monitoramento de baseline e detecção de anomalia com uso nativo de Machine Learning (ML), quase nunca é visto como um componente capaz de auxiliar o mundo da segurança cibernética.
Por outro lado, temos o Suricata, um software também open source de detecção e prevenção de intrusões (IDS/IPS) e monitoramento de tráfego de rede de alto desempenho, desenvolvido pela Open Information Security Foundation (OISF). Ele opera analisando pacotes de rede em tempo real, identificando atividades maliciosas com base em assinaturas e análises comportamentais.
Já imaginou o que pode ocorrer se unirmos o poder de fogo das duas ferramentas?
De fato, nem o Zabbix, tampouco o Suricata, são softwares do tipo SIEM. Contudo, neste artigo demonstraremos como essa integração pode ser realizada e como sua empresa pode se beneficiar desses recursos para a missão de monitorar, detectar e responder a eventos de segurança da informação e cibernética em seus endpoints.
Lhe desejo boa leitura!
Zabbix Agent2, versão 7.0+
Inegavelmente, uma das melhorias mais significativas que posso destacar por agora em termos de Zabbix Agent2, é a incrível capacidade que ele ganhou de coletar até 1000 (mil) métricas por cada plugin que ele oferta e, isso inclui Log.
Veja:
Nesta versão, um monitoramento de log agressivo como o que precisamos nessa integração, não será um problema.
Mais sobre monitoramento de logs pelo Zabbix pode ser lido em sua documentação: 6 Log file monitoring
Suricata
Não é nosso intuito explorar profundamente o Suricata neste artigo, mas vamos entender alguns pontos importantes para nossa integração, por exemplo, a diferença entre alertas e eventos.
O Suricata é capaz de analisar vários tipos de eventos e, conforme as regras trabalhadas, podem ser gerados alertas (por exemplo, para o que realmente for considerado um problema). Para entender quais tipos de eventos ele é capaz de analisar basta consultar seu arquivo de configuração em /etc/suricata/suricata.yaml (em uma instalação padrão em um endpoint Ubuntu 22.04, por exemplo). Nesse sentido, vários tipos de logs podem ser gerados para serem lidos pelo Zabbix Agent2.
Um log simples e fácil de se analisar fica em /var/log/suricata/fast.log. Neste log, independentemente do tipo de evento e regra ativa, são registrados os alertas detectados pelo Suricata.
O log é padronizado, de fácil compreensão, o que facilita nossa tarefa de leitura e interpretação pelo Zabbix. Veja um exemplo:
04/03/2025-14:20:39.103950 [**] [1:2010937:3] ET SCAN Suspicious inbound to mySQL port 3306 [**] [Classification: Potentially Bad Traffic] [Priority: 2] {TCP} 192.168.100.100:35237 -> 192.168.200.200:3306
04/03/2025-14:20:39.103951 [**] [1:2010939:3] ET SCAN Suspicious inbound to PostgreSQL port 5432 [**] [Classification: Potentially Bad Traffic] [Priority: 2] {TCP} 192.168.100.100:35237 -> 192.168.200.200:5432
Estes logs foram capturados a partir de uma tentativa de scan pelo nmap para 2 portas específicas do endpoint monitorado e poderia ser reproduzido da seguinte forma:
# nmap -p 5432,3306 192.168.200.200
As mensagens iniciadas com “ET” significam “Emerging Threats” e são regras importadas ao Suricata, como forma de tunning, por assim dizer.
EVE Log
Um log mais completo e padronizado no formato json seria o /var/log/suricata/eve.json. Nesse log, o Suricata registra todos os tipos de eventos que sua configuração consegue capturar, mas não necessariamente todos os eventos são também alertas. Por exemplo, se estou monitorando as consultas do tipo DNS que meu endpoint faz, encontrarei eventos do tipo DNS e não necessariamente isso é um problema. Mas poderia ser se, por exemplo, o domínio consultado for algo considerado malicioso ou ainda, um site não desejado ou permitido em mina empresa. Essa é uma análise a ser realizada em outra etapa e não será abordada nesse artigo. Veja um exemplo de registro de um evento DNS:
{“timestamp”:”2025-04-03T14:26:19.713892-0300″,”flow_id”:1094794285608326,”in_iface”:”eth0″,”event_type”:”dns”,”src_ip”:”165.227.65.66″,”src_port”:48656,”dest_ip”:”67.207.67.3″,”dest_port”:53,”proto”:”UDP”,”pkt_src”:”wire/pcap”,”dns”:{“version”:2,”type”:”answer”,”id”:2188,”flags”:”8180″,”qr”:true,”rd”:true,”ra”:true,”opcode”:0,”rrname”:”zabbixbook.wafproject.cloud”,”rrtype”:”AAAA”,”rcode”:”NOERROR”,”authorities”:[{“rrname”:”wafproject.cloud”,”rrtype”:”SOA”,”ttl”:292,”soa”:{“mname”:”ns65.domaincontrol.com”,”rname”:”dns.jomax.net”,”serial”:2024112901,”refresh”:28800,”retry”:7200,”expire”:604800,”minimum”:600}}]}}
Da mesma forma que monitoramos então eventos do tipo DNS, podemos monitorar eventos do SSH, HTTP, FTP, SFTP, DHCP, etc… Vamos então nos concentrar no arquivo fast.log e tratar alertas e não as infinidades de eventos possíveis.
Monitorando o arquivo fast.log
Com a premissa de que todos os requisitos de um monitoramento ativo são atendidos, vamos criar o item de monitoramento de log para o fast.log.
Name: Suricata main fast.log
Type: Zabbix agent (active)
Key: log[/var/log/suricata/fast.log]
Type of information: Log
Update interval: 1s
History: Do not store
Adicione as tags que desejar.
Não é necessário preprocessing nesse item.
Perceba que não aplicamos nenhum tipo de regex, logo, todas as linhas de log serão coletadas pelo Zabbix Agent2 em um primeiro momento, mas como não estamos armazenando histórico, vamos precisar criar “Dependent items” para extrair os dados de que precisamos.
Então, do que precisamos e como vamos extrair tais dados?
1. Event date: \1
2. Event time: \2
3. Event rule ID: \3
4. Event message: \4
5. Event classification: \5
6. Event priority: \6
7. Event protocol: \7
8. Event source IP: \8
9. Event source port: \9
10. Event destination IP: \10
11. Event destination port: \11
Todos esses dados podem ser extraídos pela seguinte expressão regular, quando aplicada à guia Preprocessing:
(\d\d\/\d\d\/\d\d\d\d)-(\d\d:\d\d:\d\d)\.\d+\s+\[\*\*\]\s+\[\d+:(\d+):\d+\]\s(\S+.*?)\s\[\*\*\]\s\[Classification:\s(\S+.*?)\]\s\[Priority:\s(\d)\]\s\{(\w+)\}\s+(\d+.\d+.\d+.\d+):(\d+).*?(\d+.\d+.\d+.\d+):(\d+)
As cores nos ajudam a diferenciar os grupos de captura e a relacioná-los os campos enumerados logo acima. \1 ou \2 correspondem ao grupo de captura a ser usado no Zabbix na guia Preprocessing.
Aqui então está um exemplo de um dos 11 itens necessários:
Um ensaio de Widget
Dentre os vários arranjos possíveis, achei que uma primeira visão desses eventos poderia ser gerada usando um widget de frontend relativamente novo no Zabbix: Item history. Veja uma prévia do resultado:
Contando os eventos
Uma análise precisa de dados numéricos e não apenas textos. Por isso, vamos avaliar o mesmo log com outra chave do Zabbix: “log.count”. A ideia é ter um quantitativo de alertas recebidos por minuto e com isso, poderemos criar várias outras métricas, tais como médias, baseline e taxas de anomalia dos eventos (o que é um pouco estranho, já que um evento, na verdade, não deveria ocorrer😉).
Usando um item calculado, também podemos obter o maior valor de eventos ocorridos ao longo de uma hora e assim, gerar um pontinho no nosso gráfico que nos ajude a entender, visualmente, a gravidade da situação:
Comparação entre períodos
Em um exercício simples, já podemos comparar a quantidade de eventos ocorridos na hora atual e os da hora anterior, obtendo uma variação percentual, nos dando uma ideia de como está nosso ambiente. Tenha em mente que também é possível criar comparações entre períodos maiores e a lógica segue praticamente a mesma que vamos ver abaixo.
Name: Hourly event percentage change
Type: Calculated
Key: hourly.event.pchange
Type of information: Numeric (float)
Formula:
((sum(//log.count[/var/log/suricata/fast.log],1h:now/h+1h) – sum(//log.count[/var/log/suricata/fast.log],1h:now/h)) / sum(//log.count[/var/log/suricata/fast.log],1h:now/h)) * 100
Unit: %
Update interval: 1m
History: 31d
Trends: 395
O resultado parcial em um widget de frontend seria:
Eventos por prioridade (priority)
Anteriormente, extraímos os dados do campo “priority” do log. Como o próprio nome sugere, a prioridade reflete a severidade de cada alerta gerado, sendo o nível “1” o mais prioritário e a partir de 4, os menos prioritários.
Com isso em mente, podemos gerar uma visão consolidada da última hora sob a ótica dos níveis de alertas gerados. Para isso, é necessário criar um item calculado para cada tipo de severidade disponível.
Atenção: a abordagem que usei nesta POC não reflete o único caminho a ser seguido, por exemplo, as prioridades poderiam ser descobertas por LLD e assim, seriam criadas à medida em que os alertas fossem sendo gerados, contudo, são apenas 5 ou 6 itens previstos. Então, resolvi criá-los manualmente.
Name: The number events with priority 1 last hour
Type: Calculated
Key: countunique.priority.1
Type of information: Numeric (unsigned)
Formula: count(//event.priority,1h,”eq”,1)
Update interval: 1m
Crie mais itens para as outras prioridades, de forma que tenha algo como abaixo:
No meu caso, criei ainda um outro item para prioridades acima de 5:
count(//event.priority,1h,”gt”,5)
Em seguida, o reflexo no widget:
A tarefa agora será de contabilizar os alertas por categoria e nesse caso, usei uma abordagem diferente: LLD.
O Suricata tem um arquivo de configuração com o registro das categorias possíveis. Foi realizada a leitura desse arquivo e dele foi extraído apenas o conteúdo que nos interessava (diferente das prioridades, as categorias estão em número maior e daria certo trabalho cadastrá-las manualmente):
Para ler o arquivo, usei a chave:
vfs.file.contents[/etc/suricata/rules/rules/classification.config]
E trabalhei preprocessing para deixá-lo no ponto de ser usado para um processo de Discovery:
O Javascript em questão, possui o seguinte conteúdo:
// Remove linhas vazias ou com espaços em branco e retorna o resultado
return value.split(‘\n’).filter(function(line) {
return line.trim() !== ”;
}).join(‘\n’);
Os prototypes da LLD terão esse formato:
E o resultado será algo assim:
E nosso widget de frontend, dessa vez em formato Doughnut, terá a seguinte configuração e formato:
Machine Learning e padrões comportamentais
Nosso monitoramento não se baseia apenas em leitura de logs, apesar de isso ser muito divertido e fácil. Vamos aplicar uma camada de ML para gerar o aprendizado do padrão comportamental de nossos eventos (baseline) e, buscar por anomalias no ambiente (Anomaly rate).
As funções no Zabbix para isso são:
baselinewma
trendstl
As fórmulas não serão inseridas aqui, mas apenas os resultados. O motivo pelo qual optei por isso é simples: a baseline é gerada com base na minha regra de negócio, ou melhor, nós podemos dizer o que, como e a partir de quando observar para gerar uma baseline. Logo, minha fórmula pode não ser aplicada ao seu cenário e além disso, a documentação da Zabbix é rica para lhe ajuda nessa compreensão. O mesmo para Anomaly Rate. Veja um resultado prévio:
Ao final, teremos um dashboard mais ou menos assim:
Detectando Eventos
Até agora, observamos os eventos gerados pelo Suricata e criamos um dashboard para auxiliar a camada visual. Contudo, quando falamos de segurança cibernética, falamos de “Monitorar, Detectar e Responder”. Nós monitoramos então com o Suricata e Zabbix, mas ainda não Detectamos ou Respondemos.
Vamos imaginar que, para facilitar a interpretação do termos “Detectar”, para além dos dados já coletados, podemos gerar alertas no Zabbix (que precisarão ser refinados mais tarde).
Uma trigger pode ser o início de tudo:
Certamente, é uma trigger bem genérica algo mais elaborado será necessário. No entanto, nossa POC tem um outro propósito e vai acabar culminando na resposta, para fechar o ciclo.
Basicamente, um alerta gerado pelo Suricata já é uma trigger em si. Então, apenas deixamos o Zabbix gerar o seu próprio evento (novamente, atente-se às flappings).
Respondendo a Eventos
Para encerrar o ciclo dessa POC, vamos gerar Actios para bloquear os atacantes nos endpoints monitorados. Sim, o Zabbix fará o papel de XDR (Extended Detection and Response).
Um script precisa ser criado para ser chamado por uma Action:
Agora, a Action que vai chamar o script quando a trigger que criamos gerar um novo evento:
Através do relatório de Actions, podemos ver o sucesso ou falha dos bloqueios:
Considerações
Para que o Zabbix Agent2 possa realizar o bloqueio do atacante via iptables, é necessário aplicar permissões explícitas a ele. As permissões envolvem configurações no Zabbix Agent2:
AllowKey=system.run[*]
E permissões no sistema operacional (/etc/sudoers):
zabbix ALL=(ALL:ALL) NOPASSWD:ALL
Ambas as configurações estão muito liberais e não são recomendadas. Elas foram criadas assim para fins de celeridade na POC e não deve ser tomada como verdade para todas as ocasiões.
Mapeando os atacantes
Anteriormente, em um de nossos vários itens, filtramos o endereço IP do atacante. Pense que a partir daí, o Zabbix pode fazer uma porção de coisas com esse dado, como por exemplo, confrontá-lo junto a plataformas de Threat Intelligence como MISP (Malware Information Sharing Plataform) ou ainda, algo mais simples, obter dados de geolocalização para criarmos um mapa de atacantes das últimas 24 horas. Faremos esse último.
Não entraremos em detalhes de construção, porém, citaremos alguns passos:
1. Encontre uma API que receba solicitações HTTP e que receba como parâmetro o IP do atacante;
2. Obtenha os campos Latitude e Lontigude e preencha o inventário do host;
3. Crie uma página adicional no seu Dashboard com o Widget de Geomap e dê visibilidade a um grupo que você pode chamar, por exemplo, de “Hosts from Suricata”;
Terá algo mais ou menos assim:
Conclusão
Este artigo não explorou em profundidade todas as opções de integrações possíveis entre Zabbix e Suricata, mas apenas uma visão dos alertas gerados pela ferramenta IDS em um endpoint específico.
Vimos também que com dados de insumos coletados a partir do Suricata, o Zabbix é capaz de ser assertivo com funções de um XDR, bloqueando atacantes no endpoint. O script usado foi simples e pode ser melhorado, por exemplo, não causando entradas duplicadas pelo iptables no firewall.
Com a capacidade de análise do Zabbix, podemos gerar diversos insights sobre os eventos de segurança detectados com itens calculados e funções nativas de aprendizado de máquina.
Monitorar, Detectar e Responder, é uma tríade em Segurança Cibernética que pode ser implementada com ferramentas open source, como Zabbix e Suricata e outras integrações ainda são possíveis, porém, esta é uma prova de conceito.
O template dessa integração está disponível gratuitamente para download em nossa página e será enviado ao Zabbix Integrations para aprovação em breve, estando disponível oficialmente em canal do fabricante Zabbix.