Campos repetidos
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_originalsatisfazany $e.principal.ip = "192.0.2.1"event_originalfalhaany $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_originalsatisfaznet.ip_in_range_cidr(all $e.principal.ip, "192.0.2.0/8")event_originalfalhaall $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 a192.168.12.16. Isso significa que a consulta está verificando se pelo menos um endereço IP não corresponde a192.168.12.16.all $e.principal.ip != "192.168.12.16"verifica se todos os endereços IP não correspondem a192.168.12.16. Isso significa que a consulta verifica se nenhum endereço IP corresponde a192.168.12.16.
Restrições:
- Os operadores
anyeallsão compatíveis apenas com campos repetidos (não escalares). anyeallnão podem ser usados para unir dois campos repetidos. Por exemplo,any $e1.principal.ip = $e2.principal.ipnão é válido.- Os operadores
anyeallnã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
anyoualloperam na lista emevent_original. - As expressões em campos repetidos que não usam
anyoualloperam em eventosevent_copy_nindividuais.
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 comotrue.
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 comoint) não são contabilizados. - A indexação de matriz não pode ser combinada com
anyouall. 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 porqueintermediaryeipsão campos repetidos, mas há apenas um índice paraip.
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.