Campos repetidos

Suportado em:

No modelo de dados unificado (UDM), alguns campos são etiquetados como repetidos, o que indica que são listas de valores ou outros tipos de mensagens. Este documento fornece informações sobre como usar expressões, marcadores de posição, indexação de matrizes e mensagens repetidas para campos UDM repetidos.

Expressões booleanas e campos repetidos

As expressões booleanas modificadas e não modificadas podem atuar em campos repetidos.

Considere o seguinte evento:

event_original {
  principal {
    // ip is a repeated field
    ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]

    hostname: "host"
  }
}

Expressões modificadas

Use os modificadores any e all em expressões em campos repetidos.

  • any - Se qualquer elemento do campo repetido cumprir a condição, o evento no seu conjunto cumpre a condição. Por exemplo:

    • event_original satisfaz any $e.principal.ip = "192.0.2.1"
    • event_original falha any $e.repeated_field.field_a = "9.9.9.9"
  • all – Se todos os elementos do campo repetido satisfizerem a condição, o evento como um todo satisfaz a condição. Por exemplo:

    • event_original satisfaz net.ip_in_range_cidr(all $e.principal.ip, "192.0.2.0/8")
    • event_original falha all $e.principal.ip = "192.0.2.2"

Quando escreve uma condição com any ou all, tenha em atenção que negar a condição com not pode não ter o mesmo significado que usar o operador negado.

Por exemplo:

  • not all $e.principal.ip = "192.168.12.16" verifica se nem todos os endereços IP correspondem a 192.168.12.16, o que significa que a consulta está a verificar se, pelo menos, um endereço IP não corresponde a 192.168.12.16
  • all $e.principal.ip != "192.168.12.16" verifica se todos os endereços IP não correspondem a 192.168.12.16, o que significa que a consulta está a verificar se nenhum endereço IP corresponde a 192.168.12.16

Restrições:

  • Os operadores any e all só são compatíveis com campos repetidos (não campos escalares).
  • Não é possível usar any e all para juntar dois campos repetidos. Por exemplo, any $e1.principal.ip = $e2.principal.ip não é válido.
  • Os operadores any e all não são suportados com a expressão da lista de referência.

Expressões não modificadas

Com expressões não modificadas, cada elemento no campo repetido é tratado individualmente. Se o campo repetido de um evento contiver n elementos, a consulta é aplicada a n cópias do evento, em que cada cópia tem um dos elementos do campo repetido. Estas cópias são temporárias e não são armazenadas.

A regra é aplicada nas seguintes cópias:

texto do evento principal.ip principal.hostname
event_copy_1 "192.0.2.1" "host"
event_copy_2 "192.0.2.2" "host"
event_copy_3 "192.0.2.3" "host"

Se qualquer cópia do evento satisfizer todas as condições não modificadas no campo repetido, o evento como um todo satisfaz todas as condições. Por conseguinte, se tiver várias condições num campo repetido, uma única cópia do evento tem de satisfazer todas elas. Os exemplos de consultas seguintes usam o conjunto de dados de exemplo anterior para demonstrar este comportamento.

Exemplo: expressões não modificadas

A regra seguinte devolve uma correspondência quando executada no conjunto de dados de exemplo event_original, porque event_copy_1 satisfaz todos os predicados de eventos:

rule repeated_field_1 {
  meta:
  events:
    net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/8") // Checks if IP address matches 192.x.x.x
    $e.principal.ip = "192.0.2.1"
  condition:
    $e
}

A regra seguinte não devolve uma correspondência quando executada no conjunto de dados de exemplo, porque não existe nenhuma cópia do evento em $e.principal.ip que satisfaça _todos_ os predicados de eventos.event_original

rule repeated_field_2 {
  meta:
  events:
    $e.principal.ip = "192.0.2.1"
    $e.principal.ip = "192.0.2.2"
  condition:
    $e
}

As expressões modificadas em campos repetidos são compatíveis com expressões não modificadas em campos repetidos porque a lista de elementos é a mesma para cada cópia do evento. Considere a seguinte regra:

rule repeated_field_3 {
  meta:
  events:
    any $e.principal.ip = "192.0.2.1"
    $e.principal.ip = "192.0.2.3"
  condition:
    $e
}

A regra é aplicada nas seguintes cópias:

texto do evento principal.ip any $e.principal.ip
event_copy_1 "192.0.2.1" ["192.0.2.1", "192.0.2.2", "192.0.2.3"]
event_copy_2 "192.0.2.2" ["192.0.2.1", "192.0.2.2", "192.0.2.3"]
event_copy_3 "192.0.2.3" ["192.0.2.1", "192.0.2.2", "192.0.2.3"]

Neste caso, todas as cópias satisfazem any $e.principal.ip = "192.0.2.1", mas apenas event_copy_3 satisfaz $e.principal.ip = "192.0.2.3". Como resultado, o evento como um todo corresponderia.

Outra forma de pensar nestes tipos de expressões é:

  • As expressões em campos repetidos que usam any ou all operam na lista em event_original.
  • As expressões em campos repetidos que não usam any ou all operam em eventos event_copy_n individuais.

Marcadores de posição e campos repetidos

Os campos repetidos funcionam com atribuições de marcadores de posição. Semelhante às expressões não modificadas em campos repetidos, é feita uma cópia do evento para cada elemento. Usando o mesmo exemplo de event_copy, o marcador de posição assume o valor do campo repetido de event_copy_n para cada uma das cópias do evento em que n é o número da cópia do evento. Se o marcador de posição for usado na secção de correspondência, isto pode resultar em várias correspondências.

Exemplo: marcador de posição de campo repetido

O exemplo seguinte gera uma correspondência. O marcador de posição `$ip` é igual a `192.0.2.1` para `event_copy_1`, o que satisfaz os predicados na regra. Os exemplos de eventos da correspondência contêm um único elemento, `event_original`.

// Generates 1 match.
rule repeated_field_placeholder1 {
  meta:
  events:
    $ip = $e.principal.ip
    $ip = "192.0.2.1"
    $host = $e.principal.hostname

  match:
    $host over 5m

  condition:
    $e
}

O exemplo seguinte gera três correspondências. O marcador de posição $ip é igual a valores diferentes para cada uma das diferentes cópias event_copy_n. O agrupamento é feito em $ip, uma vez que está na secção de correspondências. Por conseguinte, recebe três correspondências, em que cada uma tem um valor diferente para a variável de correspondência $ip. Cada correspondência tem o mesmo exemplo de evento: um único elemento, event_original.

// Generates 3 matches.
rule repeated_field_placeholder2 {
  meta:
  events:
    $ip = $e.principal.ip
    net.ip_in_range_cidr($ip, "192.0.2.0/8") // Checks if IP matches 192.x.x.x

  match:
    $ip over 5m

  condition:
    $e
}

Resultados com marcadores de posição atribuídos a campos repetidos

Os marcadores de posição são atribuídos a cada elemento de cada campo repetido e não à lista completa. Quando são usados na secção outcome, o resultado é calculado usando apenas os elementos que satisfizeram as secções anteriores.

Considere a seguinte regra:

rule outcome_repeated_field_placeholder {
  meta:
  events:
    $ip = $e.principal.ip
    $ip = "192.0.2.1" or $ip = "192.0.2.2"
    $host = $e.principal.hostname

  match:
    $host over 5m

  outcome:
    $o = array_distinct($ip)

  condition:
    $e
}

Existem quatro fases de execução para esta regra. A primeira fase é a cópia de eventos:

texto do evento $ip $host $e
event_copy_1 "192.0.2.1" "host" event_id
event_copy_2 "192.0.2.2" "host" event_id
event_copy_3 "192.0.2.3" "host" event_id

A secção de eventos filtra e exclui as linhas que não correspondem aos filtros:

texto do evento $ip $host $e
event_copy_1 "192.0.2.1" "host" event_id
event_copy_2 "192.0.2.2" "host" event_id

event_copy_3 é filtrado porque "192.0.2.3" não satisfaz $ip = "192.0.2.1" or $ip = "192.0.2.2".

A secção match é agrupada por variáveis de correspondência e a secção outcome agrega cada grupo:

$host $o $e
"host" ["192.0.2.1", "192.0.2.2"] event_id

$o = array_distinct($ip) é calculado com base em $ip da fase anterior e não da fase de cópia de eventos.

Por último, a secção condition filtra cada grupo. Uma vez que esta regra apenas verifica a existência de $e, a linha anterior produz uma única deteção.

$o não contém todos os elementos de $e.principal.ip porque nem todos os elementos satisfizeram todas as condições na secção de eventos. No entanto, todos os elementos de e.principal.ip são apresentados no exemplo de evento porque o exemplo de evento usa event_original.

Indexação de matrizes

Pode realizar a indexação de matrizes em campos repetidos. Para aceder ao elemento do campo repetido n-ésimo, use a sintaxe de lista padrão (os elementos têm índice 0). Um elemento fora dos limites devolve o valor predefinido.

  • $e.principal.ip[0] = "192.168.12.16"
  • $e.principal.ip[999] = "" Se existirem menos de 1000 elementos, esta função é avaliada como true.

Restrições:

  • Um índice tem de ser um literal de número inteiro não negativo. Por exemplo, $e.principal.ip[-1] não é válido.
  • Os valores que têm um tipo int (por exemplo, um marcador de posição definido como int) não são contabilizados.
  • A indexação de matrizes não pode ser combinada com any nem all. Por exemplo, any $e.intermediary.ip[0] não é válido.
  • Não é possível combinar a indexação de matrizes com a sintaxe de mapas. Por exemplo, $e.additional.fields[0]["key"] não é válido.
  • Se o caminho do campo contiver vários campos repetidos, todos os campos repetidos têm de usar a indexação de matrizes. Por exemplo, $e.intermediary.ip[0] não é válido porque intermediary e ip são campos repetidos, mas só existe um índice para ip.

Mensagens repetidas

Quando um campo message é repetido, o efeito não intencional é reduzir a probabilidade de uma correspondência. Isto é ilustrado nos exemplos seguintes.

Considere o seguinte evento:

event_repeated_message {
  // about is a repeated message field.
  about {
    // ip is a repeated string field.
    ip: [ "192.0.2.1", "192.0.2.2", "192.0.2.3" ]

    hostname: "alice"
  }
  about {
    hostname: "bob"
  }
}

Conforme indicado para expressões não modificadas em campos repetidos, é criada uma cópia temporária do evento para cada elemento do campo repetido. Considere a seguinte regra:

rule repeated_message_1 {
  meta:
  events:
    $e.about.ip = "192.0.2.1"
    $e.about.hostname = "bob"
  condition:
    $e
}

A regra é aplicada nas seguintes cópias:

texto do evento about.ip about.hostname
event_copy_1 "192.0.2.1" "alice"
event_copy_2 "192.0.2.2" "alice"
event_copy_3 "192.0.2.3" "alice"
event_copy_4 "" "bob"

O evento não corresponde à regra porque não existe nenhuma cópia do evento que satisfaça todas as expressões.

Mensagens repetidas e indexação de matrizes

Outro comportamento inesperado pode ocorrer quando usa a indexação de matrizes com expressões não modificadas em campos de mensagens repetidos. Considere a seguinte regra de exemplo que usa a indexação de matrizes:

rule repeated_message_2 {
  meta:
  events:
    $e.about.ip = "192.0.2.1"
    $e.about[1].hostname = "bob"
  condition:
    $e
}

A regra é aplicada às seguintes cópias:

texto do evento about.ip about[1].hostname
event_copy_1 "192.0.2.1" "bob"
event_copy_2 "192.0.2.2" "bob"
event_copy_3 "192.0.2.3" "bob"
event_copy_4 "" "bob"

Uma vez que event_copy_1 satisfaz todas as expressões em repeated_message_2, o evento corresponde à regra.

Isto pode levar a um comportamento inesperado porque a regra repeated_message_1 não tinha indexação de matrizes e não produziu correspondências, enquanto a regra repeated_message_2 usou a indexação de matrizes e produziu uma correspondência.

Precisa de mais ajuda? Receba respostas de membros da comunidade e profissionais da Google SecOps.