YARA-L 2.0-Abfrage-Referenzbibliothek
In diesem Dokument werden Abfragen in YARA-L 2.0 gezeigt. In jedem Beispiel wird gezeigt, wie Ereignisse in der Abfrageregel-Sprache korreliert werden, um Sicherheitsrisiken zu erkennen, das Verhalten von Entitäten zu überwachen und Erkennungen mit Geschäftslogik anzureichern.
Verwenden Sie die Beispiele als Bausteine für YARA-L 2.0, einschließlich der Erkennung einzelner Ereignisse, des Abgleichs regulärer Ausdrücke und der Filterung von Netzwerkbereichen. Die Beispiele sind in funktionale Kategorien unterteilt, damit Sie sich von der einfachen Logik zu erweiterten Korrelationen mehrerer Ereignisse und zusammengesetzten Erkennungen vorarbeiten können.
Grundlegende Syntax und Grundlagen
Die Beispiele in diesem Abschnitt zeigen, wie UDM-Ereignisse effektiv korreliert und Abfragen in der Regelsprache strukturiert werden.
Abfrage für ein einzelnes Ereignis
Anwendungsfall: Einfache Erkennung eines bestimmten Ereignistyps (z. B. USER_LOGIN), ohne dass eine Korrelation über ein Zeitfenster hinweg erforderlich ist.
Schlüssellogik: Hier werden nur die Abschnitte „Ereignisse“ und „Bedingung“ verwendet, um ein einzelnes Vorkommen zu identifizieren. Eine Regel für ein einzelnes Ereignis kann Folgendes sein:
- Jede Regel ohne
match-Abschnitt. - Regel mit einem
match-Abschnitt und einemcondition-Abschnitt, in dem nur das Vorhandensein eines Ereignisses geprüft wird (z. B.$e,#e > 0,#e >= 1,1 <= #e,0 < #e).
Beispiel: Suche nach der ersten Nutzeranmeldung
Regel
Im folgenden Beispiel wird nach einem Nutzeranmeldeereignis (USER_LOGIN) gesucht und das erste Ereignis zurückgegeben, das in den Unternehmensdaten in Ihrem Google SecOps-Konto gefunden wird:
rule SingleEventRule {
meta:
author = "noone@altostrat.com"
events:
$e.metadata.event_type = "USER_LOGIN"
condition:
$e
}
Suchen
In diesem Beispiel für eine nicht aggregierte Suche werden einzelne Ereignisse direkt ausgegeben. Da für diese Abfrage keine Ereigniskorrelation erforderlich ist, werden Ereignisvariablen wie $e1 weggelassen.
metadata.event_type = "USER_LOGIN"
Dashboard
Da sich diese Abfragelogik darauf konzentriert, bestimmte, nicht korrelierte Ereignisse in ihrem Rohzustand zu präsentieren, werden die für Dashboard-Visualisierungen erforderlichen Abschnitte match oder outcome nicht verwendet.
Beispiel: Anmeldungserkennung nach fünf Minuten
Regel
Im folgenden Beispiel sehen Sie eine Regel für ein einzelnes Ereignis, in der der Abschnitt match verwendet wird, um alle Nutzer mit mindestens einem Anmeldeereignis innerhalb eines 5-Minuten-Zeitfensters (5m) zu finden. Es wird geprüft, ob ein Nutzeranmeldeereignis vorhanden ist.
rule SingleEventRule {
meta:
author = "alice@example.com"
description = "windowed single event example rule"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user over 5m
condition:
#e > 0
}
Suchen
In diesem statistischen Suchbeispiel werden Aktivitäten in gleitenden Fenstern von fünf Minuten (5m) zusammengefasst. Die Ausgabe erfolgt in einer Zeile pro Nutzer und Fenster. Da sich die Abfrage auf Volumenzahlen pro Fenster konzentriert, werden event-Variablen und condition-Abschnitte weggelassen, da die Ergebnisse von Natur aus ein oder mehrere Ereignisse enthalten. In dieser Version wird ein rollierendes Fenster anstelle eines springenden Fensters verwendet, damit die Ergebnisse auf der Plattform richtig gerendert werden.
metadata.event_type = "USER_LOGIN"
principal.user.userid = $user
match:
$user by 5m
Dashboard
Das folgende Beispiel enthält den Abschnitt outcome, um die Gesamtzahl der Ereignisse pro Nutzer zu berechnen. So lassen sich die Daten als statistischer Wert im Zeitverlauf darstellen. In der Abfrage wird ein rollierendes Fenster anstelle eines springenden Fensters verwendet, um sicherzustellen, dass die Datenpunkte diskreten, nicht überlappenden Buckets zugeordnet werden. So wird eine übersichtlichere Visualisierung für Dashboard-Trends ermöglicht.
metadata.event_type = "USER_LOGIN"
principal.user.userid = $user
match:
$user by 5m
outcome:
$event_count = count(metadata.id)
Abfragen und Optimieren
Anwendungsfall: Windows-svchost.exe erkennen, die aus nicht standardmäßigen Verzeichnissen gestartet werden.
Schlüssel-Logik: Negation (not) in Kombination mit dem Abgleich regulärer Ausdrücke.
Beispiel: Prozesserkennung auf Grundlage von Ausschlüssen
Regel
Mit der folgenden Regel wird nach bestimmten Mustern in Ereignisdaten gesucht. Wenn die Muster gefunden werden, wird eine Erkennung erstellt. Diese Regel enthält eine Variable $e1 zum Erfassen des Ereignistyps und des UDM-Felds metadata.event_type. Die Regel prüft auf bestimmte Vorkommen von Übereinstimmungen mit regulären Ausdrücken mit e1. Wenn das Ereignis $e1 eintritt, wird eine Erkennung erstellt. Die Regel enthält eine not-Bedingung, um bestimmte nicht schädliche Pfade auszuschließen. Sie können not-Bedingungen hinzufügen, um falsch positive Ergebnisse zu vermeiden.
rule suspicious_unusual_location_svchost_execution
{
meta:
author = "Google Cloud Security"
description = "Windows 'svchost' executed from an unusual location"
yara_version = "YL2.0"
rule_version = "1.0"
events:
$e1.metadata.event_type = "PROCESS_LAUNCH"
re.regex($e1.principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
not re.regex($e1.principal.process.command_line, `\\Windows\\System32\\`) nocase
condition:
$e1
}
Suchen
In diesem Beispiel wird eine nicht aggregierte Suche durchgeführt, um einzelne Ereignisse auszugeben. Da für diese Suche keine Ereigniskorrelation über mehrere Instanzen hinweg erforderlich ist, sind Ereignisvariablen wie $e1 nicht notwendig.
metadata.event_type = "PROCESS_LAUNCH"
re.regex(principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
not re.regex(principal.process.command_line, `\\Windows\\System32\\`) nocase
Dashboard
Diese Syntax enthält die Abschnitte match und outcome, um das Ereignisvolumen im Zeitverlauf zu berechnen. Mit der Funktion timestamp.get_timestamp() werden Ergebnisse nach Tag gruppiert, um Trends zu visualisieren.
metadata.event_type = "PROCESS_LAUNCH"
re.regex(principal.process.command_line, `\bsvchost(\.exe)?\b`) nocase
not re.regex(principal.process.command_line, `\\Windows\\System32\\`) nocase
$date = timestamp.get_timestamp(metadata.event_timestamp.seconds)
match:
$date
outcome:
$event_count = count(metadata.id)
Netzwerkbereich und ‑logik
Anwendungsfall: Aktivitäten basierend auf bestimmten IP-Subnetzen (CIDR) filtern und mit mehreren möglichen Hostnamen abgleichen.
Wichtige Konzepte:
net.ip_in_range_cidr(): Mit dieser Funktion wird geprüft, ob eine bestimmte IP-Adresse in einem bestimmten CIDR-Subnetz (Classless Inter-Domain Routing) für den Subnetzabgleich und den OR-Operator für String-Arrays enthalten ist.- Logischer Operator
OR: Wird verwendet, um mehrere Bedingungen zu kombinieren. Bedingungen im Ereignisabschnitt werden implizit mitANDkombiniert. Der OperatorORwird für mehrere mögliche Hostnamen ausgeführt.
Beispiel: Abgleich einzelner Ereignisse (IP-Bereich)
Regel
Das folgende Beispiel zeigt eine Regel für ein einzelnes Ereignis, mit der nach Übereinstimmungen zwischen zwei bestimmten Hostnamen und einem bestimmten IP-Adressbereich gesucht wird:
rule OrsAndNetworkRange {
meta:
author = "noone@altostrat.com"
events:
// Checks CIDR ranges.
net.ip_in_range_cidr($e.principal.ip, "203.0.113.0/24")
// Detection when the hostname field matches either value using or.
$e.principal.hostname = /pbateman/ or $e.principal.hostname = /sspade/
condition:
$e
}
Suchen
Im folgenden Beispiel werden Ereignisse identifiziert, bei denen eine bestimmte IP-Adresse in einen definierten CIDR-Bereich fällt und der Hostname einem bestimmten Nutzermuster entspricht:
net.ip_in_range_cidr(principal.ip, "203.0.113.0/24")
principal.hostname = /pbateman/ or principal.hostname = /sspade/
Da es sich um eine Suchanfrage und nicht um eine Erkennungsregel handelt, wird das gesamte Ereignis automatisch zurückgegeben, wenn die Filterkriterien erfüllt sind. In einem match-Abschnitt werden Daten nach principal.ip und principal.hostname gruppiert. Ein condition-Abschnitt ist nicht erforderlich und Ereignisvariablen ($e) werden ausgelassen, da keine Ereigniskorrelation durchgeführt wird.
Dashboard
In der folgenden Beispielabfrage werden Ergebnisse durch Gruppieren eindeutiger IP- und Hostname-Paare zusammengefasst:
net.ip_in_range_cidr(principal.ip, "203.0.113.0/24")
principal.hostname = /pbateman/ or principal.hostname = /sspade/
match:
principal.ip, principal.hostname
Reguläre Ausdrücke in Abfragen
Anwendungsfall: Es wird nach flexiblen Stringmustern gesucht (z. B. nach bestimmten Domains in E‑Mails), wobei die Groß- und Kleinschreibung ignoriert wird. Diese Funktion wird am häufigsten in der Suche und in Regeln verwendet.
Schlüssellogik: Hier wird /regex/ nocase für einfache Übereinstimmungen und die Funktion re.regex() für komplexe Feldanalysen verwendet.
Beispiel: E-Mail-Filterung
Regel
Im folgenden Beispiel für einen regulären Ausdruck in YARA-L 2.0 wird nach Ereignissen mit E-Mails gesucht, die von der Domain altostrat.com empfangen wurden. Da nocase der Variablen $host-Vergleich und der Funktion regex hinzugefügt wurde, wird bei diesen Vergleichen nicht zwischen Groß- und Kleinschreibung unterschieden.regex
rule RegexRuleExample {
meta:
author = "noone@altostrat.com"
events:
$e.principal.hostname = $host
$host = /.*HoSt.*/ nocase
re.regex($e.network.email.from, `.*altostrat\.com`) nocase
match:
$host over 10m
condition:
#e > 10
}
Suchen
In der Suchoberfläche wird diese Logik für die Suche nach Bedrohungen und die Datenanalyse verwendet. Anstatt auf eine automatische Benachrichtigung zu warten, können Analysten die UDM manuell abfragen, um bestimmte Instanzen von Hostnamen zu ermitteln, die einer Namenskonvention zusammen mit bestimmten E‑Mail-Domains entsprechen. Dies ist die primäre Methode, um das Volumen dieser Ereignisse zu validieren, bevor sie in eine dauerhafte Erkennungsregel aufgenommen werden.
principal.hostname = $host
$host = /.*HoSt.*/ nocase
re.regex(network.email.from, `.*altostrat\.com`) nocase
match:
$host over 10m
```
Dashboard
Mit der folgenden Logik werden interessante Muster ermittelt, indem hostname- und email-Telemetriedaten in 10‑Minuten-Buckets (10m) zusammengefasst werden. Wenn diese Logik in einem Dashboard verwendet wird, können Analysten die Kommunikationshäufigkeit von bestimmten Assets (die mit host übereinstimmen) zur Domain altostrat.com visualisieren. Diese Ansicht ist wichtig, um Trends bei der internen Datenübertragung zu beobachten und Top-Talker in der kritischen Infrastruktur zu identifizieren.
principal.hostname = $host
$host = /.*HoSt.*/ nocase
re.regex(network.email.from, `.*altostrat\.com`) nocase
match:
$host over 10m
```
Beispiel: Regulärer Ausdruck für Hostname
Regel
Im folgenden Beispiel wird jede Log-Aktivität ermittelt, bei der das Hauptkonto hostname als Webserver (webserver) oder Entwicklungsserver (devserver) identifiziert wird. Es wird ein regulärer Ausdruck verwendet, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird, damit Abweichungen bei den Namenskonventionen nicht zu verpassten Erkennungen führen.
rule WebServerOrDevServerActivity {
meta:
author = "Alex"
description = "Detects events where the principal hostname is 'webserver' or 'devserver', ignoring case."
severity = "Informational"
events:
$e.principal.hostname = /webserver|devserver/ nocase
condition:
$e
}
Suchen
Im folgenden Beispiel entspricht principal.hostname = /webserver|devserver/ nocase Hostnamen wie "WebServer01", "devserver-test" und "MyWebServers". Dies ist ein häufiger Anwendungsfall, um ein bestimmtes Ereignis zu finden.
// Use /regex/ followed by nocase for a case-insensitive match
principal.hostname = /webserver|devserver/ nocase
Dashboard
Dieses spezielle Beispiel wird zwar nicht in einem Dashboard visualisiert, aber diese Regel bietet aktive Benachrichtigungen und eine kontinuierliche Erkennung. Im Gegensatz zu einem Dashboard, das eine manuelle Überprüfung erfordert, wird so sichergestellt, dass jede Aktivität auf diesen Servern automatisch gekennzeichnet und in der Erkennungs-Engine aufgezeichnet wird, damit sie sofort durchsucht werden kann.
Beispiel: Logs zu Rohdaten suchen
Regel
Während Sie die manuelle Suche für zeitpunktbezogene Untersuchungen verwenden, bieten Erkennungsregeln ein kontinuierliches Telemetrie-Monitoring rund um die Uhr. Sie können eine erfolgreiche Suchanfrage in eine YARA-L-Regel umwandeln, um den Benachrichtigungsprozess zu automatisieren.
Wichtige Vorteile von Regeln:
- Benachrichtigungen in Echtzeit: Übereinstimmungen werden automatisch gekennzeichnet, sobald sie im System eingehen.
- Persistenz: Suchbegriffe müssen nicht mehr manuell eingegeben werden.
- Outcome actions: Werden direkt in die Erkennungsansicht für die Triage durch Analysten und die Incident Response eingespeist.
Suchen
Sicherheitsanalysten verwenden häufig regex, um in Google SecOps in unaufbereiteten, nicht geparsten Logs zu suchen. Diese Aktion ermöglicht flexibles Musterabgleich, um bestimmte Artefakte zu finden, auch wenn sie nicht vollständig strukturiert oder indexiert sind. In der Syntax werden Schrägstriche verwendet:
raw = /host/
Diese Abfrage gibt alle Rohlogzeilen zurück, in denen die Zeichenfolge "host" vorkommt. Beispiele für übereinstimmende Rohlog-Inhalte sind "hostname": "myhost123".
Dashboard
Für diesen bestimmten Ereignistyp gibt es keine spezielle Dashboard-Variante. So können Sie diese Erkennungen im großen Maßstab visualisieren:
- Ordnen Sie
metadata.event_typeim Dashboard-Generator einem Balken- oder Kreisdiagramm zu. - Beobachten Sie die Häufigkeit dieser Ereignisse in Zeiträumen von 7, 30 oder 90 Tagen, um Anomalien im Nutzerverhalten zu erkennen.
Wiederkehrende Felder mit universellen Bedingungen
Anwendungsfall: Audit-Ereignisse, die Listen mit Daten (wiederholte Felder) enthalten, prüfen, um sicherzustellen, dass keine vertrauenswürdigen Ausnahmen vorhanden sind. Prüfen Sie beispielsweise, ob jede IP-Adresse, die mit einer Anmeldung verknüpft ist, außerhalb eines bekannten sicheren Bereichs liegt.
Schlüssellogik: Hier wird der Operator all verwendet, um jedes Element in einem wiederholten Feld anhand einer bestimmten Bedingung auszuwerten. Außerdem wird gezeigt, wie durch Zuweisen eines wiederholten Felds zu einer Platzhaltervariablen (z. B. $ip) eine separate Erkennung für jeden eindeutigen Wert in der Liste erstellt wird.
Beispiel: Validierung der IP-Adresse bei verdächtigen Anmeldungen
Regel
Mit der folgenden Regel wird nach Anmeldeereignissen gesucht, bei denen alle Quell-IP-Adressen innerhalb eines Zeitraums von fünf Minuten (5m) nicht mit einer als sicher bekannten IP-Adresse übereinstimmen.
rule SuspiciousIPLogins {
meta:
author = "alice@example.com"
events:
$e.metadata.event_type = "USER_LOGIN"
// Detects if all source IP addresses in an event do not match "100.97.16.0"
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// it will be detected since "100.97.16.1", "100.97.16.2",
// and "100.97.16.3" all do not match "100.97.16.0".
all $e.principal.ip != "100.97.16.0"
// Assigns placeholder variable $ip to the $e.principal.ip repeated field.
// There will be one detection per source IP address.
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// there will be one detection per address.
$e.principal.ip = $ip
match:
$ip over 5m
condition:
$e
}
Suchen
metadata.event_type = "USER_LOGIN"
// Detects if all source IP addresses in an event do not match "100.97.16.0"
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// it will be detected since "100.97.16.1", "100.97.16.2",
// and "100.97.16.3" all do not match "100.97.16.0".
all principal.ip != "100.97.16.0"
// Assigns placeholder variable $ip to the $e.principal.ip repeated field.
// There will be one detection per source IP address.
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// there will be one detection per address.
principal.ip = $ip
match:
$ip over 5m
Dashboard
metadata.event_type = "USER_LOGIN"
// Detects if all source IP addresses in an event do not match "100.97.16.0"
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// it will be detected since "100.97.16.1", "100.97.16.2",
// and "100.97.16.3" all do not match "100.97.16.0".
all principal.ip != "100.97.16.0"
// Assigns placeholder variable $ip to the $e.principal.ip repeated field.
// There will be one detection per source IP address.
// For example, if an event has source IP addresses
// ["100.97.16.1", "100.97.16.2", "100.97.16.3"],
// there will be one detection per address.
principal.ip = $ip
match:
$ip over 5m
Erweiterte Fensterung
In diesem Abschnitt werden mehrstufige Muster und Erkennungen behandelt, die durch Aktivitäten aus anderen Regeln ausgelöst werden.
Korrelation mehrerer Ereignisse
In diesem Abschnitt finden Sie Beispiele dafür, wie Sie Entitäten (Nutzer oder Hosts) über mehrere Ereignisse oder Zeiträume hinweg verfolgen können, um Verhaltensmuster zu erkennen.
Anwendungsfall: Erkennt unmögliche Reisen, bei denen sich ein einzelner Nutzer innerhalb von weniger als fünf (5m) Minuten in zwei oder mehr Städten anmeldet.
Schlüssellogik: Verwenden Sie den Bereich match, um nach $user und #city > 1 zu gruppieren und eindeutige Standortwerte zu finden.
Beispiel: Erkennung von Log-ins in mehreren Städten
Regel
Die folgende Regel sucht nach Nutzern, die sich innerhalb von weniger als 5 Minuten (5m) von zwei oder mehr Städten aus in Ihrem Unternehmen angemeldet haben. Dabei ist $user die Variable match, $udm die Ereignisvariable und $city und $user die Platzhaltervariablen:
rule DifferentCityLogin {
meta:
events:
$udm.metadata.event_type = "USER_LOGIN"
$udm.principal.user.userid = $user
$udm.principal.location.city = $city
match:
$user over 5m
condition:
$udm and #city > 1
}
Im Folgenden wird die Funktionsweise dieser Regel beschrieben:
- Gruppiert Ereignisse mit dem Nutzernamen (
$user) und gibt sie zurück ($user), wenn eine Übereinstimmung gefunden wird. - Die Zeitspanne beträgt fünf Minuten (
5m). Es werden nur Ereignisse korreliert, die weniger als fünf Minuten (5m) auseinanderliegen. - Sucht nach einer Ereignisgruppe (
$udm), deren EreignistypUSER_LOGINist. - Für diese Ereignisgruppe wird die Nutzer-ID in der Regel als
$userund die Stadt der Anmeldung als$citybezeichnet. - Gibt eine Übereinstimmung zurück, wenn die Anzahl der eindeutigen
city-Werte (angegeben durch#city) in der Ereignisgruppe ($udm) innerhalb des 5‑Minuten-Zeitraums (5m) größer als1ist.
Suchen
Mit der folgenden Beispielabfrage wird eine entsprechende statistische Suche ausgeführt, um Muster für unmögliche Fahrten zu erkennen. Die USER_LOGIN-Ereignisse werden nach Nutzer innerhalb eines 5-Minuten-Zeitraums (5m) gruppiert und die Ergebnisse werden so gefiltert, dass nur Instanzen angezeigt werden, in denen mehrere unterschiedliche Städte für eine einzelne Identität erkannt werden.
events:
metadata.event_type = "USER_LOGIN"
principal.user.userid = $user
principal.location.city = $city
match:
$user over 5m
condition:
#city > 1
Dashboard
Die folgende Beispielabfrage liefert eine entsprechende Dashboard-Visualisierung, um potenzielle Konto-Hacks zu verfolgen. Dabei werden USER_LOGIN-Ereignisse nach Nutzer über ein Zeitfenster von fünf Minuten (5m) zusammengefasst und nach Fällen gefiltert, in denen eine einzelne Identität mit mehr als einer unterschiedlichen Stadt (#city) verknüpft ist. So können Sie diese geografischen Anomalien mit hohem Risiko im Zeitverlauf darstellen.
events:
metadata.event_type = "USER_LOGIN"
principal.user.userid = $user
principal.location.city = $city
match:
$user over 5m
condition:
#city > 1
Schnelles Erstellen und Löschen von Nutzern
Anwendungsfall: Identifiziert Burner-Konten, die erstellt wurden, und löscht sie dann innerhalb von vier Stunden.
Schlüssel-Logik: Verknüpft zwei Ereignistypen (
USER_CREATIONundUSER_DELETION) anhand einer gemeinsamen$user-Variablen und vergleicht Zeitstempel.
Beispiel: Schnelles Erstellen und Löschen von Nutzern
Regel
Im folgenden Beispiel wird nach Nutzern gesucht, die innerhalb von vier Stunden erstellt und dann gelöscht wurden (4h). Dabei sind $create und $delete die Ereignisvariablen, $user die Variable match und es gibt keine Platzhaltervariablen:
rule UserCreationThenDeletion {
meta:
events:
$create.target.user.userid = $user
$create.metadata.event_type = "USER_CREATION"
$delete.target.user.userid = $user
$delete.metadata.event_type = "USER_DELETION"
$create.metadata.event_timestamp.seconds <=
$delete.metadata.event_timestamp.seconds
match:
$user over 4h
condition:
$create and $delete
}
Suchen
Im folgenden Beispiel wird eine Suche nach Statistiken mit mehreren Ereignissen verwendet, um schnelle Änderungen im Kontolebenszyklus zu erkennen. Mit dieser Abfrage wird eine Zeile pro Nutzer innerhalb eines vierstündigen Zeitraums ausgegeben, in der die Erstellung und Löschung von Identitäten korreliert werden.
Da bei der Suche standardmäßig alle Zeiträume zurückgegeben werden, die die angegebenen Ereignisse enthalten, ist kein condition-Abschnitt erforderlich.
$create.target.user.userid = $user
$create.metadata.event_type = "USER_CREATION"
$delete.target.user.userid = $user
$delete.metadata.event_type = "USER_DELETION"
$create.metadata.event_timestamp.seconds <=
$delete.metadata.event_timestamp.seconds
match:
$user over 4h
Dashboard
Das folgende Beispiel zeigt eine Suche in einem Dashboard mit mehreren Ereignissen, mit der Trends im Kontolebenszyklus im Zeitverlauf dargestellt werden sollen. Durch die Verwendung eines rollierenden Fensters (by 4h) werden die Ergebnisse diskreten, nicht überlappenden Zeit-Buckets zugeordnet, was sich ideal für die Visualisierung eignet.
Diese Variante enthält einen outcome-Abschnitt, um die Anzahl der eindeutigen Erstellungsereignisse in jedem Fenster zu berechnen. Im Gegensatz zur vorherigen Suche müssen in dieser Version keine bestimmten Ereignisvariablen zurückgegeben werden, da der Schwerpunkt auf aggregierten statistischen Werten und nicht auf einzelnen Logzeilen liegt.
$create.target.user.userid = $user
$create.metadata.event_type = "USER_CREATION"
$delete.target.user.userid = $user
$delete.metadata.event_type = "USER_DELETION"
$create.metadata.event_timestamp.seconds <=
$delete.metadata.event_timestamp.seconds
match:
$user by 4h
outcome:
$event_count = count_distinct($create.metadata.id)
Gleitendes Fenster in Abfragen
Anwendungsfall: Erkennen eines potenziellen Sicherheitsproblems, bei dem auf ein erstes Ereignis (von firewall_1) nicht innerhalb eines bestimmten Zeitrahmens ein erwartetes nachfolgendes Ereignis (von firewall_2) auf demselben Host folgt.
Wichtige Logik:
- Pivot-Ereignis: Die Regel basiert auf Ereignissen aus
firewall_1, die als$e1gekennzeichnet sind. Jedes Mal, wenn ein$e1-Ereignis eintritt, dient es als Ausgangspunkt. - Zeitfenster: Im Abschnitt
match($host over 10m after $e1) wird ein 10-minütiges Zeitfenster definiert, das unmittelbar nach jedem$e1-Ereignis beginnt. Dieses Zeitfenster gleitet mit jedem neuen$e1-Ereignis. - Korrelation: Ereignisse werden nach Hostname (
$host) gruppiert. - Bedingung für die Erkennung (
$e1und$e2): Eine Erkennung wird für einen bestimmten Host ausgelöst, wenn:- Ein Ereignis von
firewall_1($e1) ist vorhanden. AND: Innerhalb des 10-Minuten-Fensters nach dem jeweiligen$e1-Ereignis wird für denselben Host einNO-Ereignis vonfirewall_2($e2) gefunden.
- Ein Ereignis von
Beispiel: Erkennen fehlender sequenzieller Ereignisse
Regel
Im folgenden Beispiel werden Instanzen ermittelt, in denen ein sekundäres Ereignis nach einem primären Trigger nicht eintritt. Durch die Verwendung der Bedingung !$e2 innerhalb eines 10-Minuten-Fensters werden mit dieser Regel fehlende Telemetriedaten gekennzeichnet, insbesondere wenn ein Firewall-Log an einem Ort zu sehen ist, aber nicht am nächsten erwarteten Hop. Dies deutet auf eine potenzielle Lücke bei der Sichtbarkeit oder einen Rückgang des Traffics hin.
rule MissingSequentialEvent {
meta:
author = "alice@example.com"
events:
$e1.metadata.product_name = "firewall_1"
$e1.principal.hostname = $host
$e2.metadata.product_name = "firewall_2"
$e2.principal.hostname = $host
match:
// $e1 is the pivot; the 10-minute window starts at the $e1 timestamp
$host over 10m after $e1
condition:
$e1 and !$e2
}
Suchen
Im folgenden Beispiel wird eine sequenzielle Suche verwendet, um Lücken in der Telemetrie zwischen zwei Quellen zu identifizieren. Wenn Sie $e1 als Pivot verwenden, wird nach einem primären Firewallereignis gesucht, auf das innerhalb von 10 Minuten kein entsprechendes Ereignis auf einer zweiten Firewall folgt. Dies ist eine sehr effektive Methode, um bei einer Untersuchung manuell nach „Black Holes“ im Netzwerkverkehr oder nach Protokollierungsfehlern zu suchen.
$e1.metadata.product_name = "firewall_1"
$e1.principal.hostname = $host
$e2.metadata.product_name = "firewall_2"
$e2.principal.hostname = $host
match:
// $e1 is the pivot; the 10-minute window starts at the $e1 timestamp
$host over 10m after $e1
condition:
$e1 and !$e2
Dashboard
Im folgenden Beispiel sehen Sie eine Analyse der Sichtbarkeitslücke für eine Dashboardansicht. Wenn Sie Instanzen zusammenfassen, in denen ein sekundäres Ereignis nicht auf ein primäres Ereignis folgt, können Sie die Zuverlässigkeit Ihrer Logging-Pipeline im Zeitverlauf visualisieren. Wenn Sie diese „fehlenden“ Ereignisse darstellen, können Sie dauerhafte Funklöcher in der Netzwerksichtbarkeit oder Konfigurationsprobleme für bestimmte Hostnamen identifizieren.
$e1.metadata.product_name = "firewall_1"
$e1.principal.hostname = $host
$e2.metadata.product_name = "firewall_2"
$e2.principal.hostname = $host
match:
// $e1 is the pivot; the 10-minute window starts at the $e1 timestamp
$host over 10m after $e1
condition:
$e1 and !$e2
Abfragen mit mehreren Ereignissen
Anwendungsfall: Aktivitäten mit hoher Häufigkeit oder Brute-Force-Aktivitäten erkennen, indem eine einzelne Einheit (z. B. ein Nutzer oder Host) über mehrere Vorkommen eines Ereignisses innerhalb eines bestimmten Zeitfensters hinweg verfolgt wird.
Schlüssellogik: Hier wird ein
match-Abschnitt verwendet, um Ereignisse nach einer bestimmten Variablen zu gruppieren, und eincondition-Abschnitt, um innerhalb des definierten Zeitraums nach einer Schwellenwertanzahl (z. B.#e >= 10) zu suchen.
Eine typische Regel mit mehreren Ereignissen umfasst:
- Ereignisvariablen zum Unterscheiden von Ereignissen.
- Ein
match-Abschnitt, in dem der Zeitraum angegeben wird, über den Ereignisse gruppiert werden müssen. - Ein
condition-Abschnitt, in dem angegeben wird, unter welcher Bedingung die Erkennung ausgelöst werden soll und ob mehrere Ereignisse vorhanden sind.
In der Suche werden Abfragen mit mehreren Ereignissen durch mehr als ein Ereignis in einer Abfrage definiert. Für Regeln gibt es zwei Möglichkeiten, dies zu definieren:
Mehrere Ereignisse: (z. B.
event1 = successful login, event2 = failed login).Bedingungsbasierte Trigger: Die Bedingung wird so formuliert, dass sie nur ausgelöst wird, wenn mehrere Ereignisse die Kriterien erfüllen (z. B.
event1 > 10). Diese Art von Regel muss auch einenoutcome-Abschnitt enthalten.
Beispiel: Erkennung häufiger Anmeldungen
Regel
Die folgende Regel sucht nach einem Nutzer, der sich in weniger als 10 Minuten mindestens 10-mal angemeldet hat:
rule MultiEventRule {
meta:
author = "noone@altostrat.com"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user over 10m
condition:
#e >= 10
}
Suchen
Im folgenden Beispiel wird eine Suche nach Statistiken für mehrere Ereignisse verwendet, um Anmeldeaktivitäten mit hoher Häufigkeit zu ermitteln. Sie kennzeichnet alle Fälle, in denen ein einzelner Nutzer innerhalb von 10 Minuten (10m) 10 oder mehr Anmeldeereignisse generiert.
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user by 10m
condition:
#e >= 10
Dashboard
Im folgenden Beispiel wird eine Suche mit mehreren Ereignissen verwendet, um nach potenziellen Konto-Hacks zu suchen. Durch die Korrelation von Anmeldeversuchen in einem gleitenden 10‑Minuten-Fenster werden Fälle erkannt, in denen ein bestimmter Nutzer und Host mehrere fehlgeschlagene Anmeldungen gefolgt von einer erfolgreichen Anmeldung durchlaufen. So können Sie Authentifizierungsmuster mit hohem Risiko in Echtzeit visualisieren.
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $user
match:
$user by 10m
condition:
#e >= 10
Abfragen mit mehreren Ereignissen und berechneten Ergebnissen
Anwendungsfall: Mit bedingter Logik können Sie einen
risk_scorebasierend auf dem Schweregrad des Assets oder dem Netzwerkvolumen festlegen.Schlüssellogik: Im Abschnitt
outcomewerden Variablen berechnet und im Bedingungsabschnitt wird nach diesen Variablen gefiltert.
Beispiel: Brute-Force-Angriff gefolgt von erfolgreicher Anmeldung
Im folgenden Beispiel wird der Abschnitt outcome verwendet, um Ereignisse in einem match-Zeitraum zu zählen. Diese Abfrage generiert dieselbe Ausgabe wie eine Standardabfrage mit mehreren Ereignissen, zeigt aber, wie berechnete Variablen in die Erkennungslogik eingebunden werden.
Regel
rule PossibleBruteForceThenSuccessfulLogin {
meta:
author = "Alex"
description = "Detects multiple failed login attempts followed by a successful login for the same user and host within a 10-minute window."
severity = "High"
tactic = "Credential Access"
events:
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a time window: by 10m.
// The rule will evaluate all events matching $failed or $success that share the same $user and $hostname within any given 10-minute period.
$user, $hostname by 10m
outcome:
// Calculate aggregate values from the events within the match window.
$failed_login_count = count($failed.metadata.id)
$successful_login_count = count($success.metadata.id)
condition:
// The conditions that must be met *within each matched group* ($user, $hostname over 10m).
// - #failed >= 5: There must be 5 or more events matching the $failed criteria.
// - #success >= 1: There must be at least 1 event matching the $success criteria.
#failed >= 5 and #success >= 1
}
Suchen
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a sliding time window: over 10m.
// The rule will evaluate all events matching $failed or $success that share
// the same $user and $hostname within any given 10-minute period.
$user, $hostname over 10m
Dashboard
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a sliding time window: over 10m.
// The rule will evaluate all events matching $failed or $success that share
// the same $user and $hostname within any given 10-minute period.
$user, $hostname over 10m
Beispiel: Host-Abgleich mit Zeitfenster
Regel
In der folgenden Regel werden zwei Ereignisse betrachtet, um den Wert von $hostname abzurufen. Wenn der Wert von $hostname über einen Zeitraum von 5 Minuten (5m) übereinstimmt, wird ein Schweregrad angewendet. Wenn Sie im Abschnitt match einen Zeitraum angeben, wird die Regel innerhalb des angegebenen Zeitraums geprüft.
rule OutcomeRuleMultiEvent {
meta:
author = "Google Cloud Security"
events:
$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname
$severity = $asset_context.graph.entity.asset.vulnerabilities.severity
match:
$hostname over 5m
outcome:
$risk_score =
max(
100
+ if($hostname = "my-hostname", 100, 50)
+ if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}
Suchen
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a sliding time window: over 10m.
// The rule will evaluate all events matching $failed or $success that share
// the same $user and $hostname within any given 10-minute period.
$user, $hostname over 10m
outcome:
// Calculate aggregate values from the events within the match window.
$failed_login_count = count($failed.metadata.id)
$successful_login_count = count($success.metadata.id)
```
Dashboard
// Define the first type of event: Failed Login
// We use $failed to represent any event matching these criteria.
$failed.metadata.event_type = "USER_LOGIN"
$failed.security_result.action = "FAIL"
// Extract common fields to correlate on
$failed.target.user.userid = $user
$failed.principal.hostname = $hostname
// Define the second type of event: Successful Login
// We use $success to represent any event matching these criteria.
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
// Correlate using the same user and hostname placeholders
$success.target.user.userid = $user
$success.principal.hostname = $hostname
match:
// This section is key for multi-event rules. It groups events:
// - By the common placeholder variables: $user and $hostname.
// - Within a sliding time window: over 10m.
// The rule will evaluate all events matching $failed or $success that share
// the same $user and $hostname within any given 10-minute period.
$user, $hostname over 10m
outcome:
// Calculate aggregate values from the events within the match window.
$failed_login_count = count($failed.metadata.id)
$successful_login_count = count($success.metadata.id)
Zusammengesetzte Erkennungen
Zusammengesetzte Erkennungen verbessern die Bedrohungserkennung durch die Verwendung zusammengesetzter Regeln. Diese zusammengesetzten Regeln verwenden Erkennungen aus anderen Regeln als Eingabe. So können komplexe Bedrohungen erkannt werden, die mit einzelnen Regeln möglicherweise nicht erkannt werden. Weitere Informationen finden Sie unter Übersicht über zusammengesetzte Erkennungen.
Filterung von Inhalten mit hohem Risiko
Anwendungsfall: Vorhandene Erkennungen nach Attributen mit hohem Risiko filtern, z. B. Aktivitäten mit Administratorkonten.
Schlüssellogik: Wird auf Ergebnisse oder Metadatenfelder in vorhandenen Ergebnissen angewendet.
Zusammengesetzte Erkennungen für das Filtern mit hohem Risiko sind die einfachste Form einer zusammengesetzten Erkennung, die auf Feldern innerhalb von Erkennungsergebnissen basiert, z. B. Ergebnisvariablen oder Regelmetadaten. Sie helfen, Erkennungen nach Bedingungen zu filtern, die auf ein höheres Risiko hinweisen können, z. B. ein Administratornutzer oder eine Produktionsumgebung.
Beispiel: Erkennung von Nutzern mit Administratorzugriff
Regel
Mit der folgenden zusammengesetzten Regel wird nach vorhandenen Erkennungen gesucht, bei denen der Akteur als Nutzer mit Administratorzugriff identifiziert wird, und es wird eine standardisierte Risikobewertung angewendet.
rule composite_admin_detection {
meta:
rule_name = "Detection with Admin User"
author = "Google Cloud Security"
description = "Composite rule that looks for any detections where the actor is an admin user"
severity = "Medium"
events:
$rule_name = $d.detection.detection.rule_name
$principal_user = $d.detection.detection.variables["principal_users"]
$principal_user = /admin|root/ nocase
match:
$principal_user over 1h
outcome:
$risk_score = 75
$upstream_rules = array_distinct($rule_name)
condition:
$d
}
Suchen
Mit der folgenden statistischen Suche werden Aktivitäten für Konten mit hohen Berechtigungen ermittelt und aggregiert. Sie soll alle eindeutigen Regelnamen anzeigen, die Erkennungen mit „admin“- oder „root“-Nutzern ausgelöst haben.
In dieser speziellen Abfrage wird das Zeitfenster entfernt, um eine einzelne statistische Analyse für alle erkannten Ereignisse im ausgewählten Zeitraum durchzuführen. Da es sich außerdem um eine nicht aggregierte Suche handelt, die sich auf vorhandene Erkennungsdaten konzentriert, sind die Abschnitte „Ereignisse“, „Ereignisvariablen“ und „Bedingung“ nicht erforderlich.
$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_users"]
$principal_user = /admin|root/ nocase
match:
$principal_user
outcome:
$upstream_rules = array_distinct($rule_name)
Dashboard
Mit dieser Dashboard-Abfrage können Sie visualisieren, mit welchen Regeln am häufigsten administratorbezogene Aktivitäten erkannt werden. Sie soll einen allgemeinen Überblick über die Erkennungstrends in Ihrer Umgebung bieten.
Beachten Sie die Änderung der Variablen match und der outcome-Aggregation im Vergleich zu den vorherigen Beispielen. In dieser Abfrage werden die Ergebnisse nach Regelname gruppiert und die Anzahl der für jede Regel erkannten Administratornutzer wird berechnet.
$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_users"]
$principal_user = /admin|root/ nocase
match:
$rule_name
outcome:
$admin_detections = count($principal_user)
Aggregation und Schwellenwerte
Anwendungsfall: Nutzer oder Hosts identifizieren, die im Laufe der Zeit eine große Anzahl von Warnungen generieren oder erhebliche Risikobewertungen ansammeln.
Schlüssel-Logik: Hier werden sum() oder count_distinct() verwendet, um aggregierte Erkennungsdaten zu analysieren.
Mit Regeln für die Erkennung von Aggregationszusammensetzungen können Sie Erkennungsergebnisse anhand gemeinsamer Attribute wie Hostname oder Nutzername gruppieren und die aggregierten Daten analysieren. Im Folgenden sind einige gängige Anwendungsfälle aufgeführt:
- Nutzer identifizieren, die eine große Anzahl von Sicherheitswarnungen oder ein hohes aggregiertes Risiko verursachen.
- Erkennen von Hosts mit ungewöhnlichen Aktivitätsmustern durch Aggregieren zugehöriger Erkennungen.
Beispiel: Risikoaggregation
Regel
Bei dieser Regel wird der Risikowert eines einzelnen Nutzers über einen Zeitraum von 48 Stunden aggregiert. Es werden Nutzer identifiziert, deren kumulatives Risiko bei mehreren Erkennungen einen bestimmten Schwellenwert überschreitet.
In dieser aktualisierten Logik wird detection.detection.outcomes durch Variablen für Kartenfelder ersetzt, in denen sowohl die Variablen match als auch outcome gespeichert werden. Außerdem wird die Ergebnisvariable $principal_users entfernt, da jede Erkennung genau einen Wert für die Abgleichsvariable enthält, der bereits erfasst wird.
rule composite_risk_aggregation {
meta:
rule_name = "Risk Aggregation Composite"
author = "Google Cloud Security"
description = "Composite detection that aggregates risk of a user over 48 hours"
severity = "High"
events:
$rule_name = $d.detection.detection.rule_name
$principal_user = $d.detection.detection.outcomes["principal_users"]
$risk = $d.detection.detection.risk_score
match:
$principal_user over 48h
outcome:
$risk_score = 90
$cumulative_risk = sum($risk)
$upstream_rules = array_distinct($rule_name)
condition:
$d and $cumulative_risk > 500
}
Suchen
Bei dieser statistischen Suche werden Erkennungsdaten zusammengefasst, um das Gesamtrisiko eines Nutzers über einen Zeitraum von 48 Stunden zu berechnen. Es wird eine Zeile pro Hauptnutzer für jedes Zeitfenster ausgegeben, die einen allgemeinen Überblick über das Kontorisiko bei mehreren Erkennungstypen bietet.
In dieser Variante sind keine Ereignisvariablen erforderlich. Die Regelausführung filtert zwar automatisch Erkennungen ohne Hauptnutzer heraus, für diese Suche ist jedoch ein expliziter Filter ($principal_user != "") erforderlich, damit die Ergebnisse nur ausgefüllte Daten enthalten. Standardmäßig werden bei der Abfrage nur Ergebnisse zurückgegeben, wenn für einen bestimmten Nutzer mindestens ein Erkennungsvorgang vorhanden ist.
$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_user"]
$principal_user != ""
$risk = detection.detection.risk_score
match:
$principal_user over 48h
outcome:
$risk_score = 90
$cumulative_risk = sum($risk)
$upstream_rules = array_distinct($rule_name)
condition:
$cumulative_risk > 500
Dashboard
Diese Variante wurde speziell für Dashboards entwickelt, um das Nutzerrisiko und die Erkennungsaktivitäten im Zeitverlauf darzustellen. Die Daten werden in diskrete Gruppen zusammengefasst. Das ist ideal, um Trends zu visualisieren, z. B. das Volumen der ausgelösten eindeutigen Regeln oder die Gesamtzahl der erkannten Verstöße pro Nutzer.
In dieser Abfrage wird das Fenster von einem gleitenden (Hop-)Fenster zu einem rollierenden Fenster (by 48h) gewechselt. So werden Datenpunkte nicht überlappenden Zeitsegmenten zugeordnet, was eine übersichtlichere Visualisierung für Zeitreihendiagramme ermöglicht. Wie bei anderen nicht aggregierten Suchanfragen sind keine Ereignisvariablen erforderlich. Der Bereich outcome wird erweitert, um eindeutige Zählungen für sowohl Regelnamen als auch Erkennungs-IDs zu enthalten.
$rule_name = detection.detection.rule_name
$principal_user = detection.detection.variables["principal_user"]
$principal_user != ""
$risk = detection.detection.risk_score
match:
$principal_user by 48h
outcome:
$cumulative_risk = sum($risk)
$rule_count = count_distinct($rule_name)
$detection_count = count_distinct(detection.id)
condition:
$cumulative_risk > 500
Taktikaggregation
Anwendungsfall: Identifizieren Sie Nutzer, deren Aktivitäten Erkennungen für mehrere unterschiedliche MITRE ATT&CK-Taktiken ausgelöst haben. Dies deutet auf einen fortschreitenden Angriffszyklus hin, z. B. von Initial Access (Erster Zugriff) zu Exfiltration (Exfiltration).
Schlüssellogik: Mit count_distinct($tactic) wird das Auslösen nur dann ausgelöst, wenn ein Nutzer innerhalb von 48 Stunden einen bestimmten Schwellenwert für verschiedene Taktiken überschreitet.
Beispiel: Aggregation von MITRE-Taktiken
Regel
rule composite_tactic_aggregation {
meta:
rule_name = "MITRE Tactic Aggregation Composite"
author = "Google Cloud Security"
description = "Composite detection that detects if a user has triggered detections over multiple mitre tactics."
severity = "Medium"
events:
$principal_user = $d.detection.detection.outcomes["principal_users"]
$tactic = $d.detection.detection.outcomes["mitre_tactic"]
$rule_name = $d.detection.detection.rule_name
match:
$principal_user over 48h
outcome:
$mitre_tactics_count = count_distinct($tactic)
$mitre_tactics = array_distinct($tactic)
$calculated_risk = 50 + (15 * $mitre_tactics_count)
$upstream_rules = array_distinct($rule_name)
condition:
$d and $mitre_tactics_count > 1 }
Suchen
Das folgende Beispiel zeigt eine Suchvariante für Sicherheitsentwickler, die vorhandene Erkennungen in Beziehung setzen und eine dynamische Risikogewichtung anwenden müssen. Mit dieser Abfragelogik werden MITRE ATT&CK-Taktiken und Nutzerinformationen aus der Datenquelle detection extrahiert, die Aktivitäten nach dem Hauptnutzer gruppiert und ein benutzerdefinierter Risikowert basierend auf der Vielfalt der beobachteten Taktiken berechnet.
detection.detection.outcomes.key = "principal_users"
detection.detection.outcomes.key = "mitre_tactic"
$principal_user = detection.detection.outcomes["principal_users"]
$tactic = detection.detection.outcomes["mitre_tactic"]
$rule_name = detection.detection.rule_name
match:
$principal_user
outcome:
$mitre_tactics_count = count_distinct($tactic)
$mitre_tactics = array_distinct($tactic)
$upstream_rules = array_distinct($rule_name)
$calculated_risk = 50 + (15 * $mitre_tactics_count)
$risk_score = if($calculated_risk > 100, 100, $calculated_risk)
Dashboard
Das folgende Beispiel veranschaulicht eine Dashboards-Variante derselben Logik für die Anomalieerkennung. Wenn diese Abfrage in Google SecOps Dashboards verwendet wird, können Entwickler Nutzer mit hohem Risiko visualisieren, indem sie Erkennungsergebnisse aus verschiedenen Regeln korrelieren. Die Logik extrahiert den Prinzipal und die MITRE-Taktiken, aggregiert die Ergebnisse und wendet einen begrenzten Risikowert an, um die Priorisierung von Prüfungen direkt in einem Dashboard-Widget zu unterstützen.
detection.detection.outcomes.key = "principal_users"
detection.detection.outcomes.key = "mitre_tactic"
$principal_user = detection.detection.outcomes["principal_users"]
$tactic = detection.detection.outcomes["mitre_tactic"]
$rule_name = detection.detection.rule_name
match:
$principal_user
outcome:
$mitre_tactics_count = count_distinct($tactic)
$mitre_tactics = array_distinct($tactic)
$upstream_rules = array_distinct($rule_name)
$calculated_risk = 50 + (15 * $mitre_tactics_count)
$risk_score = if($calculated_risk > 100, 100, $calculated_risk)
```
Sequenzielle zusammengesetzte Erkennungen
Anwendungsfall: Kritische Angriffsmuster identifizieren, bei denen die Reihenfolge der Vorgänge entscheidend ist, z. B. einen erfolgreichen Kontologin erkennen, der erst nach einer Reihe von Brute-Force-Versuchen von derselben IP-Adresse erfolgt.
Schlüssel-Logik: Korreliert eine vorherige Erkennung mit einem nachfolgenden UDM-Rohereignis, indem sie anhand einer gemeinsamen Variablen (z. B. $bruteforce_ip) verknüpft werden und ein Zeitstempelvergleich verwendet wird, um sicherzustellen, dass die Ereignisse in der richtigen Reihenfolge aufgetreten sind.
Bei sequenziellen zusammengesetzten Erkennungen werden Muster von zusammenhängenden Ereignissen erkannt, bei denen die Reihenfolge der Erkennungen wichtig ist, z. B. die Erkennung eines Brute-Force-Anmeldeversuchs, gefolgt von einer erfolgreichen Anmeldung. Diese Muster können mehrere Basis-Erkennungen oder eine Kombination aus Basis-Erkennungen und Ereignissen umfassen.
Beispiel: Brute-Force-Angriff gefolgt von erfolgreicher Anmeldung
Regel
Mit der folgenden zusammengesetzten Regel werden Muster von zusammenhängenden Ereignissen identifiziert, bei denen die Reihenfolge wichtig ist. Es wird speziell nach einer Google Workspace-Brute-Force-Erkennung gesucht, gefolgt von einem erfolgreichen Anmeldeereignis von derselben Quell-IP innerhalb eines Zeitraums von 24 Stunden.
rule composite_bruteforce_login {
meta:
rule_name = "Bruteforce Login Composite"
author = "Google Cloud Security"
description = "Detects when an IP address associated with a Workspace brute force attempt successfully logs in"
severity = "High"
events:
$bruteforce_detection.detection.detection.rule_name = /Workspace Anomalous Failed Logins/
$bruteforce_ip = $bruteforce_detection.detection.detection.variables["principal_ips"]
$login_event.metadata.product_name = "login"
$login_event.metadata.product_event_type = "login_success"
$login_event.metadata.vendor_name = "Google Workspace"
$login_ip = $login_event.principal.ip
// Ensure the brute force detection and successful login occurred from the same IP
$login_ip = $bruteforce_ip
$target_account = $login_event.target.user.email_addresses
// Ensure the brute force detection occurred before the successful login
$bruteforce_detection.detection.detection_time.seconds < $login_event.metadata.event_timestamp.seconds
match:
$bruteforce_ip over 24h
outcome:
$risk_score = 90
$principal_users = array_distinct($target_account)
condition:
$bruteforce_detection and $login_event
}
Suchen
$bruteforce_detection.detection.detection.rule_name = /Workspace Anomalous Failed Logins/
$bruteforce_ip = $bruteforce_detection.detection.detection.variables["principal_ips"]
$login_event.metadata.product_name = "login"
$login_event.metadata.product_event_type = "login_success"
$login_event.metadata.vendor_name = "Google Workspace"
$login_ip = $login_event.principal.ip
// Ensure the brute force detection and successful login occurred from the same IP
$login_ip = $bruteforce_ip
$target_account = $login_event.target.user.email_addresses
// Ensure the brute force detection occurred before the successful login
$bruteforce_detection.detection.detection_time.seconds < $login_event.metadata.event_timestamp.seconds
match:
$bruteforce_ip over 24h
outcome:
$principal_users = array_distinct($target_account)
condition:
$bruteforce_detection and $login_event
Dashboard
In Dashboards werden Rohdaten zu Ereignissen visualisiert, während die zusammengesetzte Erkennungslogik vorhandene Erkennungsbenachrichtigungen mit nachfolgenden Ereignissen in Beziehung setzt. Diese mehrschichtige Analyse ist für die Erkennungs-Engine und nicht für Echtzeit-Dashboard-Widgets optimiert.
Kontextsensitive Erkennungen
Anwendungsfall: Vorhandene Erkennungen mit externer Threat Intelligence anreichern, um zu prüfen, ob eine Benachrichtigung bekannte schädliche Entitäten enthält. So kann beispielsweise geprüft werden, ob eine in einer Sicherheitserkennung gekennzeichnete IP-Adresse auch in einem globalen Threat-Feed für TOR-Exit-Knoten aufgeführt ist.
Schlüssellogik: Hier werden zusammengesetzte Regeln verwendet, um Erkennungsergebnisse mit GLOBAL_CONTEXT-Graphendaten (z. B. Google Cloud Threat Intelligence-Feeds) zu verknüpfen, indem ein gemeinsames Attribut wie eine IP-Adresse abgeglichen wird.
Kontextsensitive zusammengesetzte Erkennungen werden mit zusätzlichem Kontext angereichert, z. B. mit IP-Adressen, die in Threat-Feeds gefunden wurden.
Beispiel: Anreicherung von Threat Intelligence
Regel
Mit der folgenden zusammengesetzten Regel wird Ihren vorhandenen Erkennungen automatisch zusätzlicher Kontext aus dem TOR-Informationsfeed hinzugefügt. Dabei wird eine IP-Adresse, die in einer früheren Erkennung gefunden wurde, mit dem Feed für TOR-Ausgangsknoten in Beziehung gesetzt, um den Schweregrad und die Risikobewertung des Ergebnisses zu erhöhen.
rule composite_tor_enrichment {
meta:
rule_name = "Detection with IP from TOR Feed"
author = "Google Cloud Security"
description = "Adds additional context from the TOR intel feed to detections"
severity = "High"
events:
$rule_name = $d.detection.detection.rule_name
$gcti.graph.metadata.entity_type = "IP_ADDRESS"
$gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence"
$gcti.graph.metadata.source_type = "GLOBAL_CONTEXT"
$gcti.graph.metadata.product_name = "GCTI Feed"
$gcti.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes"
$detection_ip = $d.detection.detection.variables["principal_ips"]
$detection_ip = $gcti.graph.entity.ip
match:
$detection_ip, $rule_name over 1h
outcome:
$risk_score = 80
condition:
$d and $gcti
}
Suchen
``` $rule_name = $d.detection.detection.rule_name
$gcti.graph.metadata.entity_type = "IP_ADDRESS" $gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence" $gcti.graph.metadata.source_type = "GLOBAL_CONTEXT" $gcti.graph.metadata.product_name = "GCTI Feed" $gcti.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes"
$detection_ip = $d.detection.detection.variables["principal_ips"] $detection_ip = $gcti.graph.entity.ip
match: $detection_ip, $rule_name over 1h
Bedingung: $d and $gcti ```
Dashboard
Erkennung von gemeinsam auftretenden Begriffen
Anwendungsfall: Erkennen einer Kombination aus verwandten Taktiken, die von derselben Entität innerhalb eines bestimmten Zeitrahmens ausgelöst werden, z. B. Erkennen eines Nutzers, der innerhalb von 48 Stunden sowohl eine Erkennung von Rechteausweitung als auch eine Erkennung von Daten-Exfiltration ausgelöst hat.
Schlüssel-Logik: Hier wird eine Form der Aggregation verwendet, um mehrere unterschiedliche Erkennungstypen zu korrelieren. Dazu werden sie im Abschnitt match über eine gemeinsame Entitätsvariable (z. B. $pe_user) verknüpft.
Zusammengesetzte Co-occurrence-Erkennungen sind eine Form der Aggregation, mit der eine Kombination aus zusammengehörigen Ereignissen erkannt werden kann, z. B. eine Kombination aus Erkennungen von Rechteausweitung und Daten-Exfiltration, die von einem Nutzer ausgelöst werden.
Beispiel: Gleichzeitiges Auftreten von Rechteausweitung und Exfiltration
Regel
Mit der folgenden zusammengesetzten Regel wird innerhalb eines Zeitraums von 48 Stunden nach einer bestimmten Sequenz oder Kombination von erkannten Ereignissen gesucht, die mit demselben Nutzer verknüpft sind: Rechteausweitung gefolgt von Exfiltration.
rule composite_privesc_exfil_sequential {
meta:
rule_name = "Privilege Escalation and Exfiltration Composite"
author = "Google Cloud Security"
description = "Looks for a detection sequence of privilege escalation followed by exfiltration."
severity = "High"
events:
$privilege_escalation.detection.detection.rule_labels["tactic"] = "TA0004"
$exfiltration.detection.detection.rule_labels["tactic"] = "TA0010"
$privesc_user = $privilege_escalation.detection.detection.variables["principal_users"]
$exfil_user = $exfiltration.detection.detection.variables["principal_users"]
$privesc_user = $exfil_user
$privilege_escalation.detection.detection_time.seconds < $exfiltration.detection.detection_time.seconds
match:
$privesc_user over 48h
outcome:
$risk_score = 75
$privesc_rules = array_distinct($privilege_escalation.detection.detection.rule_name)
$exfil_rules = array_distinct($exfiltration.detection.detection.rule_name)
condition:
$privilege_escalation and $exfiltration
}
Suchen
$privilege_escalation.detection.detection.rule_labels["tactic"] = "TA0004"
$exfiltration.detection.detection.rule_labels["tactic"] = "TA0010"
$privesc_user = $privilege_escalation.detection.detection.variables["principal_users"]
$exfil_user = $exfiltration.detection.detection.variables["principal_users"]
$privesc_user = $exfil_user
$privilege_escalation.detection.detection_time.seconds < $exfiltration.detection.detection_time.seconds
match:
$privesc_user over 48h
outcome:
$privesc_rules = array_distinct($privilege_escalation.detection.detection.rule_name)
$exfil_rules = array_distinct($exfiltration.detection.detection.rule_name)
condition:
$privilege_escalation and $exfiltration
Dashboard
Ergebnis- und Variablenverwaltung
In diesem Abschnitt finden Sie Beispiele für die Berechnung des Risikos und die Normalisierung von Daten für die nachgelagerte Nutzung.
Suchanfragen mit dem Abschnitt outcome
Sie können den optionalen Abschnitt outcome in einer YARA-L 2.0-Regel hinzufügen, um zusätzliche Informationen zu den einzelnen Erkennungen zu extrahieren. Im Abschnitt condition können Sie auch Bedingungen für Ergebnisvariablen angeben. Im Abschnitt outcome einer Erkennungsregel können Sie Variablen für die nachgelagerte Verwendung festlegen. Sie können beispielsweise einen Schweregrad auf Grundlage der Daten der analysierten Ereignisse festlegen.
Hier finden Sie weitere Informationen:
- Syntax des Ergebnisbereichs
- Syntax für Bedingungsabschnitte
- Abschnitt „Kontextsensitiver Zugriff“
outcome
Bedingungen für Ergebnisse
Anwendungsfall: Erkennungen anhand von berechneten Risikobewertungen filtern, um Rauschen zu reduzieren und dafür zu sorgen, dass nur Ereignisse mit hoher Konfidenz oder hohem Schweregrad Warnungen auslösen. Das ist nützlich, um Aktivitäten mit geringem Risiko zu unterdrücken, die einen bestimmten geschäftlichen Schwellenwert nicht erreichen.
Schlüssellogik: Definiert Variablen im outcome-Abschnitt mithilfe von bedingter Mathematik (z. B. Hinzufügen von Risiko basierend auf der Dateigröße oder der Tageszeit) und verweist dann im condition-Abschnitt auf diese Variablen, um die Erkennung zu steuern.
Beispiel: Nach berechnetem Risikowert filtern
Regel
Im Abschnitt condition können Sie outcome-Variablen verwenden, die im Abschnitt outcome definiert wurden. Im folgenden Beispiel wird gezeigt, wie Sie mithilfe von Ergebnisbedingungen nach Risikobewertungen filtern, um das Rauschen bei Erkennungen zu reduzieren.
rule OutcomeConditionalRule {
meta:
author = "alice@example.com"
description = "Rule that uses outcome conditionals"
events:
$u.metadata.event_type = "FILE_COPY"
$u.principal.file.size = $file_size
$u.principal.hostname = $hostname
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week($u.metadata.collected_timestamp.seconds)
outcome:
$risk_score =
if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices
condition:
$u and $risk_score >= 10
}
Suchen
metadata.event_type = "FILE_COPY"
principal.file.size = $file_size
principal.hostname = $hostname
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.collected_timestamp.seconds)
outcome:
$risk_score =
if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices
Dashboard
Mit dieser Abfrage wird die Ergebnisvariable $hostname hinzugefügt, um zu visualisieren, welche Hosts mit den einzelnen Risikobewertungen verknüpft sind.
metadata.event_type = "FILE_COPY"
principal.file.size = $file_size
principal.hostname = $hostname
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.collected_timestamp.seconds)
outcome:
$host = $hostname
$risk_score =
if($file_size > 500*1024*1024, 2) + // Files 500MB are moderately risky
if($file_size > 1024*1024*1024, 3) + // Files over 1G get assigned extra risk
if($dayofweek=1 or $dayofweek=7, 4) + // Events from the weekend are suspicious
if($hostname = /highly-privileged/, 5) // Check for files from highly privileged devices
Abfrage mit einem einzelnen Ereignis und Ergebnis
Anwendungsfall: Momentaufnahmen mit sofortigem Kontext anreichern, z. B. Schweregrad-Tags basierend auf Nutzerlisten oder Dateiattributen zuweisen, ohne dass ein Zeitfenster oder eine Ereigniskorrelation erforderlich ist.
Schlüssellogik: Verwendet den Abschnitt outcome in einer Regel, in der kein Abschnitt match vorhanden ist. So können Sie Metadaten extrahieren und bedingte Logik ausführen (z. B. einen Nutzer mit einer Referenzliste abgleichen) für jedes einzelne Ereignis, das die Kriterien erfüllt.
Beispiel: Schweregrad-Tagging zu einem bestimmten Zeitpunkt
Regel
Im folgenden Beispiel wird gezeigt, wie Sie den Abschnitt outcome in einer Einzelereignisregel verwenden, um Variablen für die nachgelagerte Verwendung festzulegen. So können Sie beispielsweise einen Schweregrad basierend auf dem jeweiligen Nutzer und der Dateigröße festlegen, die an einem Dateikopierereignis beteiligt sind.
rule OutcomeRuleSingleEvent {
meta:
author = "alice@example.com"
events:
$u.metadata.event_type = "FILE_COPY"
$u.principal.file.size = $file_size
$u.principal.hostname = $hostname
outcome:
$suspicious_host = $hostname
$admin_severity = if($u.principal.user.userid in %admin_users, "SEVERE", "MODERATE")
$severity_tag = if($file_size > 1024, $admin_severity, "LOW")
condition:
$u
}
Suchen
Im folgenden Beispiel werden Ereignisse zum Erstellen von Dateien erkannt und der Abschnitt outcome wird verwendet, um jedem Ergebnis dynamisch Schweregrade zuzuweisen. Im Gegensatz zu Regeln mit mehreren Ereignissen sind für diese nicht aggregierte Suche keine Ereignisvariablen oder ein match-Abschnitt erforderlich. Stattdessen wird jedes Log einzeln verarbeitet, um 1 row per event auszugeben, das mit benutzerdefinierter Logik basierend auf Dateigröße und Nutzerberechtigungen angereichert wird.
metadata.event_type = "FILE_CREATION"
principal.file.size = $file_size
principal.hostname = $hostname
outcome:
$suspicious_host = $hostname
$admin_severity = if(principal.user.userid in %a1, "SEVERE", "MODERATE")
$severity_tag = if($file_size > 1024, $admin_severity, "LOW")
Dashboard
Eine Dashboard-Variante ist für dieses Beispiel nicht relevant, da die primäre Absicht darin besteht, einzelne Ereignisse zu taggen und anzureichern. In einem Dashboard könnten diese Ereignisse aggregiert werden, z. B. durch Berechnung der Gesamtzahl der Ereignisse pro Schweregrad-Tag. Dadurch würden jedoch die detaillierten Informationen auf Zeilenebene, die durch diese nicht aggregierte Suche ermittelt werden sollen, verdeckt.
Netzwerkbasierte Risikobewertung
Anwendungsfall: Identifizieren Sie Datenübertragungen mit hohem Risiko, indem Sie das kumulative Volumen des Netzwerkverkehrs für eine Gruppe von Ereignissen berechnen. So können Sie Bedrohungen identifizieren, bei denen der Gesamtdatenschwellenwert ein bestimmtes Limit überschreitet (z. B. 1024 Byte), und gleichzeitig die Schwere der Sicherheitslücke der beteiligten Assets berücksichtigen.
Schlüssellogik: Hier wird die Aggregatfunktion sum() im Abschnitt outcome verwendet, um sent_bytes und received_bytes für alle Ereignisse in einem match-Zeitraum zu kombinieren. Bei Regeln wird in der Abfrage eine „if“-Anweisung verwendet, um einen höheren Risikowert anzuwenden, wenn die Summe einen definierten Grenzwert überschreitet.
Beispiel: Netzwerkbasierte Regel für die Risikobewertung
Regel
Im folgenden Beispiel wird gezeigt, wie Sie den Abschnitt outcome verwenden, um eine dynamische Risikobewertung basierend auf der Netzwerkaktivität zu berechnen. Durch Summieren der insgesamt übertragenen Bytes über eine Ereignisgruppe hinweg wird durch die Regel eine höhere Priorität auf Treffer angewendet, die einen bestimmten Datenschwellenwert (1024 Byte) überschreiten, während gleichzeitig die Schwere der Sicherheitslücke des beteiligten Assets berücksichtigt wird.
rule OutcomeRuleMultiEvent {
meta:
author = "alice@example.com"
events:
$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname
$severity = $asset_context.graph.entity.asset.vulnerabilities.severity
match:
$hostname over 5m
outcome:
$total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)
$risk_score = if($total_network_bytes > 1024, 100, 50) +
max(
if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
}
Suchen
Im folgenden Beispiel wird eine Suchvariante veranschaulicht, die UDM-Netzwerkereignisse mit dem Asset-Kontext aus dem Entity Context Graph (ECG) in Beziehung setzt. Dabei wird ein match-Minuten-Zeitfenster verwendet, um den Netzwerkverkehr nach Hostname zu aggregieren, eine Risikobewertung basierend auf Datenvolumen und Schweregrad der Sicherheitslücke zu berechnen und ein bedingter Filter angewendet, um bestimmte Asset-IDs aus dem endgültigen Ergebnissatz auszuschließen.
$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname
$severity = $asset_context.graph.entity.asset.vulnerabilities.severity
match:
$hostname over 5m
outcome:
$total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)
$risk_score = if($total_network_bytes > 1024, 100, 50) +
max(
if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
Dashboard
Das folgende Beispiel zeigt eine Dashboard-Variante, in der die Netzwerktelemetrie in Echtzeit mit Daten zur Asset-Sicherheitslücke angereichert wird. Mit dieser Abfrage können Entwickler Dashboard-Widgets erstellen, die das Risikoniveau von Assets visualisieren. Dabei werden Hostnamen in einem gleitenden 5‑Minuten-Zeitfenster abgeglichen. Die Logik passt einen Risikowert dynamisch an den Netzwerkdurchsatz und die Sicherheitslücke mit dem höchsten Schweregrad an, die auf dem Asset gefunden wurde. So erhalten Sie eine priorisierte Ansicht potenziell kompromittierter Systeme.
$u.udm.principal.hostname = $hostname
$asset_context.graph.entity.hostname = $hostname
$severity = $asset_context.graph.entity.asset.vulnerabilities.severity
match:
$hostname over 5m
outcome:
$total_network_bytes = sum($u.network.sent_bytes) + sum($u.network.received_bytes)
$risk_score = if($total_network_bytes > 1024, 100, 50) +
max(
if($severity = "HIGH", 10)
+ if($severity = "MEDIUM", 5)
+ if($severity = "LOW", 1)
)
$asset_id_list =
array(
if($u.principal.asset_id = "",
"Empty asset id",
$u.principal.asset_id
)
)
$asset_id_distinct_list = array_distinct($u.principal.asset_id)
$asset_id_count = count($u.principal.asset_id)
$asset_id_distinct_count = count_distinct($u.principal.asset_id)
condition:
$u and $asset_context and $risk_score > 50 and not arrays.contains($asset_id_list, "id_1234")
Regel mit mehreren Ereignissen vom Typ outcome refaktorieren (vor der Refaktorierung)
Anwendungsfall: Systemleistung verbessern und Verarbeitungslatenz verringern, indem Regeln mit mehreren Ereignissen in Regeln mit einem einzelnen Ereignis umgewandelt werden. Das ist ideal für Regeln, die ursprünglich nur mit einem Abschnitt „Abgleich“ entworfen wurden, um den Abschnitt „Ergebnis“ zu aktivieren, aber keine Korrelation zwischen mehreren unterschiedlichen Ereignissen erfordern.
Schlüssel-Logik: Entfernt den Abschnitt match und alle Aggregatfunktionen (z. B. max(), sum() oder count()) aus dem Abschnitt outcome. Bei dieser Umstellung werden Ereignisse nicht mehr im Zeitverlauf gruppiert, sondern jedes Ereignis wird einzeln bewertet, sobald es eintrifft.
match-Abschnitt) und Mehrfachereignisregeln (Regeln mit einem match-Abschnitt).
Sie können den Abschnitt outcome sowohl für Regeln mit einem einzelnen Ereignis (Regeln ohne match-Abschnitt) als auch für Regeln mit mehreren Ereignissen verwenden. Wenn Sie eine Regel zuvor als Regel mit mehreren Ereignissen konzipiert haben, nur um den Ergebnisabschnitt verwenden zu können, können Sie diese Regeln optional umgestalten, indem Sie den match-Abschnitt löschen, um die Leistung zu verbessern. Da Ihre Regel keinen match-Abschnitt mehr enthält, in dem die Gruppierung angewendet wird, erhalten Sie möglicherweise mehr Erkennungen.
Beispiel: Outcome refactor (pre-refactor)
Regel
Das folgende Beispiel zeigt eine Regel für mehrere Ereignisse, in der nur eine Ereignisvariable verwendet wird. Da ein match-Abschnitt verwendet wird, muss die Rules Engine Ereignisse in einem 5-Minuten-Zeitraum gruppieren, bevor das Ergebnis berechnet wird. Das verbraucht mehr Ressourcen als eine Einzelergebnisbewertung.
rule OutcomeMultiEventPreRefactor {
meta:
author = "alice@example.com"
description = "Outcome refactor rule, before the refactor"
events:
$u.udm.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
$risk_score = max(if($hostname = "my-hostname", 100, 50))
condition:
$u
}
Suchen
Entsprechende Statistikabfrage
events:
$u.udm.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
$risk_score = max(if($hostname = "my-hostname", 100, 50))
condition:
$u
Dashboard
events:
$u.udm.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
$risk_score = max(if($hostname = "my-hostname", 100, 50))
condition:
$u
Eine Regel mit mehreren Ereignissen vom Typ outcome refaktorieren (nach der Refaktorierung)
Anwendungsfall: Optimierung einer Abfrage abschließen, um die Verarbeitungsgeschwindigkeit zu verbessern. Da die Gruppierungsanforderung entfernt wurde, wird durch die Abfrage jetzt sofort eine Erkennung ausgelöst, sobald ein einzelnes übereinstimmendes Ereignis eintrifft. Das ist für die Rules Engine deutlich effizienter.
Schlüssellogik: Löscht den Abschnitt match und entfernt die Funktion aggregate (z. B. max()) aus der Variablendeklaration outcome. Die Logik in der IF-Anweisung bleibt unverändert, wird aber jetzt auf ein einzelnes Ereignis statt auf eine Gruppe angewendet.
Sie können die Abfrage umgestalten, indem Sie den Abschnitt match löschen. Hinweis: Sie müssen das Aggregat auch im Abschnitt outcome entfernen, da die Abfrage jetzt ein Einzelereignis ist. Weitere Informationen zu Aggregationen finden Sie unter Ergebnisaggregationen.
Beispiel: Outcome refactor (: #outcome-post-refactor)
Regel
rule OutcomeSingleEventPostRefactor {
meta:
author = "alice@example.com"
description = "Outcome refactor rule, after the refactor"
events:
$u.udm.principal.hostname = $hostname
// We deleted the match section.
outcome:
// We removed the max() aggregate.
$risk_score = if($hostname = "my-hostname", 100, 50)
condition:
$u
}
Suchen
events:
$u.udm.principal.hostname = $hostname
outcome:
$risk_score = if($hostname = "my-hostname", 100, 50)
Dashboard
events:
$u.udm.principal.hostname = $hostname
outcome:
$risk_score = if($hostname = "my-hostname", 100, 50)
Zuweisung von Funktion zu Platzhalter
Anwendungsfall: Daten normalisieren, z. B. E-Mail-Domains standardisieren, um zu prüfen, ob die Gruppierung im Bereich „Abstimmung“ korrekt ist.
Schlüssellogik: Weist das Ergebnis von re.capture() oder strings.concat() einer Platzhaltervariablen zu.
Beispiel: Zuweisung von Funktion zu Platzhaltervariable
Sie können dem Ergebnis eines Funktionsaufrufs eine Platzhaltervariable zuweisen und diese in anderen Abschnitten der Regel verwenden, z. B. im Abschnitt match, outcome oder condition.
Regel
rule FunctionToPlaceholderRule {
meta:
author = "alice@example.com"
description = "Rule that uses function to placeholder assignments"
events:
$u.metadata.event_type = "EMAIL_TRANSACTION"
// Use function-placeholder assignment to extract the
// address from an email.
// address@website.com -> address
$email_to_address_only = re.capture($u.network.email.to , "(.*)@")
// Use function-placeholder assignment to normalize an email:
// address@-> address@company.com
$email_from_normalized = strings.concat(
re.capture($u.network.email.from , "(.*)@"),
"@company.com"
)
// Use function-placeholder assignment to get the day of the week of the event.
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week($u.metadata.event_timestamp.seconds)
match:
// Use placeholder (from function-placeholder assignment) in match section.
// Group by the normalized from email, and expose it in the detection.
$email_from_normalized over 5m
outcome:
// Use placeholder (from function-placeholder assignment) in outcome section.
// Assign more risk if the event happened on weekend.
$risk_score = max(
if($dayofweek = 1 or $dayofweek = 7, 10, 0)
)
condition:
// Use placeholder (from function-placeholder assignment) in condition section.
// Match if an email was sent to multiple addresses.
#email_to_address_only > 1
}
Suchen
metadata.event_type = "EMAIL_TRANSACTION"
// Use function-placeholder assignment to extract the
// address from an email.
// address@website.com -> address
$email_to_address_only = re.capture(network.email.from , "(.*)@")
// Use function-placeholder assignment to normalize an email:
// address@??? -> address@company.com
$email_from_normalized = strings.concat(
re.capture(network.email.to , "(.*)@"),
"@company.com"
)
// Use function-placeholder assignment to get the day of the week of the event.
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.event_timestamp.seconds)
match:
// Use placeholder (from function-placeholder assignment) in match section.
// Group by the normalized from email, and expose it in the detection.
$email_from_normalized over 5m
outcome:
// Use placeholder (from function-placeholder assignment) in outcome section.
// Assign more risk if the event happened on weekend.
$risk_score = max(
if($dayofweek = 1 or $dayofweek = 7, 10, 0)
)
condition:
// Use placeholder (from function-placeholder assignment) in condition section.
// Match if an email was sent to multiple addresses.
#email_to_address_only > 1
Dashboard
Das folgende Beispiel zeigt eine für die Zeitreihenvisualisierung optimierte Dashboard-Variante. Durch die Verwendung eines eintägigen rollierenden Fensters anstelle einer Granularität auf Minutenebene werden mit dieser Abfrage stabile, nicht überlappende Datenpunkte erzeugt, die sich ideal für die Darstellung von Risikobewertungen über einen längeren Zeitraum eignen. Die Logik normalisiert E-Mail-Entitäten und wendet höhere Risikogewichtungen auf Transaktionen am Wochenende an. So wird ein klarer täglicher Trend verdächtiger E-Mail-Aktivitäten für die langfristige Überwachung bereitgestellt.
metadata.event_type = "EMAIL_TRANSACTION"
// Use function-placeholder assignment to extract the
// address from an email.
// address@website.com -> address
$email_to_address_only = re.capture(network.email.from , "(.*)@")
// Use function-placeholder assignment to normalize an email:
// address@??? -> address@company.com
$email_from_normalized = strings.concat(
re.capture(network.email.to , "(.*)@"),
"@company.com"
)
// Use function-placeholder assignment to get the day of the week of the event.
// 1 = Sunday, 7 = Saturday.
$dayofweek = timestamp.get_day_of_week(metadata.event_timestamp.seconds)
match:
// Use placeholder (from function-placeholder assignment) in match section.
// Group by the normalized from email, and expose it in the detection.
$email_from_normalized over 5m
outcome:
// Use placeholder (from function-placeholder assignment) in outcome section.
// Assign more risk if the event happened on weekend.
$risk_score = max(
if($dayofweek = 1 or $dayofweek = 7, 10, 0)
)
condition:
// Use placeholder (from function-placeholder assignment) in condition section.
// Match if an email was sent to multiple addresses.
#email_to_address_only > 1
Optimierung und Filterung
Eine effektive Regeloptimierung basiert auf einer präzisen Datenfilterung, damit die Erkennungs-Engine nur aussagekräftige Informationen verarbeitet. Wenn Sie „verrauschte“ oder unvollständige Daten ausschließen, können Sie die Leistung von Regeln erheblich verbessern und dafür sorgen, dass generierte Benachrichtigungen umsetzbar sind.
| Thema | Beispiele |
|---|---|
| Ausschluss von Nullwerten | Expliziter und impliziter Ausschluss von Nullwerten |
Ausschluss von Nullwerten
Anwendungsfall: Sie können die Genauigkeit von Regeln verbessern und Fehlalarme reduzieren, indem Sie explizit leere Strings, Nullwerte oder generische Platzhalterkonten (z. B. „Gast“) herausfiltern, die keine verwertbaren Sicherheitsdaten liefern.
Schlüssellogik: Hier wird die implizite Filterung von Nullwerten für Variablen genutzt, die im Abschnitt match verwendet werden. Gleichzeitig werden explizite Ungleichheitsoperatoren (!= "") für andere Ereignisfelder verwendet, damit nur Daten, die Werte enthalten, eine Erkennung auslösen.
In der Rules Engine werden die Nullwerte für alle Platzhalter, die im Abschnitt match verwendet werden, implizit herausgefiltert. Verwenden Sie die Option allow_zero_values, um die Funktion zu deaktivieren. Bei anderen referenzierten Ereignisfeldern werden Nullwerte jedoch nicht ausgeschlossen, sofern Sie solche Bedingungen nicht explizit angeben. Weitere Informationen finden Sie unter Nullwerte im Abschnitt „Abstimmung“.
Beispiel: Expliziter und impliziter Ausschluss von Nullwerten
Regel
rule ExcludeZeroValues {
meta:
author = "alice@example.com"
events:
$e1.metadata.event_type = "NETWORK_DNS"
$e1.principal.hostname = $hostname
// $e1.principal.user.userid may be empty string.
$e1.principal.user.userid != "Guest"
$e2.metadata.event_type = "NETWORK_HTTP"
$e2.principal.hostname = $hostname
// $e2.target.asset_id cannot be empty string as explicitly specified.
$e2.target.asset_id != ""
match:
// $hostname cannot be empty string. The rule behaves as if the
// predicate, `$hostname != ""` was added to the events section, because
// `$hostname` is used in the match section.
$hostname over 1h
condition:
$e1 and $e2
}
Suchen
Sie müssen explizit angeben, dass hostname kein leerer String sein darf, da es keinen impliziten Nullwertfilter für Platzhalter im Abschnitt match gibt.
$e1.metadata.event_type = "NETWORK_DNS"
$e1.principal.hostname = $hostname
// $e1.principal.user.userid may be empty string.
$e1.principal.user.userid != "Guest"
$e2.metadata.event_type = "NETWORK_HTTP"
$e2.principal.hostname = $hostname
// $e2.target.asset_id and hostname cannot be empty string as explicitly specified.
$e2.target.asset_id != ""
$hostname != ""
match:
$hostname over 1h
Dashboard
Sie müssen explizit angeben, dass hostname kein leerer String sein darf, da es keinen impliziten Nullwertfilter für Platzhalter im Abschnitt match gibt.
$e1.metadata.event_type = "NETWORK_DNS"
$e1.principal.hostname = $hostname
// $e1.principal.user.userid may be empty string.
$e1.principal.user.userid != "Guest"
$e2.metadata.event_type = "NETWORK_HTTP"
$e2.principal.hostname = $hostname
// $e2.target.asset_id and hostname cannot be empty string as explicitly specified.
$e2.target.asset_id != ""
$hostname != ""
match:
$hostname over 1h
Benötigen Sie weitere Hilfe? Antworten von Community-Mitgliedern und Google SecOps-Experten erhalten