Configura los atributos del lenguaje de reglas personalizadas

Cada regla de la política de seguridad de Google Cloud Armor tiene una prioridad, una condición de coincidencia y una acción. Google Cloud Armor realiza la acción de la regla de prioridad más alta que coincide con una solicitud. No se evalúan las reglas con una prioridad más baja que la regla de coincidencia de prioridad más alta, incluso si tienen las mismas condiciones de coincidencia.

Cada regla de la política de seguridad admite dos tipos de condiciones de coincidencia:

  • Una condición de coincidencia básica contiene listas de direcciones IP o listas de rangos de direcciones IP. Las condiciones de coincidencia básicas se definen con la marca --src-ip-ranges cuando se crea una regla con Google Cloud CLI.
  • Una condición de coincidencia avanzada contiene una expresión con hasta cinco subexpresiones que pueden coincidir con una variedad de atributos de una solicitud entrante. Las condiciones de coincidencia avanzadas se definen con la marca --expression cuando se crea una regla con Google Cloud CLI.

En esta página, se analizan las condiciones de coincidencia avanzadas y el lenguaje de reglas personalizadas de Google Cloud Armor que usas para escribir expresiones en las condiciones de coincidencia avanzadas de las reglas de políticas de seguridad. El lenguaje de reglas personalizadas de Google Cloud Armor es un subconjunto del Common Expression Language (CEL). Las expresiones escritas en el lenguaje de reglas personalizadas de Google Cloud Armor requieren dos componentes:

  • El atributo: Son los datos que se inspeccionarán.
  • La operación: cómo usar los datos

Por ejemplo, en la siguiente expresión, se usan los atributos origin.ip9.9.9.0/24 en la operación inIpRange(). En este caso, la expresión muestra un valor verdadero si origin.ip está dentro del rango de direcciones IP 9.9.9.0/24.

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

Aunque la expresión del ejemplo anterior solo coincide con la dirección IP de origen, cuando la usas en una regla de política de seguridad de Google Cloud Armor, la regla se considera una regla con condiciones de coincidencia avanzadas desde una perspectiva de cuota. Para obtener más información, consulta Cuotas y límites de Google Cloud Armor.

Atributos

Los atributos representan información de una solicitud entrante, como la dirección IP de origen o la ruta de URL solicitada.

Campo Tipo Descripción del campo
origin.ip string Es la dirección IP de origen de la solicitud.
origin.user_ip string Es la dirección IP del cliente de origen, que un proxy upstream incluye en HTTP-HEADER. Antes de usar este atributo, debes configurar la opción userIpRequestHeaders[] en el campo advancedOptionsConfig de la política de seguridad para que coincida con una fuente como True-Client-IP, X-Forwarded-For o X-Real-IP.

Si no configuras la opción userIpRequestHeaders[], si el encabezado configurado contiene valores de direcciones IP no válidos o si no está presente, origin.user_ip se establece de forma predeterminada en origin.ip. Para obtener más información, consulta la referencia de recursos securityPolicy.

origin.tls_ja3_fingerprint string Huella digital de TLS/SSL de JA3 si el cliente se conecta con HTTPS, HTTP/2 o HTTP/3. Si no está disponible, se muestra una cadena vacía.
request.headers mapa Es un mapa de string a string de los encabezados de solicitud HTTP. Si un encabezado contiene varios valores, el valor de este mapa es una string separada por comas de todos los valores del encabezado. Las claves en este mapa están en minúsculas. Se inspeccionan todos los encabezados que aceptan los balanceadores de cargas de aplicaciones externos, y se aplican las mismas limitaciones.

El enfoque recomendado es verificar primero la disponibilidad con has(), como has(request.headers['header-key']) && request.headers['header-key'] != 'header-value'.

request.method string Es el método de solicitud HTTP, como GET o POST.
request.path string La ruta de URL HTTP solicitada.
request.scheme string Es el esquema de URL HTTP, como http o https. Todos los valores de este atributo están en minúsculas.
request.query string Es la consulta de URL HTTP en el formato name1=value&name2=value2, como aparece en la primera línea de la solicitud HTTP. No se realiza ninguna decodificación.
origin.region_code string Es el código de país de Unicode que está asociado a la IP de origen, como US. Si creas una regla o una expresión que usa códigos de país o región ISO 3166-1 alfa-2, Google Cloud Armor trata cada código de forma independiente. Las reglas y expresiones de Google Cloud Armor usan esos códigos de región de forma explícita para permitir o denegar solicitudes.

Para obtener más información, consulta unicode_region_subtag en el estándar técnico de Unicode.

origin.asn número entero El número de sistema autónomo (ASN) asociado con la dirección IP de origen. El ASN único a nivel global se determina en función del operador de red que admite los prefijos de direcciones IP que contienen la dirección IP de origen.

Atributos de reCAPTCHA

En esta sección, se enumeran los atributos que solo se aplican a tokens o cookies de exención de reCAPTCHA. Una subexpresión basada en estos atributos muestra false si el token o la cookie de exención de reCAPTCHA que se evaluará no está disponible o no es válido por uno de los siguientes motivos:

  • El token tiene un formato incorrecto y no se puede decodificar.
  • El token contiene atributos no válidos. Por ejemplo, el token se generó con una clave de reCAPTCHA que no coincide con las claves de reCAPTCHA asociadas a la regla.
  • El token está vencido.
Campo Tipo Descripción del campo
token.recaptcha_exemption.valid bool La presencia de una cookie de exención de reCAPTCHA válida.

Atributos del token de acción

Campo Tipo Descripción del campo
token.recaptcha_action.score float La puntuación de un token de acción de reCAPTCHA Enterprise. Una puntuación válida varía de 0.0 a 1.0, donde 0.0 es muy probable que sea un usuario ilegítimo y 1.0 es muy probable que sea un usuario legítimo.
token.recaptcha_action.captcha_status string El estado del captcha de un token de acción de reCAPTCHA. Un estado válido es NONE, PASS o FAIL, en el que NONE hace referencia a que no hay desafíos involucrados durante la evaluación de reCAPTCHA, de modo que falta el campo de captcha en el token de acción.
token.recaptcha_action.action string El nombre de la acción (hasta 100 caracteres) de un token de acción de reCAPTCHA. Consulta Nombres de acciones.
token.recaptcha_action.valid bool La presencia de un token de acción de reCAPTCHA válido.

Atributos del token de sesión

Campo Tipo Descripción del campo
token.recaptcha_session.score float La puntuación de un token de sesión de reCAPTCHA. Una puntuación válida varía de 0.0 a 1.0, donde 0.0 es muy probable que sea un usuario ilegítimo y 1.0 es muy probable que sea un usuario legítimo.
token.recaptcha_session.valid bool La presencia de un token de sesión de reCAPTCHA válido.

Operations

En la siguiente referencia, se describen los operadores que puedes usar con atributos (representados por xyk) para definir expresiones de reglas.

Expresiones Descripción
x == "foo" El resultado es verdadero si x es igual al literal de string constante determinado.
x == R"fo'o" El resultado es verdadero si x es igual al literal de string sin procesar determinado que no interpreta las secuencias de escape. Los literales de string sin procesar son convenientes para expresar strings que deben usar caracteres de secuencia de escape.
x == y Muestra TRUE si x es igual que y.
x != y Muestra TRUE si x no es igual que y.
x + y El resultado es la string concatenada xy.
x && y El resultado es verdadero si tanto xcomo y son verdaderos.
x || y El resultado es verdadero si x, y, o ambos son verdaderos.
!x El resultado es verdadero si el valor booleano x es falso. En cambio, el resultado es falso si el valor booleano x es verdadero.
x.contains(y) El resultado es verdadero si la string x contiene la substring y.
x.startsWith(y) El resultado es verdadero si la string x comienza con la substring y.
x.endsWith(y) El resultado es verdadero si la string x termina con la substring y.
x.matches(y) El resultado es verdadero si la cadena x coincide parcialmente con el patrón RE2 y especificado. El patrón RE2 se compila con la opción RE2::Latin1 que inhabilita las funciones de Unicode.
inIpRange(x, y) Muestra true si la dirección IP x está incluida en el rango de IP y.
x.lower() Muestra el valor de la string x en minúsculas.
x.upper() Muestra el valor de la string x en mayúsculas.
x.base64Decode() Muestra el valor decodificado en Base64 de x. A los caracteres _ - se los reemplaza primero por / +, respectivamente. Muestra "" (string vacía) si x no es un valor en Base64 válido.
has(m['k']) El resultado es verdadero si la clave k está disponible en el mapa m.
m['k'] Muestra el valor de la clave k en el mapa de string a string m si k está disponible; de lo contrario, muestra un error. El enfoque recomendado es verificar primero la disponibilidad mediante "has(m['k'])==true".
int(x) Convierte el resultado de la string de x en un tipo de int. Luego, se puede usar con el fin de hacer una comparación de números enteros mediante operadores aritméticos estándar como > y <=. Esto funciona solo para valores que deben ser enteros.
size(x) Muestra la longitud de la cadena x.
x.urlDecode() Muestra el valor decodificado en URL de x; las secuencias de caracteres en formato %## se reemplazan por los equivalentes que no son ASCII y + se reemplaza por un espacio. Las codificaciones no válidas se muestran tal como están.
x.urlDecodeUni() Muestra el valor decodificado en URL de x; además de urlDecode(), esto también controla secuencias de caracteres unicode en formato %u###. Las codificaciones no válidas se muestran tal como están.
x.utf8ToUnicode() Muestra la representación Unicode en minúsculas de una x codificada en UTF-8.

Expresiones de ejemplo

Para cada una de estas expresiones, la acción que se realiza depende de si la expresión se incluye en una regla de denegación o de admisión.

Permite o deniega el acceso según un rango de direcciones IP en IPv4 o IPv6

  • La siguiente expresión coincide con las solicitudes del rango de direcciones IP 198.51.100.0/24:

    inIpRange(origin.ip, '198.51.100.0/24')
    
  • La siguiente expresión coincide con las solicitudes del rango de direcciones IP 2001:db8::/32:

    inIpRange(origin.ip, '2001:db8::/32')
    

Permite o deniega el acceso según un rango de direcciones IP de cliente personalizado detrás de un proxy upstream

Si configuraste el operador origin.user_ip, puedes establecer coincidencias según los valores de encabezado que especificaste en tu campo advancedOptionsConfig.userIpRequestHeaders[].

  • La siguiente expresión coincide con las solicitudes que se originaron en el rango de direcciones IP 192.0.2.0/24:

    inIpRange(origin.user_ip, '192.0.2.0/24')
    
  • La siguiente expresión coincide con las solicitudes que se originaron en el rango de direcciones IP 2001:db8::/32:

    inIpRange(origin.user_ip, '2001:db8::/32')
    
  • La siguiente expresión coincide con las solicitudes que tienen una cookie que tiene 80=BLAH.

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

Permite o deniega el tráfico con un encabezado referer que no esté vacío

  • La siguiente expresión coincide con las solicitudes que tienen un encabezado referer que no está vacío.

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

Permite o deniega el tráfico según la URL del host en el encabezado

  • La siguiente expresión coincide con las solicitudes a una URL específica:

    request.headers['host'].lower().contains('test.example.com')
    

Permite o deniega el tráfico desde una región específica

Si tu aplicación web no está disponible en la región AU, todas las solicitudes de esa región deben bloquearse.

  • En una regla de rechazo, usa la siguiente expresión, que coincide con las solicitudes de la región AU:

    origin.region_code == 'AU'
    

Como alternativa, si tu aplicación web solo está disponible en la región AU, se deben bloquear las solicitudes de todas las demás regiones.

  • En una regla de denegación, usa la siguiente expresión, que coincide con las solicitudes de todas las regiones que no sean AU:

    origin.region_code != 'AU'
    

Los códigos de región se basan en los códigos ISO 3166-1 alfa-2. En algunos casos, una región corresponde a un país, pero no siempre es así. Por ejemplo, el código US incluye todos los estados de Estados Unidos, un distrito y seis áreas periféricas.

Permite o deniega el tráfico desde un ASN específico

Si tu aplicación web debe bloquearse para los clientes a los que presta servicio un operador de red específico, puedes usar el número ASN del operador de red para realizar el bloqueo.

  • En una regla de denegación, usa la siguiente expresión, que coincide con las solicitudes de un ASN específico:

    origin.asn == 123
    

Como alternativa, si tu aplicación web está solo disponible para los clientes detrás de un operador de red específico, deben bloquearse las solicitudes de todos los demás operadores de red.

  • En una regla de denegación, usa la siguiente expresión, que coincide con todos los demás operadores de red, excepto el que te interesa permitir:

    origin.asn != 123
    

Expresiones múltiples

Para incluir varias condiciones en una sola regla, combina varias subexpresiones.

  • En el siguiente ejemplo, las solicitudes de 1.2.3.0/24 (como tus verificadores Alfa) en la región AU coinciden con la siguiente expresión:

    origin.region_code == "AU" && inIpRange(origin.ip, '1.2.3.0/24')
    
  • La siguiente expresión coincide con las solicitudes de 1.2.3.4 en las que un usuario-agente contiene la string WordPress:

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

Permite o deniega el tráfico para un URI de solicitud que coincida con una expresión regular

  • La siguiente expresión coincide con las solicitudes que contienen la string example_path en el URI:

    request.path.matches('/example_path/')
    
  • La siguiente expresión coincide con las solicitudes que tienen Chrome en el campo de encabezado User-Agent:

    request.headers['user-agent'].matches('Chrome')
    
  • En la siguiente expresión, se muestra la coincidencia que no distingue entre mayúsculas y minúsculas para el encabezado User-Agent que contiene wordpress. Coincide con User-Agent:WordPress/605.1.15, User-Agent:wordPress y otras variantes de wordpress:

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

Permite o deniega el tráfico que contiene un valor decodificado en Base64 específico

  • La siguiente expresión coincide con las solicitudes que tienen un valor decodificado en Base64 de myValue para el encabezado user-id:

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

Permite o deniega el tráfico que contiene un valor de cadena de una longitud específica

  • La siguiente expresión coincide con las solicitudes que tienen una URL de más de 10 caracteres:

    size(request.path) > 10
    
  • La siguiente expresión coincide con las solicitudes que tienen una longitud de encabezado x-data superior o igual a 1,024 caracteres:

    size(request.headers['x-data']) >= 1024
    

Permite o deniega el tráfico que tiene una content-length de cero en el cuerpo HTTP

  • La siguiente expresión coincide con las solicitudes que tienen un content-length de cero en el cuerpo HTTP:

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

Permite o deniega el tráfico que contiene un valor codificado de URL específico

  • La siguiente expresión coincide con las solicitudes que tienen un valor de cookie que contiene %3c:

    has(request.headers['cookie']) && request.headers['cookie'].urlDecode().contains('<')
    

Permite o deniega el tráfico que contiene un valor codificado de URL específico de una cadena Unicode

  • La siguiente expresión coincide con las solicitudes que tienen un valor de cookie igual a Match%2BValue o Match%u002BValue:

    has(request.headers['cookie']) && request.headers['cookie'].urlDecodeUni() == 'Match+Value'
    

Permite o deniega el tráfico que contiene una string Unicode específica de un texto UTF-8

  • La siguiente expresión coincide con las solicitudes que tienen un valor de cookie igual a ¬:

    has(request.headers['cookie']) && request.headers['cookie'].utf8ToUnicode() == '%u00ac'
    

Permite o deniega el tráfico según una huella dactilar JA3 conocida

  • La siguiente expresión coincide con las solicitudes que tienen una huella digital de JA3 igual a e7d705a3286e19ea42f587b344ee6865:

    origin.tls_ja3_fingerprint == 'e7d705a3286e19ea42f587b344ee6865'
    

Permite o deniega el tráfico según una lista de huellas digitales JA3

  • La siguiente expresión coincide con las solicitudes que tienen una huella digital de JA3 igual a cualquiera de las siguientes:

    • e7d705a3286e19ea42f587b344ee6865
    • f8a5929f8949e846267b582072e35f84
    • 8f8b62163873a62234c14f15e7b88340
    origin.tls_ja3_fingerprint == 'e7d705a3286e19ea42f587b344ee6865' || origin.tls_ja3_fingerprint == 'f8a5929f8949e846267b582072e35f84' || origin.tls_ja3_fingerprint == '8f8b62163873a62234c14f15e7b88340'
    

Reglas de WAF preconfiguradas

Las reglas de WAF preconfiguradas usan firmas estáticas preconfiguradas, expresiones regulares o ambas para coincidir con el cuerpo HTTP POST, los encabezados de solicitud HTTP y los parámetros de consulta. Las reglas de WAF preconfiguradas disponibles se basan en el conjunto de reglas principales de Modsecurity de OWASP versión 3.3. Google Cloud Armor proporciona varias reglas de WAF predefinidas. Para obtener una lista completa de las reglas de WAF preconfiguradas, consulta la descripción general de las reglas de WAF preconfiguradas de Google Cloud Armor.

Para obtener una lista de todas las reglas de WAF preconfiguradas, consulta Visualiza las reglas de WAF preconfiguradas.

Para obtener más información sobre las reglas de WAF preconfiguradas, consulta el caso de uso Mitiga los ataques de la capa de la aplicación mediante reglas de WAF preconfiguradas.

Nombres de reglas de WAF preconfiguradas

Los nombres de reglas de WAF preconfigurados tienen el formato <attack category>-<ModSecurity CRS version>-<version field>. La categoría de ataque especifica el tipo de ataques de lo que te quieres proteger, como xss (secuencias de comandos entre sitios) o sqli (inyección de SQL).

Los campos de versiones compatibles son stable y canary. Las adiciones y modificaciones a las reglas se publican primero en la versión canary. Cuando las incorporaciones y modificaciones se consideran seguras y estables, se ascienden a la versión stable.

ID de miembros de reglas de WAF preconfigurados

Una regla de WAF preconfigurada contiene varias expresiones, cada una con su firma. Por ejemplo, la regla de WAF preconfigurada xss-v33-stable incluye una expresión llamada owasp-crs-v030301-id941100-xss, que corresponde al ID de regla id941100 para la versión 3.3. Puedes usar las firmas para excluir el uso de expresiones específicas, lo que es útil si una expresión en particular siempre activa un falso positivo. Para obtener más información, consulta la información sobre solución de problemas de falsos positivos.

Para obtener información sobre el conjunto de reglas principales y el ajuste en diferentes niveles de sensibilidad, consulta Ajusta las reglas de WAF de Google Cloud Armor.

Operador para reglas de WAF preconfiguradas

Expresiones Descripción
evaluatePreconfiguredWaf(string, MAP<string, dyn>) Muestra verdadero si alguna de las firmas de WAF dentro del conjunto de reglas de WAF especificado es verdadera. El primer argumento es el nombre del conjunto de reglas de WAF, como xss-v33-stable. El segundo argumento (opcional) es un mapa en el que la clave es una string y el valor se escribe de forma dinámica según la clave. El propósito de este argumento es ajustar las firmas de WAF que se evalúan. Entre las claves aceptadas, se incluyen las siguientes:
  • “Sensibilidad”: Corresponde al nivel de paranoia del conjunto de reglas principales de ModSecurity, que tiene 4 niveles, desde 1 hasta 4. Su valor es un número entero con un rango válido de 0 a 4. Ten en cuenta que 0 se reserva como un valor válido cuando se usa en combinación con “opt_in_rule_ids” (que se describe más adelante). Cuando se especifica una sensibilidad de x (x >= 1), se evalúan todas las firmas de WAF asociadas con un valor de sensibilidad de 1 a x. Cuando se omite, se usa 4 como el valor de sensibilidad.
  • “opt_out_rule_ids”: Las firmas WAF (representadas por los ID de regla) se deben inhabilitar de la evaluación, en el que el conjunto base se determina mediante el valor de sensibilidad. Su valor es una lista de strings. La cantidad máxima de ID de reglas permitidas es 128.
  • “opt_in_rule_ids”: Las firmas WAF (representadas por los ID de regla) se deben habilitar para la evaluación, en las que el conjunto base está vacío. Su valor es una lista de strings. La cantidad máxima de ID de reglas permitidas es 128. Cuando se usa, se debe especificar una “sensibilidad” de 0.

Las claves “opt_out_rule_ids” y “opt_in_rule_ids” son mutuamente excluyentes. Puedes usar “opt_in_rule_ids” si quieres revisar y habilitar manualmente las firmas nuevas de WAF que se agregan más adelante en un conjunto de reglas existente.

evaluatePreconfiguredExpr(string, LIST)

El resultado es verdadero si alguna de las expresiones dentro de la regla de WAF preconfigurada especificada es verdadera.

El primer argumento es el nombre de la regla de WAF preconfigurada, como xss-stable. El segundo argumento (opcional) es una lista de string separada por comas de los ID que se debe excluir de la evaluación. La lista de exclusiones es útil cuando un miembro determinado de la regla de WAF preconfigurada activa un falso positivo.

Ejemplos de reglas de WAF preconfiguradas

  • En la siguiente expresión, se usa la regla de WAF preconfigurada xss-v33-stable para mitigar los ataques de XSS:

    evaluatePreconfiguredExpr('xss-v33-stable')
    
  • En la siguiente expresión, se usan todas las expresiones de la regla de WAF preconfigurada xss-v33-stable, excepto los ID de miembro 941100 y 941110:

    evaluatePreconfiguredExpr('xss-v33-stable', ['owasp-crs-v030301-id941100-xss',
    'owasp-crs-v030301-id941110-xss'])
    
  • En la siguiente expresión, se usa una regla de WAF preconfigurada para mitigar los ataques de SQLi desde el rango de direcciones IP 198.51.100.0/24:

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

¿Qué sigue?