Visão geral da linguagem YARA-L 2.0
A YARA-L 2.0 é uma linguagem de computador usada para criar regras de pesquisa nos seus dados de registros corporativos conforme eles são ingeridos na sua instância do Google Security Operations. A sintaxe YARA-L é derivada da linguagem YARA desenvolvida pelo VirusTotal. A linguagem funciona em conjunto com o mecanismo de detecção do Google SecOps e permite detectar ameaças e outros eventos em grandes volumes de dados.
Para ver mais informações, consulte os seguintes tópicos:
Exemplos de regras YARA-L 2.0
Os exemplos a seguir mostram regras escritas em YARA-L 2.0. Cada um demonstra como correlacionar eventos na linguagem de regras.
Regras e ajuste
A regra a seguir verifica padrões específicos nos dados de eventos e cria uma detecção se encontrar os padrões. Essa regra inclui uma variável $e1
para rastrear o tipo de evento e o campo metadata.event_type
da UDM. A regra verifica ocorrências específicas de correspondências de expressões regulares com e1
. Quando o evento $e1
ocorre, uma detecção é criada.
Uma condição not
é incluída na regra para excluir determinados caminhos não maliciosos.
É possível adicionar condições not
para evitar falsos positivos.
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
}
Logins de cidades diferentes
A regra a seguir procura usuários que fizeram login na sua empresa em duas ou mais cidades em menos de cinco minutos:
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
}
Variável de correspondência: $user
Variável de evento:$udm
Variável de marcador: $city
e $user
A seguir, descrevemos como essa regra funciona:
- Agrupa eventos com nome de usuário (
$user
) e o retorna ($user
) quando uma correspondência é encontrada. - O período é de cinco minutos, ou seja, apenas eventos com menos de cinco minutos de diferença são correlacionados.
- Pesquisando um grupo de eventos (
$udm
) cujo tipo de evento é USER_LOGIN. - Para esse grupo de eventos, a regra chama o ID do usuário como
$user
e a cidade de login como$city.
. - Retorna uma correspondência se o número distinto de valores
city
(indicado por#city
) for maior que 1 no grupo de eventos ($udm
) dentro do período de cinco minutos.
Criação e exclusão rápidas de usuários
A regra a seguir pesquisa usuários que foram criados e excluídos em até 4 horas:
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
}
Variáveis de evento:$create
e $delete
Variável de correspondência: $user
Variável de substituição: N/A
A seguir, descrevemos como essa regra funciona:
- Agrupa eventos com nome de usuário (
$user
) e o retorna ($user
) quando uma correspondência é encontrada. - O período é de quatro horas, ou seja, apenas eventos separados por menos de quatro horas são correlacionados.
- Pesquisa dois grupos de eventos (
$create
e$delete
, em que$create
é equivalente a#create >= 1
). $create
corresponde a eventosUSER_CREATION
e chama o ID do usuário como$user
.$user
é usado para unir os dois grupos de eventos.$delete
corresponde a eventosUSER_DELETION
e chama o ID do usuário como$user
. Essa regra procura uma correspondência em que o identificador de usuário nos dois grupos de eventos seja o mesmo.- Essa regra procura casos em que o evento de
$delete
acontece depois do evento de$create
, retornando uma correspondência quando descoberta.
Regra de evento único
As regras de evento único são aquelas que fazem correlação em um único evento. Uma única regra de evento pode ser:
- Qualquer regra sem uma seção de correspondência.
- Regra com uma seção
match
e uma seçãocondition
que verifica apenas a existência de um evento (por exemplo, "$e", "#e > 0", "#e >= 1", "1 <= #e", "0 < #e").
Por exemplo, a regra a seguir procura um evento de login do usuário e retorna o primeiro que encontra nos dados corporativos armazenados na sua conta do Google SecOps:
rule SingleEventRule {
meta:
author = "noone@altostrat.com"
events:
$e.metadata.event_type = "USER_LOGIN"
condition:
$e
}
Este é outro exemplo de uma regra de evento único com uma seção de correspondência. Essa regra procura um usuário que fez login pelo menos uma vez em menos de 5 minutos. Ele verifica a simples existência de um evento de login do usuário.
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
}
Várias regras de evento
Use várias regras de evento para agrupar muitos eventos em um período especificado e tente encontrar correlações entre eles. Uma regra de vários eventos típica tem o seguinte:
- Uma seção
match
que especifica o período em que os eventos precisam ser agrupados. - Uma seção
condition
que especifica qual condição deve acionar a detecção e verifica a existência de vários eventos.
Por exemplo, a regra a seguir pesquisa um usuário que fez login pelo menos 10 vezes em menos de 10 minutos:
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
}
Evento único dentro do intervalo de endereços IP
O exemplo a seguir mostra uma única regra de evento que procura correspondências entre dois nomes de host específicos e um intervalo específico de endereços 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
}
qualquer exemplo de regra
A regra a seguir pesquisa eventos de login em que todos os endereços IP de origem não correspondem a um endereço IP conhecido como seguro em um período de 5 minutos.
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
}
Expressões regulares em uma regra
O exemplo de expressão regular da YARA-L 2.0 a seguir pesquisa eventos com e-mails recebidos do domínio altostrat.com. Como nocase
foi adicionado à comparação da variável $host
regex
e à função regex
, as duas comparações não diferenciam maiúsculas de minúsculas.
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
}
Exemplos de regras compostas
As detecções compostas melhoram a detecção de ameaças usando regras compostas. Essas regras compostas usam detecções de outras regras como entrada. Isso permite a detecção de ameaças complexas que regras individuais talvez não detectem. Para mais informações, consulte Visão geral das detecções compostas.
Detecções de tripwire
As detecções compostas de Tripwire são a forma mais simples de uma detecção composta que opera em campos dentro das descobertas de detecção, como variáveis de resultado ou metadados de regra. Eles ajudam a filtrar detecções de condições que podem indicar maior risco, como um usuário administrador ou um ambiente de produção.
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.outcomes["principal_users"]
$principal_user = /admin|root/ nocase
match:
$principal_user over 1h
outcome:
$risk_score = 75
$upstream_rules = array_distinct($rule_name)
condition:
$d
}
Detecções de limite e agregação
Com as regras de detecção agregada, você agrupa descobertas com base em atributos compartilhados, como um nome de host ou de usuário, e analisa os dados agregados. Confira alguns casos de uso comuns:
- Identificar usuários que geram um grande volume de alertas de segurança ou risco agregado.
- Detectar hosts com padrões de atividade incomuns agregando detecções relacionadas.
Exemplo de agregação de risco:
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)
$principal_users = array_distinct($principal_users)
$upstream_rules = array_distinct($rule_name)
condition:
$d and $cumulative_risk > 500
}
Exemplo de agregação de táticas:
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.rule_labels["tactic"]
$rule_name = $d.detection.detection.rule_name
match:
$principal_user over 48h
outcome:
$mitre_tactics_count = count_distinct($tactic)
$mitre_tactics = array_distinct($d.detection.rule_labels["tactic"])
$risk_score = min(100, (50+15*$mitre_tactics_count))
$upstream_rules = array_distinct($rule_name)
condition:
$d and $mitre_tactics_count > 1
}
Detecções compostas sequenciais
As detecções compostas sequenciais identificam padrões de eventos relacionados em que a sequência de detecções é importante, como uma tentativa de login por força bruta seguida de um login bem-sucedido. Esses padrões podem envolver várias detecções básicas ou uma combinação de detecções básicas e eventos.
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 = $d.detection.detection.outcomes["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
}
Detecções com base no contexto
As detecções compostas com base no contexto enriquecem as detecções com mais contexto, como endereços IP encontrados em feeds de ameaças.
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:
$detection_ip = $d.detection.detection.outcomes["principal_ips"]
$gcti.graph.metadata.entity_type = "IP_ADDRESS"
$gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence"
$gcti_feed.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 = $gcti.graph.entity.ip
$rule_name = $d.detection.detection.rule_name
$risk = $d.detection.detection.outcomes["risk_score"]
match:
$detection_ip, $rule_name over 1h
outcome:
$risk_score = 80
$upstream_rule = array_distinct($rule_name)
condition:
$d and $gcti
}
Detecções de coocorrência
As detecções compostas de coocorrência são uma forma de agregação que pode detectar uma combinação de eventos relacionados, como uma combinação de escalonamento de privilégios e detecções de exfiltração de dados acionadas por um usuário.
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"
$pe_user = $privilege_escalation.detection.detection.outcomes["principal_users"]
$ex_user = $exfiltration.detection.detection.outcomes["principal_users"]
$pe_user = $ex_user
match:
$pe_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
}
Exemplo de regra de janela deslizante
O exemplo a seguir de janela deslizante do YARA-L 2.0 procura a ausência de eventos
firewall_2
após eventos firewall_1
. A palavra-chave after
é usada com a variável de evento de pivô $e1
para especificar que apenas janelas de 10 minutos após cada evento firewall_1
devem ser verificadas ao correlacionar eventos.
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
}
Exemplo de exclusão de valor zero
O mecanismo de regras filtra implicitamente os valores zero de todos os marcadores de posição usados na seção match
.
Para mais informações, consulte processamento de valores zero na seção match
.
Isso pode ser desativado usando a opção allow_zero_values
, conforme descrito em allow_zero_values.
No entanto, para outros campos de eventos referenciados, os valores zero não são excluídos, a menos que você especifique essas condições explicitamente.
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
}
Exemplo de regra com seção outcome
É possível adicionar a seção opcional outcome
em uma regra YARA-L 2.0 para extrair mais informações de cada detecção. Na seção de condição, também é possível especificar condicionais em variáveis de resultado. Use a seção outcome
de uma regra de detecção
para definir variáveis para consumo downstream. Por exemplo, é possível definir uma pontuação de gravidade com base nos dados dos eventos analisados.
Para ver mais informações, consulte os seguintes tópicos:
Regra de vários eventos com seção de resultado:
A regra a seguir analisa dois eventos para extrair o valor de $hostname
. Se o valor de $hostname
corresponder por um período de 5 minutos, uma pontuação de gravidade será aplicada. Ao incluir um período na seção match
, a regra verifica dentro do período especificado.
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")
}
Regra de evento único com seção de resultado:
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
}
Refatorar uma regra de resultado de vários eventos em uma regra de resultado de evento único.
Você pode usar a seção outcome
para regras de evento único (sem uma seção match
) e de vários eventos (com uma seção match
).
Se você criou uma regra para ser multievento apenas para usar a seção de resultado, é possível refatorar essas regras excluindo a seção match
para melhorar o desempenho. Como sua regra não tem mais uma seção match
que aplica o agrupamento, você pode receber mais detecções. Essa refatoração só é possível para regras que usam uma variável de evento, como mostrado no exemplo a seguir.
Regra de resultado de vários eventos que usa apenas uma variável de evento (uma boa candidata a refatoração):
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
}
Para refatorar a regra, exclua a seção match
. Também é necessário remover o agregado da seção outcome
, já que a regra agora será de evento único. Para mais informações sobre agregações, consulte agregações de resultados.
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
}
Exemplo de função para regra de marcador
É possível atribuir uma variável de marcador de posição ao resultado de uma chamada de função e usar essa variável em outras seções da regra, como match
, outcome
ou condition
. Veja o exemplo a seguir:
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
}
Exemplo de regra condicional de resultado
Na seção condition
, você pode usar variáveis de resultado definidas na seção outcome
. O exemplo a seguir demonstra como filtrar pontuações de risco para reduzir o ruído nas detecções usando condicionais de resultado.
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
}
Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais do Google SecOps.