Pular para o conteúdo
Novo

DeepSeek V4.1 Flash grátis por 7 dias: 10M tokens por dia após qualquer recarga. Até 30/11.

Como funciona

Escrevendo uma regra Sigma: sua primeira detecção, testada

Escreva uma regra Sigma para falhas de logon no Windows, valide, converta para Splunk e teste com eventos bons e ruins.

Intermediário14 min de leituraPor NotHoly

O que é uma regra Sigma

Sigma é um formato aberto e neutro em relação a fornecedores para descrever uma detecção. Você escreve a lógica uma vez, em um arquivo YAML pequeno, e um conversor a transforma na linguagem de consulta do SIEM ou da plataforma de logs que você realmente usa. Splunk, Elastic, Microsoft Sentinel e outros backends têm conversores, e a mesma regra pode gerar consultas para vários deles.

O formato é mantido pelo projeto SigmaHQ. A especificação fica no repositório sigma-specification, e a documentação de regras no sigmahq.io explica cada campo. Se você sabe ler um evento do Windows, já domina a parte difícil. Uma regra Sigma é só uma forma de dizer "este evento, com estes valores de campo" de um jeito que outras pessoas e outras ferramentas consigam ler.

Por que isso importa

A maior parte da lógica de detecção é escrita direto na linguagem de consulta de um produto. Uma busca do Splunk não roda no Sentinel, e uma consulta KQL não roda no Splunk. Quando uma equipe troca de plataforma, ou quando a comunidade compartilha uma detecção, a lógica precisa ser reescrita do zero. Isso é lento, e a reescrita introduz erros.

O Sigma separa a lógica de detecção da linguagem de consulta. A regra descreve a fonte de logs e a condição. O backend transforma isso em uma consulta. Disso saem duas consequências:

  • Uma regra pode ser compartilhada, revisada e versionada como texto, do mesmo jeito que você revisa código.
  • A mesma regra pode ser testada contra eventos de exemplo antes de chegar a um SIEM de produção.

O segundo ponto é o assunto deste artigo. Uma regra Sigma que é interpretada e convertida não está pronta. Ela só está sintaticamente correta. Ela passa a ser útil quando você consegue mostrar que dispara nos eventos certos e fica quieta nos eventos que deveria ignorar.

As partes de uma regra

Veja a regra que você vai montar no laboratório, com cada campo explicado.

yaml
title: Failed Logon Event
id: bd37e49d-15ab-4e88-a3fb-53594e831b27
status: experimental
description: Detects Windows Security event 4625 (an account failed to log on).
logsource:
    product: windows
    service: security
detection:
    selection:
        EventID: 4625
    condition: selection
falsepositives:
    - Users mistyping passwords
level: low
tags:
    - attack.credential-access
    - attack.t1110

O seu UUID será diferente. Gere o seu com qualquer biblioteca de UUID, por exemplo python -c "import uuid; print(uuid.uuid4())", e mantenha esse valor quando editar a regra depois. O id é como outras ferramentas acompanham a mesma regra entre versões.

  • title é um nome curto e legível. Aparece nos alertas e nas listas de regras.
  • id é um UUID que identifica a regra, não o conteúdo. Mantenha-o estável quando mudar a lógica.
  • status informa ao leitor o quanto confiar na regra. Os valores aceitos são stable, test, experimental, deprecated e unsupported. Uma regra nova que ainda não foi testada em ambiente real fica como experimental.
  • description diz o que a regra procura, em uma ou duas frases.
  • logsource diz de onde vêm os eventos. product: windows e service: security apontam para o log de segurança do Windows. Outros campos, como category, permitem descrever uma classe de logs, por exemplo criação de processo, sem citar o canal exato.
  • detection guarda a lógica de correspondência. Cada bloco nomeado, aqui o selection, é um conjunto de condições sobre campos. Os nomes dos campos são os que a fonte de logs usa.
  • condition diz como os blocos se combinam. selection sozinho significa "eventos que batem com o bloco selection". Mais adiante você vai somar blocos de filtro e combiná-los com and e not.
  • falsepositives lista os casos legítimos que também vão bater. Escrever isso faz parte da regra, não é um detalhe depois.
  • level é a severidade que a regra recebe quando dispara. Os valores aceitos são informational, low, medium, high e critical. Escolha o nível pelo que um acerto significa no seu ambiente, não pelo quanto a técnica parece assustadora.
  • tags ligam a regra a frameworks. O prefixo attack. aponta para uma tática do MITRE ATT&CK, e attack.t1110 aponta para a técnica T1110, Brute Force.

Duas observações sobre esta regra. Primeiro, EventID é o nome do campo no mundo Sigma, e se refere ao Event ID que você lê no Visualizador de Eventos. Segundo, level: low é uma escolha. Uma falha de logon isolada é comum. A regra como está dispara em cada 4625, então um nível baixo é o ponto de partida honesto até você adicionar um limite.

Como o Sigma se mapeia para a linguagem de um SIEM

O Sigma não conhece o seu SIEM. Quem conhece é o backend. O conversor lê a detecção, aplica um pipeline de processamento que renomeia campos e adiciona restrições de índice ou de origem, e escreve uma consulta na linguagem de destino.

Um pipeline de processamento é um conjunto de regras de mapeamento. Ele responde perguntas como: qual é o nome do campo do Event ID no Splunk, qual índice guarda os eventos de segurança do Windows e qual sourcetype a consulta deve buscar. Sem pipeline, o conversor pode devolver o nome do campo Sigma exatamente como foi escrito. Muitas vezes essa saída não serve na plataforma que você usa.

Cada backend tem os próprios pipelines. Alguns são obrigatórios, e o conversor se recusa a continuar sem um, a não ser que você peça explicitamente para pular o pipeline. Você vai ver isso no laboratório.

A ideia é simples: a regra continua a mesma, e o pipeline a adapta para a plataforma. Quando você troca de Splunk para outro SIEM, muda o backend e o pipeline, não a detecção.

Laboratório prático: escrever, validar e converter a regra

O laboratório roda na sua própria máquina. Você não precisa de domínio, de controlador de domínio nem de nenhum sistema-alvo. Você está escrevendo e convertendo uma regra. Não está gerando falhas de logon contra nada, e não deve tentar isso contra um sistema que não seja seu ou para o qual você não tenha permissão por escrito para testar.

Este laboratório foi executado no Windows 11 com Git Bash, Python 3.12 e o log de segurança padrão do Windows. Os comandos são os mesmos no Linux e no macOS, exceto pelo caminho do ambiente virtual.

Passo 1: criar um ambiente virtual e instalar o sigma-cli

Crie uma pasta para o laboratório e rode:

bash
python3 -m venv .venv
. .venv/bin/activate
pip install sigma-cli

No Windows com Git Bash, o python3 pode não estar no seu PATH. Use o caminho completo da instalação do Python 3.12, ou py -3.12. O ambiente virtual também coloca os scripts em .venv/Scripts em vez de .venv/bin, então ative com:

bash
. .venv/Scripts/activate

Confira a instalação:

bash
sigma version

Na máquina usada para este artigo, o sigma-cli 4.0.0 foi instalado junto com o pysigma 2.0.2 e o Python 3.12.10. As suas versões podem ser mais novas. O que vale é a saída da versão que você vê na sua máquina, não os números acima.

Passo 2: escrever a regra

Crie um arquivo chamado failed_logon.yml com o conteúdo mostrado na seção anterior. Gere o seu próprio UUID para o campo id. Salve o arquivo em UTF-8 e sem tabulações na indentação do YAML.

Passo 3: validar a regra

bash
sigma check failed_logon.yml

O sigma check interpreta o arquivo e roda validadores. Ele pega um campo ausente, uma tag malformada, um status ou nível desconhecido e vários problemas de estilo.

Na máquina usada para este artigo, o passo de validação não terminou. O validador de tags carrega os dados do MITRE ATT&CK pela rede. A requisição devolveu um erro de gateway HTTP 504, e o erro se repetiu a cada nova tentativa. A saída foi um traceback terminando em RuntimeError: Failed to load MITRE ATT&CK data, e o código de saída foi 1.

Isso é uma dependência de rede, não um erro da regra. Você deve ver um resultado de aprovação, ou uma lista de problemas do validador, quando os dados carregarem. Se a validação falhar com a mesma mensagem do MITRE, rode de novo mais tarde, ou em uma rede que consiga alcançar a fonte de dados. Não marque a regra como validada até a checagem terminar.

Se a validação apontar problemas, leia cada um. Corrija a regra, não o validador. Um problema com tag geralmente é um erro de digitação, como attack.t1100 em vez de attack.t1110.

Passo 4: instalar o backend do Splunk

bash
sigma plugin install splunk

Na máquina usada para este artigo, o comando mostrou Successfully installed plugin 'splunk' e pySigma version is compatible with sigma-cli.

Passo 5: converter sem pipeline

bash
sigma convert -t splunk --without-pipeline failed_logon.yml

A saída foi:

text
Parsing Sigma rules
EventID=4625

É assim que a regra fica antes de qualquer mapeamento do Splunk. O nome do campo continua sendo o nome Sigma, EventID. Uma busca no Splunk sobre eventos do Windows costuma usar EventCode e uma origem, então essa consulta não encontraria os eventos que você quer numa instalação padrão do add-on do Windows.

Passo 6: converter com o pipeline do Splunk

Tente a mesma conversão sem --without-pipeline:

bash
sigma convert -t splunk failed_logon.yml

O conversor parou e explicou que o backend do Splunk exige um pipeline de processamento. A mensagem pedia que você adicionasse --without-pipeline apenas se soubesse o que estava fazendo. Aqui o pipeline é obrigatório, então o conversor se recusa a gerar a consulta sem ele. Leia essa mensagem como um recurso de segurança.

Agora adicione o pipeline do Windows:

bash
sigma list pipelines
sigma convert -t splunk -p splunk_windows failed_logon.yml

A lista mostrou três pipelines do Splunk: splunk_windows, splunk_sysmon_acceleration e splunk_cim. A conversão com splunk_windows imprimiu:

text
Parsing Sigma rules
source="WinEventLog:Security" EventCode=4625

O pipeline mudou duas coisas. Mapeou EventID para EventCode e acrescentou uma restrição de origem para WinEventLog:Security. O resultado é uma consulta que uma instância do Splunk com o add-on do Windows consegue executar. O seu índice e o seu sourcetype podem ser diferentes, então trate isso como ponto de partida e confira com os seus dados.

Tentar também o pipeline CIM falhou com Rule type not yet supported by the Splunk data model CIM pipeline!. Nem toda regra converte para todo pipeline. Uma falha dessas é uma informação útil: a regra ou o backend não encaixam no mapeamento que você pediu.

Passo 7: comparar com o evento que você gerou

No artigo sobre o log de eventos do Windows, você olhou um evento no Visualizador de Eventos. Abra esse evento de novo e compare com a consulta:

  • O campo Event ID no Visualizador de Eventos deve ser 4625. É o valor que a seleção do Sigma procura.
  • O nome do campo no Visualizador é Event ID. Na saída do Splunk ele aparece como EventCode, porque o pipeline o converte para o nome que o add-on do Windows usa.
  • O source da consulta, WinEventLog:Security, corresponde ao canal de Segurança que você leu no Visualizador de Eventos.

Se o seu evento no Visualizador tiver um Event ID diferente de 4625, a regra não vai bater com ele. Esse é o comportamento correto. A regra trata de falhas de logon, não de todos os eventos do log.

Teste a regra

Uma regra que converte ainda é um palpite até ser testada. O teste mínimo tem duas metades:

  • Eventos conhecidos como ruins. Eventos que a regra precisa pegar. Para esta regra, são eventos 4625.
  • Eventos conhecidos como bons. Eventos que a regra não pode pegar. Logons bem-sucedidos (4624), logoffs (4634) e criação de processo (4688) são bons negativos.

Sem os negativos, você não tem evidência de que a regra é específica. Sem os positivos, não tem evidência de que ela funciona.

Neste laboratório, o teste usa um pequeno arquivo de eventos sintéticos, events.json, com cinco entradas: dois eventos 4625 e três que não devem bater. O script carrega o bloco selection da regra e verifica cada evento. É um teste simplificado. Mostra que a lógica de seleção faz o que você escreveu. Não substitui testar a consulta convertida com dados reais.

python
import json, sys
import yaml

rule = yaml.safe_load(open("failed_logon.yml", encoding="utf-8"))
events = json.load(open("events.json", encoding="utf-8"))

selection = rule["detection"]["selection"]

def selection_matches(event):
    return all(str(event.get(k)) == str(v) for k, v in selection.items())

failures = 0
for ev in events:
    got = "match" if selection_matches(ev) else "no match"
    ok = got == ev["expect"]
    failures += 0 if ok else 1
    print(f"{'PASS' if ok else 'FAIL'}  {ev['name']:<40} expected={ev['expect']:<9} got={got}")

print(f"{len(events) - failures}/{len(events)} passed")
sys.exit(1 if failures else 0)

O arquivo de eventos fica assim:

json
[
  {"name": "known-bad: failed logon", "EventID": 4625, "expect": "match"},
  {"name": "known-bad: failed logon, second try", "EventID": 4625, "expect": "match"},
  {"name": "known-good: successful logon", "EventID": 4624, "expect": "no match"},
  {"name": "known-good: logoff", "EventID": 4634, "expect": "no match"},
  {"name": "known-good: process creation", "EventID": 4688, "expect": "no match"}
]

Rode:

bash
python test_failed_logon.py

Na máquina usada para este artigo, a saída foi:

text
PASS  known-bad: failed logon                  expected=match     got=match
PASS  known-bad: failed logon, second try      expected=match     got=match
PASS  known-good: successful logon             expected=no match  got=no match
PASS  known-good: logoff                       expected=no match  got=no match
PASS  known-good: process creation             expected=no match  got=no match
5/5 passed

Repare no que esse teste mostra e no que não mostra. Ele mostra que a regra bate nos eventos que deve bater e ignora os que deve ignorar. Não mostra que a regra é boa. Uma regra que batesse em todo 4625 passaria nesse teste, porque todo 4625 do arquivo deve bater. O teste é útil, mas só como piso.

O próximo passo, em um ambiente real, é rodar a consulta convertida do Splunk contra um período de logs de segurança do Windows que você sabe que tem falhas de logon e atividade comum. Conte os resultados e abra uma amostra. Cada acerto deve ser um evento 4625. Se a consulta devolver acertos de outros Event IDs, o pipeline ou o mapeamento de campos está errado.

A regra ainda não está pronta

Esta regra dispara em cada 4625. Uma senha digitada errada gera um acerto, e também uma conta de serviço com senha expirada que tenta de novo a cada minuto. Uma tentativa de força bruta são muitas falhas contra a mesma conta em pouco tempo, e a primeira versão não consegue expressar isso.

O Sigma resolve isso com regras de correlação, definidas em uma especificação separada. Uma regra de correlação não casa eventos por conta própria. Ela aponta para uma ou mais regras base pelo name, agrupa os acertos por um campo e aplica uma contagem em uma janela de tempo. O tipo event_count conta acertos, e condition: gte: 5 significa cinco ou mais. Coloque as duas regras no mesmo arquivo, separadas por ---, e dê um name à regra base:

yaml
title: Failed Logon Event
name: failed_logon_event
id: bd37e49d-15ab-4e88-a3fb-53594e831b27
status: experimental
description: Detects Windows Security event 4625 (an account failed to log on).
logsource:
    product: windows
    service: security
detection:
    selection:
        EventID: 4625
    condition: selection
falsepositives:
    - Users mistyping passwords
level: low
tags:
    - attack.credential-access
    - attack.t1110
---
title: Many Failed Logons For One Account
id: 3f6c1d52-8a0e-4b7e-9d2a-6c41e0b7a915
status: experimental
description: Five or more failed logons for the same target account within ten minutes.
correlation:
    type: event_count
    rules:
        - failed_logon_event
    group-by:
        - TargetUserName
    timespan: 10m
    condition:
        gte: 5
falsepositives:
    - Service accounts with an expired password
level: medium

Salve como multi.yml e converta com o mesmo pipeline:

bash
sigma convert -t splunk -p splunk_windows multi.yml

A saída foi:

text
Parsing Sigma rules
source="WinEventLog:Security" EventCode=4625

| bin _time span=10m
| stats count as event_count by _time TargetUserName

| search event_count >= 5

A primeira linha é a regra base. As três linhas seguintes são a correlação: agrupar os eventos em janelas de dez minutos, contar por TargetUserName e manter os grupos com cinco ou mais. Os valores 5 e 10 minutos são provisórios. Escolha-os a partir dos seus dados e teste o resultado com os mesmos eventos bons e ruins. Nem todo backend suporta todo tipo de correlação, então confira a saída do conversor antes de depender dela.

Guarde a primeira versão da regra. Ela é a linha de base, e a comparação com a versão correlacionada mostra se o limite ajuda.

Erros comuns

  • Escrever a regra e pular os negativos. Uma regra só com testes positivos pode bater em tudo e ainda passar. Adicione eventos bons de propósito.
  • Nomear o campo pelo rótulo do Visualizador de Eventos. O Sigma usa EventID. O Splunk usa EventCode depois do pipeline. Misturar os dois nomes numa mesma regra causa falhas silenciosas.
  • Converter sem pipeline e confiar na saída. --without-pipeline é uma opção deliberada. Não é atalho. A saída pode não rodar na sua plataforma.
  • Usar level: high numa regra barulhenta. A severidade deve refletir o que um acerto significa. Um evento comum sem contexto deve começar como baixo.
  • Esquecer o campo falsepositives. Se você não consegue citar um caso legítimo, provavelmente ainda não pensou no ambiente com profundidade suficiente.
  • Trocar o id ao editar a lógica. O id deve identificar a regra ao longo do tempo. Uma regra nova ganha um id novo. Uma regra editada mantém o seu.
  • Tratar a validação aprovada como prova. O sigma check testa a estrutura do arquivo. Não testa se a detecção encontra os eventos certos.

Como ir além

Depois de ter uma regra que valida, converte e passa nos testes, os próximos passos são diretos:

  • Ajuste a regra de correlação com dados reais: mude o limite e a janela de tempo e compare acertos e falsos positivos com a regra base.
  • Leia o resto da especificação do Sigma para ver filtros, modificadores como |contains e |endswith, e o campo category.
  • Converta a mesma regra para um segundo backend, como Elastic ou Splunk SPL2, e compare as consultas. Anote onde o pipeline muda a lógica e onde só renomeia campos.
  • Monte um conjunto de eventos de teste maior, incluindo eventos de um laboratório onde você controla a atividade. Gere falhas de logon apenas em contas e sistemas que são seus, e somente em um laboratório que você tem permissão para testar.

Resumindo: uma regra é uma afirmação sobre eventos. Escreva a afirmação, converta, e depois mostre com eventos que devem bater e eventos que não devem.

Fontes

Fontes

  1. SigmaHQ, Sigma specification
  2. SigmaHQ, Sigma rules documentation
  3. SigmaHQ, sigma-cli
  4. MITRE ATT&CK, T1110 Brute Force
  5. SigmaHQ, Sigma correlation rules specification

Mais em Detecção e blue team

Detecção e blue team

O que é um SIEM? Logs, consultas e alertas

Um SIEM coleta logs, normaliza os campos, roda regras de correlação e gera alertas para triagem. Aprenda o caminho com um exemplo que você executa.

Iniciante14 min de leitura