Campos repetidos

Compatível com:

No modelo de dados unificado (UDM), alguns campos são rotulados 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 repetidos do UDM.

Expressões booleanas e campos repetidos

Expressões booleanas modificadas e não modificadas podem agir 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 atender à condição, o evento como um todo vai atender. 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 atenderem à condição, o evento como um todo vai atender à condição. 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"

Ao escrever uma condição com any ou all, saiba que negar a condição com not pode não ter o mesmo significado que usar o operador negado.

Exemplo:

  • not all $e.principal.ip = "192.168.12.16" verifica se nem todos os endereços IP correspondem a 192.168.12.16. Isso significa que a consulta está verificando 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. Isso significa que a consulta verifica se nenhum endereço IP corresponde a 192.168.12.16.

Restrições:

  • Os operadores any e all são compatíveis apenas com campos repetidos (não escalares).
  • any e all não podem ser usados para unir 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 compatíveis 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 tiver n elementos, a consulta será aplicada em n cópias do evento, em que cada cópia tem um dos elementos do campo repetido. Essas cópias são temporárias e não são armazenadas.

A regra é aplicada nas seguintes cópias:

cópia 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 de evento satisfizer todas as condições não modificadas no campo repetido, o evento como um todo vai satisfazer todas as condições. Portanto, se você tiver várias condições em um campo repetido, uma única cópia de evento precisará atender a todas elas. Os exemplos de consultas a seguir usam o conjunto de dados de exemplo anterior para demonstrar esse comportamento.

Exemplo: expressões não modificadas

A regra a seguir retorna 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 a seguir não retorna uma correspondência quando executada no conjunto de dados de exemplo event_original porque não há uma cópia de evento em $e.principal.ip que satisfaça _todos_ os predicados de evento.

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 as não modificadas porque a lista de elementos é a mesma para cada cópia de 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:

cópia 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"]

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

Outra forma de pensar nesses 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

Campos repetidos funcionam com atribuições de marcador de posição. Assim como as expressões não modificadas em campos repetidos, uma cópia do evento é feita para cada elemento. Usando o mesmo exemplo de event_copy, o marcador de posição recebe o valor do campo repetido de event_copy_n para cada uma das cópias de evento em que n é o número da cópia do evento. Se o marcador de posição for usado na seção de correspondência, isso poderá resultar em várias correspondências.

Exemplo: marcador de posição de campo repetido

O exemplo a seguir gera uma correspondência. O marcador de posição `$ip` é igual a `192.0.2.1` para `event_copy_1`, o que atende aos predicados na regra. As amostras de eventos da partida 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 a seguir gera três correspondências. O marcador de posição $ip é igual a valores diferentes para cada uma das cópias de event_copy_n. O agrupamento é feito em $ip porque está na seção de correspondência. Portanto, você recebe três correspondências, cada uma com um valor diferente para a variável de correspondência $ip. Cada correspondência tem a mesma amostra 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 usando 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, não à lista inteira. Quando eles são usados na seção outcome, o resultado é calculado usando apenas os elementos que atenderam às seçõ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
}

Há quatro estágios de execução para essa regra. A primeira etapa é a cópia de eventos:

cópia 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 seção de eventos vai filtrar as linhas que não correspondem aos filtros:

cópia 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 atende a $ip = "192.0.2.1" or $ip = "192.0.2.2".

A seção match vai agrupar por variáveis de correspondência, e a seção outcome vai fazer a agregação em cada grupo:

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

$o = array_distinct($ip) é calculado usando $ip da etapa anterior, não da etapa de cópia de eventos.

Por fim, a seção condition vai filtrar cada grupo. Como essa regra verifica apenas a existência de $e, a linha anterior vai gerar uma única detecção.

$o não contém todos os elementos de $e.principal.ip porque nem todos os elementos atendem a todas as condições na seção de eventos. No entanto, todos os elementos de e.principal.ip vão aparecer na amostra de evento porque ela usa event_original.

Indexação de matrizes

É possível realizar indexação de matrizes em campos repetidos. Para acessar o n-ésimo elemento de campo repetido, use a sintaxe de lista padrão (os elementos são indexados em zero). Um elemento fora dos limites retorna o valor padrão.

  • $e.principal.ip[0] = "192.168.12.16"
  • $e.principal.ip[999] = "" Se houver menos de 1.000 elementos, isso será avaliado como true.

Restrições:

  • Um índice precisa ser um literal inteiro não negativo. Por exemplo, $e.principal.ip[-1] não é válido.
  • 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 matriz não pode ser combinada com any ou 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 mapa. Por exemplo, $e.additional.fields[0]["key"] não é válido.
  • Se o caminho do campo contiver vários campos repetidos, todos eles precisarão usar indexação de matriz. Por exemplo, $e.intermediary.ip[0] não é válido porque intermediary e ip são campos repetidos, mas há apenas um índice para ip.

Mensagens repetidas

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

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

Como afirmado para expressões não modificadas em campos repetidos, uma cópia temporária do evento é feita 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:

cópia 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 há uma cópia que satisfaça todas as expressões.

Mensagens repetidas e indexação de matrizes

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

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:

cópia 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"

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

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

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