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.
Escreva uma regra Sigma para falhas de logon no Windows, valide, converta para Splunk e teste com eventos bons e ruins.
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.
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:
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.
Veja a regra que você vai montar no laboratório, com cada campo explicado.
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.t1110O 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.
stable, test, experimental, deprecated e unsupported. Uma regra nova que ainda não foi testada em ambiente real fica como experimental.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.selection, é um conjunto de condições sobre campos. Os nomes dos campos são os que a fonte de logs usa.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.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.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.
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.
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.
Crie uma pasta para o laboratório e rode:
python3 -m venv .venv
. .venv/bin/activate
pip install sigma-cliNo 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:
. .venv/Scripts/activateConfira a instalação:
sigma versionNa 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.
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.
sigma check failed_logon.ymlO 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.
sigma plugin install splunkNa máquina usada para este artigo, o comando mostrou Successfully installed plugin 'splunk' e pySigma version is compatible with sigma-cli.
sigma convert -t splunk --without-pipeline failed_logon.ymlA saída foi:
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.
Tente a mesma conversão sem --without-pipeline:
sigma convert -t splunk failed_logon.ymlO 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:
sigma list pipelines
sigma convert -t splunk -p splunk_windows failed_logon.ymlA lista mostrou três pipelines do Splunk: splunk_windows, splunk_sysmon_acceleration e splunk_cim. A conversão com splunk_windows imprimiu:
Parsing Sigma rules
source="WinEventLog:Security" EventCode=4625O 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.
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:
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.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.
Uma regra que converte ainda é um palpite até ser testada. O teste mínimo tem duas metades:
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.
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:
[
{"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:
python test_failed_logon.pyNa máquina usada para este artigo, a saída foi:
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 passedRepare 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.
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:
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: mediumSalve como multi.yml e converta com o mesmo pipeline:
sigma convert -t splunk -p splunk_windows multi.ymlA saída foi:
Parsing Sigma rules
source="WinEventLog:Security" EventCode=4625
| bin _time span=10m
| stats count as event_count by _time TargetUserName
| search event_count >= 5A 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.
EventID. O Splunk usa EventCode depois do pipeline. Misturar os dois nomes numa mesma regra causa falhas silenciosas.--without-pipeline é uma opção deliberada. Não é atalho. A saída pode não rodar na sua plataforma.level: high numa regra barulhenta. A severidade deve refletir o que um acerto significa. Um evento comum sem contexto deve começar como baixo.sigma check testa a estrutura do arquivo. Não testa se a detecção encontra os eventos certos.Depois de ter uma regra que valida, converte e passa nos testes, os próximos passos são diretos:
|contains e |endswith, e o campo category.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.
Detecção e blue team
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.
Detecção e blue team
Leia o log Security do Windows: política de auditoria, eventos 4624, 4625, 4634, 4672, 4688 e 1102, o que o Sysmon acrescenta e um logon com falha seu.