Configurer les attributs de langage des règles personnalisées

Chaque règle de stratégie de sécurité Google Cloud Armor possède une priorité, une condition de correspondance et une action. Google Cloud Armor exécute l'action de la règle de priorité la plus élevée qui correspond à une requête. Les règles dont la priorité est inférieure à celle de la règle de correspondance de priorité la plus élevée ne sont pas évaluées, même si elles ont les mêmes conditions de correspondance.

Chaque règle de stratégie de sécurité accepte deux types de conditions de correspondance:

  • Une condition de correspondance de base contient des listes d'adresses IP ou des listes de plages d'adresses IP. Les conditions de correspondance de base sont définies à l'aide de l'option --src-ip-ranges lorsque vous créez une règle à l'aide de Google Cloud CLI.
  • Une condition de correspondance avancée contient une expression avec jusqu'à cinq sous-expressions pouvant correspondre à divers attributs d'une requête entrante. Les conditions de correspondance avancées sont définies à l'aide de l'indicateur --expression lorsque vous créez une règle à l'aide de Google Cloud CLI.

Cette page présente les conditions de correspondance avancées et le langage des règles personnalisées Google Cloud Armor que vous utilisez pour écrire des expressions dans les conditions de correspondance avancées des règles de stratégie de sécurité. Le langage des règles personnalisées Google Cloud Armor est un sous-ensemble de Common Expression Language (CEL). Les expressions écrites dans le langage de règles personnalisées de Google Cloud Armor nécessitent deux composants:

  • Attribut: données à inspecter
  • L'opération: comment utiliser les données

Par exemple, l'expression suivante utilise les attributs origin.ip et 9.9.9.0/24 dans l'opération inIpRange(). Dans ce cas, l'expression renvoie "true" si origin.ip est compris dans la plage d'adresses IP 9.9.9.0/24.

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

Même si l'exemple d'expression précédent ne correspond qu'à l'adresse IP source, lorsque vous utilisez l'exemple d'expression dans une règle de stratégie de sécurité Google Cloud Armor, la règle est considérée comme une règle avec des conditions de correspondance avancées du point de vue des quotas. Pour en savoir plus, consultez la page Quotas et limites de Google Cloud Armor.

Attributs

Les attributs représentent des informations provenant d'une requête entrante, telles que l'adresse IP d'origine ou le chemin d'URL demandé.

Champ Type Description du champ
origin.ip chaîne Adresse IP source de la requête.
origin.user_ip chaîne Adresse IP du client d'origine, incluse dans HTTP-HEADER par un proxy en amont. Avant d'utiliser cet attribut, vous devez configurer l'option userIpRequestHeaders[] dans le champ advancedOptionsConfig de la stratégie de sécurité pour qu'elle corresponde à une source telle que True-Client-IP, X-Forwarded-For ou X-Real-IP.

Si vous ne configurez pas l'option userIpRequestHeaders[], si l'en-tête configuré contient des valeurs d'adresse IP non valides ou si l'en-tête configuré n'est pas présent, origin.user_ip est défini par défaut sur origin.ip. Pour en savoir plus, consultez la documentation de référence sur la ressource securityPolicy.

origin.tls_ja3_fingerprint chaîne Empreinte TLS/SSL JA3 si le client se connecte via HTTPS, HTTP/2 ou HTTP/3. Si ce n'est pas le cas, une chaîne vide est renvoyée.
request.headers carte Mappage chaîne à chaîne des en-têtes de requête HTTP. Si un en-tête contient plusieurs valeurs, la valeur figurant dans ce mappage est une chaîne de toutes les valeurs de l'en-tête, séparées par des virgules. Les clés de ce mappage sont toutes en minuscules. Tous les en-têtes acceptés par les équilibreurs de charge d'application externes sont inspectés, et les mêmes limites s'appliquent.

L'approche recommandée consiste à vérifier d'abord la disponibilité à l'aide de has(), par exemple has(request.headers['header-key']) && request.headers['header-key'] != 'header-value'.

request.method chaîne Méthode de requête HTTP, telle que GET ou POST.
request.path chaîne Chemin d'URL HTTP demandé.
request.scheme chaîne Schéma d'URL HTTP, tel que http ou https. Les valeurs de cet attribut sont toutes en minuscules.
request.query chaîne Requête d'URL HTTP au format name1=value&name2=value2, telle qu'elle apparaît sur la première ligne de la requête HTTP. Aucun décodage n'est effectué
origin.region_code chaîne Code pays Unicode associé à l'adresse IP d'origine, tel que US. Si vous créez une règle ou une expression qui utilise des codes de pays ou de région ISO 3166-1 alpha-2, Google Cloud Armor traite chaque code indépendamment. Les règles et expressions Google Cloud Armor utilisent explicitement ces codes de région pour autoriser ou refuser des requêtes.

Pour plus d'informations, consultez la section unicode_region_subtag de la spécification Unicode Technical Standard.

origin.asn Entier Numéro ASN (Autonomous System Number) associé à l'adresse IP d'origine Le numéro ASN unique est déterminé en fonction de l'opérateur réseau qui accepte les préfixes d'adresse IP contenant l'adresse IP d'origine.

Attributs reCAPTCHA

Cette section liste les attributs qui ne s'appliquent qu'aux jetons ou aux cookies d'exception reCAPTCHA. Une sous-expression basée sur ces attributs renvoie false si le jeton ou le cookie d'exception reCAPTCHA à évaluer n'est pas disponible ou n'est pas valide pour l'une des raisons suivantes:

  • Le jeton est incorrect et ne peut pas être décodé.
  • Le jeton contient des attributs non valides. Par exemple, le jeton a été généré à l'aide d'une clé reCAPTCHA qui ne correspond pas aux clés reCAPTCHA associées à la règle.
  • Le jeton a expiré.
Champ Type Description du champ
token.recaptcha_exemption.valid bool Présence d'un cookie d'exception reCAPTCHA valide.

Attributs des jetons d'action

Champ Type Description du champ
token.recaptcha_action.score float Score d'un jeton d'action reCAPTCHA. Un score valide varie de 0.0 à 1.0, où 0.0 désigne très probablement un utilisateur illégitime et 1.0 désigne très probablement un utilisateur légitime.
token.recaptcha_action.captcha_status string État captcha d'un jeton reCAPTCHA. Un état valide est NONE, PASS ou FAIL, où NONE fait référence à l'absence de questions d'authentification lors de l'évaluation reCAPTCHA, de sorte que le champ captcha ne figure pas dans le jeton d'action.
token.recaptcha_action.action string Nom de l'action (jusqu'à 100 caractères) provenant d'un jeton d'action reCAPTCHA Enterprise. Consultez la section Noms des actions.
token.recaptcha_action.valid bool Présence d'un jeton d'action reCAPTCHA valide.

Attributs des jetons de session

Champ Type Description du champ
token.recaptcha_session.score float Score d'un jeton de session reCAPTCHA. Un score valide varie de 0.0 à 1.0, où 0.0 désigne très probablement un utilisateur illégitime et 1.0 désigne très probablement un utilisateur légitime.
token.recaptcha_session.valid bool Présence d'un jeton de session reCAPTCHA valide.

Opérations

La documentation de référence suivante décrit les opérateurs que vous pouvez utiliser avec des attributs (représentés par x, y et k) pour définir des expressions de règle.

Description Description
x == "foo" Renvoie "true" si x est égal au littéral de chaîne constante donné.
x == R"fo'o" Renvoie "true" si x est égal au littéral de chaîne brute donné qui n'interprète pas les séquences d'échappement. Les littéraux de chaîne brute sont pratiques pour exprimer des chaînes qui doivent elles-mêmes utiliser des caractères de séquence d'échappement.
x == y Renvoie "true" si x est égal à y.
x != y Renvoie "true" si x n'est pas égal à y.
x + y Renvoie la chaîne concaténée xy.
x && y Renvoie "true" si x et y sont vrais.
x || y Renvoie "true" si x, y ou les deux sont vrais.
!x Renvoie "true" si la valeur booléenne x est fausse ou renvoie "false" si la valeur booléenne x est vraie.
x.contains(y) Renvoie "true" si la chaîne x contient la sous-chaîne y.
x.startsWith(y) Renvoie "true" si la chaîne x commence par la sous-chaîne y.
x.endsWith(y) Renvoie "true" si la chaîne x se termine par la sous-chaîne y.
x.matches(y) Renvoie "true" si la chaîne x est partiellement mise en correspondance par le modèle RE2 y spécifié. Le modèle RE2 est compilé à l'aide de l'option RE2::Latin1 qui désactive les fonctionnalités Unicode.
inIpRange(x, y) Renvoie la valeur "true" si l'adresse IP x est comprise dans la plage d'adresses IP y.
x.lower() Renvoie la valeur en minuscules de la chaîne x.
x.upper() Renvoie la valeur en majuscules de la chaîne x.
x.base64Decode() Renvoie la valeur décodée en base64 de x. Les caractères _ - sont d'abord remplacés par / + respectivement. Renvoie "" (chaîne vide) si x n'est pas une valeur base64 valide.
has(m['k']) Renvoie "true" si la clé k est disponible dans le mappage m.
m['k'] Renvoie la valeur à la clé k dans le mappage chaîne à chaîne m si k est disponible. Sinon, renvoie une erreur. L'approche recommandée consiste à vérifier d'abord la disponibilité à l'aide de "has(m['k'])==true".
int(x) Convertit le résultat de chaîne de x en type int. Il peut ensuite être utilisé pour établir une comparaison d'entiers à l'aide d'opérateurs arithmétiques standards tels que ">" et "<=". Cela ne fonctionne que pour les valeurs qui sont supposées être des entiers.
size(x) Renvoie la longueur de la chaîne x.
x.urlDecode() Renvoie la valeur décodée par l'URL de x. Les séquences de caractères au format %## sont remplacées par des équivalents non-ASCII, et + par une espace. Les encodages non valides sont renvoyés tels quels.
x.urlDecodeUni() Renvoie la valeur décodée par l'URL de x. En plus de urlDecode(), cette fonction gère également les séquences de caractères Unicode au format %u###. Les encodages non valides sont renvoyés tels quels.
x.utf8ToUnicode() Renvoie la représentation Unicode en minuscules d'un x encodé en UTF-8.

Exemples d'expressions

Pour chacune de ces expressions, l'action entreprise varie selon que l'expression est incluse dans une règle de refus ou d'autorisation.

Autoriser ou refuser l'accès en fonction d'une plage d'adresses IP en IPv4 ou IPv6

  • L'expression suivante correspond aux requêtes provenant de la plage d'adresses IP 198.51.100.0/24 :

    inIpRange(origin.ip, '198.51.100.0/24')
    
  • L'expression suivante correspond aux requêtes provenant de la plage d'adresses IP 2001:db8::/32 :

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

Autoriser ou refuser l'accès en fonction d'une plage d'adresses IP client personnalisée derrière un proxy en amont

Si vous avez configuré l'opérateur origin.user_ip, vous pouvez effectuer une correspondance en fonction des valeurs d'en-tête que vous avez spécifiées dans votre champ advancedOptionsConfig.userIpRequestHeaders[].

  • L'expression suivante correspond aux requêtes provenant de la plage d'adresses IP 192.0.2.0/24:

    inIpRange(origin.user_ip, '192.0.2.0/24')
    
  • L'expression suivante correspond aux requêtes provenant de la plage d'adresses IP 2001:db8::/32:

    inIpRange(origin.user_ip, '2001:db8::/32')
    
  • L'expression suivante correspond aux requêtes qui présentent un cookie contenant 80=BLAH :

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

Autoriser ou refuser le trafic avec un en-tête referer non vide

  • L'expression suivante correspond aux requêtes qui ont un en-tête referer non vide :

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

Autoriser ou refuser le trafic en fonction de l'URL de l'hôte dans l'en-tête

  • L'expression suivante correspond aux requêtes adressées à une URL spécifique :

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

Autoriser ou refuser le trafic provenant d'une région spécifique

Si votre application Web n'est pas disponible dans la région AU, toutes les requêtes provenant de cette région doivent être bloquées.

  • Dans une règle de refus, utilisez l'expression suivante, qui correspond aux requêtes de la région AU :

    origin.region_code == 'AU'
    

Si votre application Web est exclusivement disponible dans la région AU, les requêtes provenant de toutes les autres régions doivent être bloquées.

  • Dans une règle de refus, utilisez l'expression suivante pour faire correspondre les requêtes de toutes les régions autres que la région AU :

    origin.region_code != 'AU'
    

Les codes de région sont basés sur les codes ISO 3166-1 alpha-2. Dans certains cas, une région correspond à un pays, mais ce n'est pas toujours le cas. Par exemple, le code US comprend tous les États des États-Unis, un district et six zones périphériques.

Autoriser ou refuser le trafic provenant d'un numéro ASN spécifique

Si votre application Web doit être bloquée pour les clients desservis par un opérateur réseau spécifique, vous pouvez utiliser le numéro ASN de l'opérateur réseau à bloquer.

  • Dans une règle de refus, utilisez l'expression suivante, qui identifie les requêtes provenant d'un numéro ASN spécifique :

    origin.asn == 123
    

Si votre application Web doit être exclusivement disponible pour les clients situés derrière un opérateur réseau spécifique, les requêtes de tous les autres opérateurs réseau doivent être bloquées.

  • Dans une règle de refus, utilisez l'expression suivante, qui identifie tous les autres opérateurs réseau autres que celui que vous souhaitez autoriser:

    origin.asn != 123
    

Expressions multiples

Pour inclure plusieurs conditions dans une seule règle, combinez plusieurs sous-expressions.

  • Dans l'exemple suivant, les requêtes provenant de 1.2.3.0/24 (comme vos testeurs alpha) dans la région AU correspondent à l'expression suivante :

    origin.region_code == "AU" && inIpRange(origin.ip, '1.2.3.0/24')
    
  • L'expression suivante correspond aux requêtes provenant de 1.2.3.4 où un en-tête user-agent contient la chaîne WordPress :

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

Autoriser ou refuser le trafic pour un URI de requête qui correspond à une expression régulière

  • L'expression suivante correspond aux requêtes dont l'URI contient la chaîne example_path :

    request.path.matches('/example_path/')
    
  • L'expression suivante correspond aux requêtes dont le champ d'en-tête User-Agent contient Chrome :

    request.headers['user-agent'].matches('Chrome')
    
  • L'expression suivante montre une correspondance non sensible à la casse pour l'en-tête User-Agent contenant wordpress. Elle correspond à User-Agent:WordPress/605.1.15, User-Agent:wordPress et d'autres variantes de wordpress :

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

Autoriser ou refuser le trafic contenant une valeur décodée en base64 spécifique

  • L'expression suivante correspond aux requêtes qui ont la valeur décodée en base64 myValue pour l'en-tête user-id :

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

Autoriser ou refuser le trafic contenant une valeur de chaîne d'une longueur spécifique

  • L'expression suivante correspond aux requêtes dont l'URL est plus longue que 10 caractères:

    size(request.path) > 10
    
  • L'expression suivante correspond aux requêtes dont la longueur de l'en-tête x-data est supérieure ou égale à 1 024 caractères:

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

Autoriser ou refuser le trafic dont le corps HTTP contient un en-tête content-length nul

  • L'expression suivante correspond aux requêtes dont le corps HTTP contient un en-tête content-length nul :

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

Autoriser ou refuser le trafic contenant une valeur encodée sous forme d'une URL spécifique

  • L'expression suivante correspond aux requêtes qui présentent une valeur de cookie contenant %3c:

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

Autoriser ou refuser le trafic contenant une valeur de chaîne Unicode encodée sous forme d'une URL spécifique

  • L'expression suivante correspond aux requêtes dont la valeur de cookie est égale à Match%2BValue ou Match%u002BValue:

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

Autoriser ou refuser le trafic contenant une chaîne Unicode spécifique d'un texte UTF-8

  • L'expression suivante correspond aux requêtes dont la valeur de cookie est égale à ¬:

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

Autoriser ou refuser le trafic en fonction d'une empreinte JA3 connue

  • L'expression suivante correspond aux requêtes dont l'empreinte JA3 est égale à e7d705a3286e19ea42f587b344ee6865:

    origin.tls_ja3_fingerprint == 'e7d705a3286e19ea42f587b344ee6865'
    

Autoriser ou refuser le trafic en fonction d'une liste d'empreintes JA3

  • L'expression suivante correspond aux requêtes dont l'empreinte JA3 est égale à l'une des empreintes JA3 suivantes:

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

Règles WAF préconfigurées

Les règles WAF préconfigurées utilisent des signatures statiques préconfigurées, des expressions régulières ou les deux pour mettre en correspondance le corps POST HTTP, les en-têtes de requête HTTP et les paramètres de requête. Les règles WAF préconfigurées disponibles sont basées sur l'ensemble de règles de base OWASP ModSecurity version 3.3. Google Cloud Armor fournit plusieurs règles WAF préconfigurées. Pour obtenir la liste complète des règles WAF préconfigurées, consultez la présentation des règles WAF préconfigurées de Google Cloud Armor.

Pour répertorier toutes les règles WAF préconfigurées disponibles, consultez la section Répertorier les règles WAF préconfigurées disponibles.

Pour plus d'informations sur les règles WAF préconfigurées, consultez le cas d'utilisation Atténuer les attaques de couche d'application à l'aide de règles WAF préconfigurées.

Noms des règles WAF préconfigurées

Les noms des règles WAF préconfigurées suivent le format <attack category>-<ModSecurity CRS version>-<version field>. La catégorie d'attaque spécifie le type d'attaques contre lesquelles vous souhaitez vous protéger, comme xss (script intersites) ou sqli (injection SQL).

Les champs de version compatibles sont stable et canary. Les ajouts et changements effectués dans les règles sont d'abord publiés dans la version canary. Lorsque des ajouts et des changements sont considérés comme sûrs et stables, ils sont promus vers la version stable.

ID des membres de la règle WAF préconfigurée

Une règle WAF préconfigurée contient plusieurs expressions, chacune avec sa signature. Par exemple, la règle WAF préconfigurée xss-v33-stable inclut une expression appelée owasp-crs-v030301-id941100-xss, qui correspond à l'ID de règle id941100 pour la version 3.3. Vous pouvez utiliser les signatures pour empêcher l'utilisation d'expressions spécifiques, ce qui est utile si une expression particulière déclenche systématiquement un faux positif. Pour plus d'informations, consultez les informations de dépannage concernant les faux positifs.

Pour plus d'informations sur l'ensemble de règles de base et l'ajustement à différents niveaux de sensibilité, consultez la page Ajuster les règles WAF Google Cloud Armor.

Opérateur pour les règles WAF préconfigurées

Expressions Description
evaluatePreconfiguredWaf(string, MAP<string, dyn>) Renvoie "true" si l'une des signatures WAF figurant dans l'ensemble de règles WAF spécifié renvoie "true". Le premier argument est le nom de l'ensemble de règles du WAF, par exemple xss-v33-stable. Le deuxième argument (facultatif) est un mappage dans lequel la clé est une chaîne et la valeur est typée dynamiquement en fonction de la clé. L'objectif de cet argument est d'affiner les signatures WAF évaluées. Les clés acceptées sont les suivantes :
  • "sensitivity" : correspond au niveau de paranoïa de règles de base ModSecurity, qui comprend quatre niveaux, compris entre 1 et 4. Sa valeur est un entier avec une plage valide comprise entre 0 et 4. Notez que 0 est réservé en tant que valeur valide lorsqu'il est utilisé en combinaison avec "opt_in_rule_ids" (décrit plus loin). Lorsque vous spécifiez une sensibilité de x (x >= 1), toutes les signatures WAF associées à une valeur de sensibilité comprise entre 1 et x sont évaluées. En cas d'omission, la valeur 4 est utilisée comme valeur de sensibilité.
  • "opt_out_rule_ids" : signatures WAF (représentées par des ID de règle) à désactiver de l'évaluation, où l'ensemble de base est déterminé par la valeur de sensibilité. Sa valeur est une liste de chaînes. Le nombre maximal d'ID de règle autorisé est de 128.
  • "opt_in_rule_ids" : signatures WAF (représentées par des ID de règle) à activer pour l'évaluation, où l'ensemble de base est vide. Sa valeur est une liste de chaînes. Le nombre maximal d'ID de règle autorisé est de 128. Lorsque vous utilisez cette option, une sensibilité ("sensitivity") à 0 doit être spécifiée.

Les clés "opt_out_rule_ids" et "opt_in_rule_ids" s'excluent mutuellement. Vous pouvez choisir d'utiliser "opt_in_rule_ids" si vous souhaitez examiner et activer manuellement les nouvelles signatures WAF qui sont ajoutées ultérieurement à un ensemble de règles existant.

evaluatePreconfiguredExpr(string, LIST)

Renvoie "true" si l'une des expressions figurant dans la règle WAF préconfigurée spécifiée renvoie "true".

Le premier argument est le nom de la règle WAF préconfigurée, par exemple xss-stable. Le deuxième argument (facultatif) est une liste d'ID sous forme de chaînes séparées par des virgules, qui doivent être exclues de l'évaluation. La liste d'exclusion est utile lorsqu'un membre donné de la règle WAF préconfigurée déclenche un faux positif.

Exemples de règles WAF préconfigurées

  • L'expression suivante utilise la règle WAF préconfigurée xss-v33-stable pour atténuer les attaques XSS :

    evaluatePreconfiguredExpr('xss-v33-stable')
    
  • L'expression suivante utilise toutes les expressions de la règle WAF préconfigurée xss-v33-stable, à l'exception des ID membres 941100 et 941110 :

    evaluatePreconfiguredExpr('xss-v33-stable', ['owasp-crs-v030301-id941100-xss',
    'owasp-crs-v030301-id941110-xss'])
    
  • L'expression suivante utilise une règle WAF préconfigurée pour atténuer les attaques SQLi à partir de la plage d'adresses IP 198.51.100.0/24 :

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

Étapes suivantes