Panoramica del linguaggio YARA-L 2.0

YARA-L 2.0 è un linguaggio informatico utilizzato per creare regole per la ricerca nei dati del log aziendale man mano che vengono importati nell'istanza di Google Security Operations. La sintassi YARA-L deriva dal linguaggio YARA sviluppato da VirusTotal. Il linguaggio funziona in combinazione con Google Security Operations Detection Engine e ti consente di ricercare minacce e altri eventi in grandi volumi di dati.

Per ulteriori informazioni, consulta le seguenti risorse:

Regole di esempio per YARA-L 2.0

I seguenti esempi mostrano le regole scritte in YARA-L 2.0. Ciascuno di essi dimostra come correlare gli eventi all'interno del linguaggio delle regole.

Regole e ottimizzazione

La seguente regola verifica la presenza di pattern specifici nei dati sugli eventi e crea un rilevamento se trova i pattern. Questa regola include una variabile $e1 per il tipo di evento di monitoraggio e un campo UDM metadata.event_type. La regola verifica la presenza di occorrenze specifiche di corrispondenze di espressioni regolari con e1. Quando si verifica l'evento $e1, viene creato un rilevamento. Una condizione not è inclusa nella regola per escludere determinati percorsi non dannosi. Puoi aggiungere condizioni not per evitare falsi positivi.

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
}

Accessi da città diverse

La seguente regola cerca gli utenti che hanno eseguito l'accesso alla tua azienda da due o più città in meno di 5 minuti:

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
}

Variabile di corrispondenza: $user

Variabile evento:$udm

Variabile segnaposto: $city e $user

Di seguito viene descritto come funziona questa regola:

  • Raggruppa gli eventi con il nome utente ($user) e lo restituisce ($user) quando viene trovata una corrispondenza.
  • L'intervallo di tempo è di 5 minuti, il che significa che solo gli eventi a distanza inferiore a 5 minuti sono correlati.
  • Ricerca di un gruppo di eventi ($udm) il cui tipo di evento è USER_LOGIN.
  • Per tale gruppo di eventi, la regola chiama l'ID utente $user e la città di accesso come $city.
  • Restituisce una corrispondenza se il numero distinto di valori city (indicato da #city) è maggiore di 1 nel gruppo di eventi ($udm) nell'intervallo di tempo di 5 minuti.

Creazione ed eliminazione rapide degli utenti

La seguente regola cerca gli utenti che sono stati creati e poi eliminati entro 4 ore:

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
}

Variabili evento:$create e $delete

Variabile di corrispondenza: $user

Variabile segnaposto: N/D

Di seguito viene descritto come funziona questa regola:

  • Raggruppa gli eventi con il nome utente ($user) e lo restituisce ($user) quando viene trovata una corrispondenza.
  • La finestra temporale è di 4 ore, il che significa che solo gli eventi separati da meno di 4 ore sono correlati.
  • Cerca due gruppi di eventi ($create e $delete, dove $create è equivalente a #create >= 1).
  • $create corrisponde a USER_CREATION eventi e chiama l'ID utente come $user.
  • $user viene utilizzato per unire i due gruppi di eventi.
  • $delete corrisponde a USER_DELETION eventi e chiama l'ID utente come $user. Questa regola cerca una corrispondenza in cui l'identificatore utente nei due gruppi di eventi è lo stesso.
  • Questa regola cerca i casi in cui l'evento di $delete si verifica dopo l'evento del giorno $create e restituisce una corrispondenza quando viene rilevato.

Regola evento singolo

Le regole evento singolo sono regole correlate a un singolo evento. Una singola regola evento può essere:

  • Qualsiasi regola senza una sezione di corrispondenza.
  • Regola con una sezione match e una sezione condition che verifica solo l'esistenza di 1 evento (ad esempio, "$e", "#e > 0", "#e >= 1", "1 <= #e", "0 < #e").

Ad esempio, la seguente regola cerca un evento di accesso utente e restituisce il primo rilevato nei dati aziendali archiviati nel tuo account Google Security Operations:

rule SingleEventRule {
  meta:
    author = "noone@altostrat.com"

  events:
    $e.metadata.event_type = "USER_LOGIN"

  condition:
    $e
}

Ecco un altro esempio di regola evento singola con una sezione di corrispondenza. Questa regola cerca un utente che ha eseguito l'accesso almeno una volta in meno di 5 minuti. Verifica la semplice esistenza di un evento di accesso utente.

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
}
rule MultiEventRule{
  meta:
    author = "alice@example.com"
    description = "Rule with outcome condition and simple existence condition on one event variable"

  events:
    $e.metadata.event_type = "USER_LOGIN"
    $e.principal.user.userid = $user

  match:
    $user over 10m

  outcome:
    $num_events_in_match_window = count($e.metadata.id)

  condition:
    #e > 0 and $num_events_in_match_window >= 10 // Could be rewritten as #e >= 10
}

Regola per eventi multipli

Utilizza più regole di evento per raggruppare molti eventi in un intervallo di tempo specificato e prova a trovare correlazioni tra gli eventi. Una tipica regola per più eventi avrà quanto segue:

  • Una sezione match che specifica l'intervallo di tempo durante il quale gli eventi devono essere raggruppati.
  • Una sezione condition che specifica la condizione che deve attivare il rilevamento e il controllo dell'esistenza di più eventi.

Ad esempio, la seguente regola cerca un utente che ha eseguito l'accesso almeno 10 volte in meno di 10 minuti:

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
}

Singolo evento nell'intervallo di indirizzi IP

L'esempio seguente mostra una singola regola evento che cerca una corrispondenza tra due utenti specifici e un intervallo specifico di indirizzi IP:

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
}

esempio di regole con qualsiasi tipo di regola

La seguente regola cerca gli eventi di accesso in cui tutti gli indirizzi IP di origine non corrispondono a un indirizzo IP noto come sicuro entro un intervallo di tempo di 5 minuti.

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
}

Espressioni regolari in una regola

Il seguente esempio di espressione regolare YARA-L 2.0 consente di cercare eventi con email ricevute dal dominio altostrat.com. Poiché nocase è stato aggiunto al confronto della variabile $host regex e alla funzione regex, entrambi i confronti non fanno distinzione tra maiuscole e minuscole.

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
}

Esempio di regola per finestre scorrevoli

Il seguente esempio di finestra scorrevole YARA-L 2.0 cerca l'assenza di eventi firewall_2 dopo eventi firewall_1. La parola chiave after viene utilizzata con la variabile evento pivot $e1 per specificare che devono essere controllate solo le finestre di 10 minuti dopo ogni evento firewall_1 quando si correlano gli eventi.

rule SlidingWindowRuleExample {
  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:
    $host over 10m after $e1

  condition:
    $e1 and !$e2
}

Esempio di esclusione valore zero

Il Motore regole filtra implicitamente i valori zero per tutti i segnaposto utilizzati nella sezione match. Per ulteriori informazioni, consulta la sezione sulla gestione di valori pari a zero nella sezione match. Questa operazione può essere disabilitata utilizzando l'opzione allow_zero_values come descritto in allow_zero_values.

Tuttavia, per gli altri campi degli eventi a cui viene fatto riferimento, non vengono esclusi valori zero, a meno che non specifichi esplicitamente queste condizioni.

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
}

Esempio di regola con sezione outcome

Puoi aggiungere la sezione facoltativa outcome nella regola YARA-L 2.0 per estrarre informazioni aggiuntive da ciascun rilevamento. Nella sezione delle condizioni puoi anche specificare le condizionali sulle variabili risultato. Puoi utilizzare la sezione outcome di una regola di rilevamento per impostare le variabili per il consumo downstream. Ad esempio, puoi impostare un punteggio di gravità in base ai dati degli eventi analizzati.

Per ulteriori informazioni, consulta le seguenti risorse:

Regola per più eventi con sezione Risultato:

La seguente regola controlla due eventi per ottenere il valore $hostname. Se il valore di $hostname corrisponde in un periodo di 5 minuti, viene applicato un punteggio di gravità. Quando includi un periodo di tempo nella sezione match, la regola verifica entro il periodo di tempo specificato.

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")
}

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")
}

Regola per evento singolo con sezione Risultato:

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.userid in %admin_users, "SEVERE", "MODERATE")
        $severity_tag = if($file_size > 1024, $admin_severity, "LOW")

    condition:
        $u
}

Refactoring di una regola per il risultato di più eventi in una regola per il risultato di un evento singolo.

Puoi utilizzare la sezione outcome sia per le regole per evento singolo (regole senza sezione match) sia per le regole multievento (regole con una sezione match). Se in precedenza hai progettato una regola per più eventi solo per poter utilizzare la sezione dei risultati, puoi facoltativamente eseguire il refactoring di queste regole eliminando la sezione match per migliorare le prestazioni. Tieni presente che, poiché la regola non ha più una sezione match che applica il raggruppamento, potresti ricevere più rilevamenti. Questo refactoring è possibile solo per le regole che utilizzano una variabile evento, come mostrato nell'esempio seguente.

Regola di risultato per più eventi che utilizza una sola variabile evento (un buon candidato per un refactoring):

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
}

Puoi eseguire il refactoring della regola eliminando la sezione match. Tieni presente che devi rimuovere anche l'aggregato nella sezione outcome poiché la regola ora sarà un evento singolo. Per saperne di più sulle aggregazioni, consulta Aggregazioni di risultati.

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
}

Esempio di regola da funzione a segnaposto

Puoi assegnare una variabile segnaposto al risultato di una chiamata di funzione e utilizzarla in altre sezioni della regola, ad esempio la sezione match, outcome o condition. Vedi l'esempio che segue:

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.from , "(.*)@")

        // Use function-placeholder assignment to normalize an email:
        // uid@??? -> uid@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, 10, 0) +
            if($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
}

Regola di esempio condizionali dei risultati

Nella sezione condition, puoi utilizzare le variabili di risultato definite nella sezione outcome. L'esempio seguente mostra come filtrare in base ai punteggi di rischio per ridurre il rumore nei rilevamenti utilizzando le condizionali dei risultati.

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
}