Referência de linguagem das regras personalizadas do Google Cloud Armor

O Google Cloud Armor permite definir regras priorizadas com ações e condições de correspondência configuráveis em uma política de segurança. Uma regra entra em vigor, o que significa que a ação configurada é aplicada, se a regra for a de maior prioridade, em que os atributos da solicitação de entrada correspondem aos expressos na condição de correspondência da regra.

Há dois tipos de condições de correspondência.

  • Uma condição de correspondência básica contém listas de endereços IP ou de intervalos de endereços IP.
  • Uma condição de correspondência avançadacontém uma expressão com várias subexpressões para corresponder a diversos atributos de uma solicitação recebida.

A linguagem das regras personalizadas é usada para escrever as expressões em condições avançadas de correspondência para regras de política de segurança. A linguagem das regras personalizadas do Google Cloud Armor é uma extensão da Common Expression Language (CEL).

Uma expressão requer dois componentes:

  • Atributos que podem ser inspecionados em expressões de regra.
  • Operações que podem ser executadas nos atributos como parte de uma expressão.

Por exemplo, a expressão a seguir usa os atributos origin.ip e 9.9.9.0/24 na operação inIpRange(). Nesse caso, a expressão retornará como verdadeiro se origin.ip estiver dentro do intervalo de endereços IP de 9.9.9.0/24.

inIpRange(origin.ip, '9.9.9.0/24')

Atributos

Os atributos representam informações de uma solicitação recebida, como o endereço IP de origem ou o caminho do URL solicitado.

Campo Tipo Descrição do campo
origin.ip string O endereço IP de origem da solicitação.
request.headers mapa Um mapa string a string dos cabeçalhos de solicitação HTTP. Se um cabeçalho contiver vários valores, o valor nesse mapa seria uma string separada por vírgula de todos os valores do cabeçalho. As chaves deste mapa ficam todas em minúsculas. Somente os primeiros 16kb de cada valor de cabeçalho estão disponíveis para inspeção. Qualquer valor de cabeçalho acima de 16 KB é truncado pelas especificações do balanceador de carga do Google Cloud.
request.method string O método de solicitação HTTP, como GET ou POST.
request.path string O caminho do URL de HTTP solicitado.
request.scheme string O esquema de URL HTTP, como http ou https. Os valores deste atributo ficam todos em minúsculas.
request.query string A consulta de URL de HTTP no formato name1=value&name2=value2, conforme aparece na primeira linha da solicitação HTTP. Nenhuma decodificação é executada.
origin.region_code string O código do país em Unicode associado ao IP de origem, como US. Se você estiver criando uma regra ou expressão que usa códigos de país ou região ISO 3166-1 Alfa 2, o Google Cloud Armor tratará cada código de maneira independente. As regras e expressões do Google Cloud Armor usam explicitamente esses códigos de região para permitir ou negar solicitações.

Saiba mais em unicode_region_subtag no Unicode Technical Standard.

Operações

A referência a seguir descreve os operadores que podem ser usados com atributos (representados por x, y e k) para definir expressões de regra.

Expressões Descrição
x == "foo" Retorna como verdadeiro se x for igual à literal de string constante fornecida.
x == R"fo'o" Retorna como verdadeiro se x for igual à literal de string bruta fornecida que não interpreta sequências de escape. As literais de string bruta são convenientes para expressar strings que precisam usar caracteres de sequência de escape.
x == y Retorna TRUE, se x for igual a y.
x != y Retorna TRUE, se x não for igual a y.
x + y Retorna a string concatenada xy .
x && y Retorna como verdadeiro se x e y forem verdadeiros.
x || y Retorna como verdadeiro se x, y ou ambos forem verdadeiros.
!x Retorna como verdadeiro se o valor booleano x for falso ou retorna como falso se o valor booleano x for verdadeiro.
x.contains(y) Retorna como verdadeiro se a string x contiver a substring y.
x.startsWith(y) Retorna como verdadeiro se a string x começar com a substring y.
x.endsWith(y) Retorna como verdadeiro se a string x terminar com a substring y.
x.matches(y) Retorna como verdadeiro se a string x corresponder ao padrão RE2 especificado y O padrão RE2 é compilado usando a opção RE2::Latin1 que desativa os recursos Unicode.
inIpRange(x, y) Retorna como verdadeiro se o endereço IP x estiver dentro do intervalo IP de y As máscaras de sub-rede para endereços IPv6 não podem ser maiores que /64.
x.lower() Retorna o valor em minúsculas da string x.
x.upper() Retorna o valor em maiúsculas da string x.
x.base64Decode() Retorna o valor de x. decodificado em Base64; os caracteres _ - são substituídos primeiro por / + respectivamente. Retorna "" (string vazia) se x não for um valor base64 válido.
has(m['k']) Retorna como verdadeiro se a chave k. estiver disponível no mapa m.
m['k'] Retorna o valor na chave k no mapa string a string m. se k estiver disponível, caso contrário, retorna um erro. A abordagem recomendada é verificar a disponibilidade usando "has(m['k'])==true".
int(x) Converte o resultado da string de x em um tipo int. Ele pode ser usado para fazer uma comparação de números inteiros usando operadores aritméticos padrão, como > e <=. Isso funciona apenas para valores que precisam ser inteiros.

Exemplos de expressões

Para cada uma dessas expressões, a ação realizada depende de a expressão ser incluída em uma regra de negação ou em uma regra de permissão.

Permitir ou negar acesso com base em um intervalo de endereços IP em IPv4 ou IPv6

  • A expressão a seguir corresponde às solicitações do intervalo de endereços IP 9.9.9.0/24:

    inIpRange(origin.ip, '9.9.9.0/24')
    
  • A expressão a seguir corresponde às solicitações do intervalo de endereços IP 2001:db8::/32:

    inIpRange(origin.ip, '2001:db8::/32')
    
  • A expressão a seguir corresponde a solicitações que têm um cookie contendo 80=BLAH:

    has(request.headers['cookie']) && request.headers['cookie'].contains('80=BLAH')
    

Permitir ou negar tráfego com um cabeçalho referer não vazio

  • A expressão a seguir corresponde a solicitações que têm um cabeçalho referer não vazio:

    has(request.headers['referer']) && request.headers['referer'] != ""
    

Negar tráfego de uma região específica

Se o aplicativo da Web ainda não estiver disponível na região AU, todas as solicitações dessa região deverão ser bloqueadas.

  • Use a seguinte expressão, que corresponde às solicitações da região AU, em uma regra de negação:

    origin.region_code == 'AU'
    

Os códigos de região são baseados nos códigos ISO 3166-1 alpha 2. Em alguns casos, uma região corresponde a um país, mas nem sempre é o caso. Por exemplo, o código US inclui todos os estados dos Estados Unidos, um distrito e seis áreas remotas.

Várias expressões

Para incluir várias condições em apenas uma regra, combine várias subexpressões.

  • No exemplo a seguir, solicitações de 1.2.3.0/24 (como seus testadores alfa) na região AU correspondem à seguinte expressão:

    origin.region_code == "AU" && inIpRange(origin.ip, '1.2.3.0/24')
    
  • A expressão a seguir corresponde a solicitações de 1.2.3.4 em que um user agent contém a string WordPress:

    inIpRange(origin.ip, '1.2.3.4/32') &&
    has(request.headers['user-agent']) && request.headers['user-agent'].contains('WordPress')
    

Permitir ou negar tráfego para um URI de solicitação que corresponda a uma expressão regular

  • A expressão a seguir corresponde a solicitações que contêm a string bad_path no URI:

    request.path.matches('/bad_path/')
    
  • A expressão a seguir corresponde a solicitações que têm Chrome no campo de cabeçalho User-Agent:

    request.headers['user-agent'].matches('Chrome')
    
  • A expressão a seguir mostra uma correspondência que não diferencia maiúsculas de minúsculas para o cabeçalho User-Agent que contém wordpress; corresponde a User-Agent:WordPress/605.1.15, User-Agent:wordPress e outras variações de wordpress:

    request.headers['user-agent'].matches('(?i:wordpress)')
    

Permitir ou negar tráfego que contém um valor decodificado em Base64 específico

  • A expressão a seguir corresponde a solicitações que têm um valor decodificado em Base64 de myValue para o cabeçalho user-id:

    has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')
    

Permitir ou negar tráfego que tenha o valor zero content-length no corpo HTTP

  • A expressão a seguir corresponde a solicitações que têm um content-length zero no corpo do HTTP:

    int(request.headers["content-length"]) == 0
    

Regras pré-configuradas

As regras pré-configuradas usam assinaturas estáticas pré-configuradas, expressões regulares ou ambas para corresponder aos cabeçalhos de solicitação HTTP e parâmetros de consulta. As regras pré-configuradas disponíveis são baseadas no conjunto de regras principais do OWASP Modsecurity versão 3.0.1. O Google Cloud Armor oferece dois conjuntos de expressões predefinidas:

  • xss-<version>: protege contra ataques de scripting em vários locais
  • sqli-<version>: protege contra ataques de injeção de SQL

Para listar todas as regras pré-configuradas disponíveis, consulte Como listar as regras pré-configuradas disponíveis.

Para mais informações sobre regras pré-configuradas, consulte o caso de uso Reduzir ataques de camada de aplicativo usando regras pré-configuradas.

Nomes de conjuntos de expressões

Os nomes de conjuntos de expressões têm o formato <attack category>-<version field>. A categoria de ataque especifica o tipo de ataque que você quer proteger, como xss (scripts entre sites) ou sqli (injeção de SQL).

Os campos de versão compatíveis são stable e canary. Adições e modificações nas regras são lançadas primeiro na versão canary. Quando as adições e modificações são consideradas seguras e estáveis, elas são promovidas à versão stable.

IDs de membros do conjunto de expressões

Um conjunto de expressões contém várias expressões, cada uma com seu próprio ID do conjunto de regras principais (CRS, na sigla em inglês). Por exemplo, o conjunto de expressões xss-stable inclui uma expressão chamada owasp-crs-v020901-id981136-xss, que corresponde ao ID de regra 981136 da version 2.9.1. É possível usar os IDs do CRS para excluir o uso de expressões específicas, o que é útil se uma expressão específica acionar constantemente um falso positivo. Veja mais informações na solução de problemas de falsos positivos.

Para informações sobre o conjunto de regras principais e ajuste em diferentes níveis de sensibilidade, consulte Como ajustar as regras da WAF do Google Cloud Armor.

Operador para regras pré-configuradas

Expressões Descrição
evaluatePreconfiguredExpr(string, LIST)

Retorna como verdadeiro se qualquer uma das expressões dentro do conjunto de expressões especificado retornar como verdadeiro.

O primeiro argumento é o nome do conjunto de expressões, como xss-stable. O segundo argumento (opcional) é uma lista string de IDs separados por vírgulas que devem ser excluídos da avaliação. A lista de exclusão é útil quando um determinado membro do conjunto de expressões aciona um falso positivo.

Exemplos de regras pré-configuradas

  • A expressão a seguir usa a regra pré-configurada xss-stable para mitigar ataques XSS:

    evaluatePreconfiguredExpr('xss-stable')
    
  • A expressão a seguir usa todas as expressões da regra pré-configurada xss-stable, exceto os IDs de membro 981136 e 981138:

    evaluatePreconfiguredExpr('xss-stable', ['owasp-crs-v020901-id981136-xss',
    'owasp-crs-v020901-id981138-xss'])
    
  • A expressão a seguir usa uma regra pré-configurada para mitigar ataques SQLi do intervalo de endereços IP 198.51.100.0/24:

    inIpRange(origin.ip, '198.51.100.0/24') && evaluatePreconfiguredExpr('sqli-stable')
    

A seguir