
Biblioteca Go para analizar y ejecutar reglas de detección Sigma contra entradas de registro, soportando modificadores de campo, coincidencia CIDR y resolvedores de campo personalizados para monitoreo de seguridad.
github.com/runreveal/sigmaliteEl paquete sigmalite proporciona un analizador sintáctico y un motor de ejecución para el formato de detección 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
Las reglas se escriben en formato YAML y, como mínimo, deben incluir un title y un :
detectiontitle: My example rule
detection:
keywords:
- foo
- bar
selection:
EventId: 1234
condition: keywords and selection
El campo condition en el bloque detection es una expresión lógica que une otros selectores de campo en el bloque detection. En este ejemplo, esta regla coincidirá con cualquier entrada de registro que tenga un campo EventId que sea exactamente 1234 y tenga "foo" o "bar" en su mensaje.
Los campos también pueden coincidir usando expresiones regulares:
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
Así como 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
Puede encontrar más información en la documentación oficial de reglas Sigma.
Esta biblioteca admite los siguientes modificadores de campo:
La interfaz FieldResolver extiende la especificación estándar de Sigma para admitir escenarios complejos de búsqueda de campos que van más allá de pares clave/valor simples. Esto le permite implementar lógica personalizada de resolución de campos para:
event.process.user)process.*.user o network[*].iptype FieldResolver interface {
Resolve(fieldName string, entry *LogEntry) []string
}
El método Resolve toma un nombre de campo de su regla Sigma y devuelve todos los valores coincidentes como un segmento de cadenas. Si no se encuentran coincidencias, devuelva nil o un segmento vacío.
// 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)
}
Los resolvedores de campos funcionan sin problemas con todos los modificadores de campo, permitiéndole aplicar patrones regex, coincidencias sin distinción de mayúsculas/minúsculas y otras transformaciones a los valores resueltos.