
Библиотека Go для разбора и выполнения правил обнаружения Sigma для записей журналов, поддерживающая модификаторы полей, сопоставление CIDR и пользовательские преобразователи полей для мониторинга безопасности.
github.com/runreveal/sigmaliteПакет sigmalite предоставляет парсер и исполнительный движок для [формата обнаружения Sigma][].
rule, err := sigmalite.ParseRule([]byte(`
title: My example rule
detection:
keywords:
- foo
- bar
selection:
EventId: 1234
condition: keywords and selection
`))
if err != nil {
return err
}
entry := &sigmalite.LogEntry{
Message: "Hello foo",
Fields: map[string]string{
"EventId": "1234",
},
}
isMatch := rule.Detection.Matches(entry, nil)
go get github.com/runreveal/sigmalite
Правила записываются в формате YAML и, как минимум, должны содержать title и :
detectiontitle: My example rule
detection:
keywords:
- foo
- bar
selection:
EventId: 1234
condition: keywords and selection
Поле condition в блоке detection представляет собой логическое выражение, объединяющее другие селекторы полей в блоке detection. В этом примере правило будет соответствовать любой записи журнала, у которой поле EventId равно 1234 и в сообщении содержится "foo" или "bar".
Поля также могут сопоставляться с помощью regular expressions:
title: My example rule with a timestamp
detection:
selection:
Timestamp|re: ^2024-06-01T(01|02|03):[0-5][0-9]:[0-5][0-9]$
condition: selection
А также с помощью CIDRs:
title: My example rule with IP addresses
detection:
local:
DestinationIp|cidr:
- "127.0.0.0/8"
- "10.0.0.0/8"
- "172.16.0.0/12"
- "192.168.0.0/16"
- "169.254.0.0/16"
- "::1/128" # IPv6 loopback
- "fe80::/10" # IPv6 link-local addresses
- "fc00::/7" # IPv6 private addresses
condition: not local
Дополнительную информацию можно найти в official Sigma rules documentation.
Эта библиотека поддерживает следующие field modifiers:
Интерфейс FieldResolver расширяет стандартную спецификацию Sigma для поддержки сложных сценариев поиска полей, выходящих за рамки простых пар ключ/значение. Это позволяет реализовать пользовательскую логику разрешения полей для:
event.process.user)process.*.user или network[*].iptype FieldResolver interface {
Resolve(fieldName string, entry *LogEntry) []string
}
Метод Resolve принимает имя поля из правила Sigma и возвращает все совпадающие значения в виде среза строк. Если совпадений не найдено, возвращается nil или пустой срез.
// CustomResolver demonstrates field resolution for structured logs
type CustomResolver struct{}
func (r *CustomResolver) Resolve(fieldName string, entry *sigma.LogEntry) []string {
switch fieldName {
case "process.users":
// Aggregate user fields from multiple sources
var users []string
if user, ok := entry.Fields["Event.Process.User"]; ok {
users = append(users, user)
}
if user, ok := entry.Fields["Event.Login.User"]; ok {
users = append(users, user)
}
if user, ok := entry.Fields["Event.Session.User"]; ok {
users = append(users, user)
}
return users
case "network.internal_ips":
// Extract all IP addresses from network-related fields
var ips []string
for fieldName, value := range entry.Fields {
if strings.Contains(strings.ToLower(fieldName), "ip") {
// Simple IP validation (in real usage, use proper validation)
if strings.Contains(value, ".") {
ips = append(ips, value)
}
}
}
return ips
default:
return nil
}
}
func matches(detection *sigmalite.Detection) bool {
opts := &sigmalite.MatchOptions{
FieldResolver: CustomResolver{},
},
entry := &sigmalite.LogEntry{
Message: string("Message Text"),
Fields: nil, // Using resolver so this can be empty
}
return detection.Matches(entry, opts)
}
Разрешители полей бесшовно работают со всеми field modifiers, позволяя применять регулярные выражения, сопоставление без учёта регистра и другие преобразования к разрешённым значениям.