カスタムルール言語属性の構成

各 Google Cloud Armor セキュリティ ポリシー ルールには、優先度、一致条件、アクションがあります。Google Cloud Armor は、リクエストに一致する最も優先度の高いルールのアクションを実行します。同じ一致条件であっても、優先度の最も高い一致条件よりも優先度の低いルールは評価されません。

各セキュリティ ポリシー ルールは 2 種類の一致条件をサポートします。

  • 基本一致条件。IP アドレスまたは IP アドレス範囲のリストで構成されます。 基本的な一致条件は、Google Cloud CLI を使用してルールを作成するときに --src-ip-ranges フラグを使用して定義します。
  • 受信リクエストのさまざまな属性と一致する可能性がある最大 5 つのサブ式を含む式で構成される、詳細一致条件。Google Cloud CLI を使用してルールを作成する場合は、--expression フラグを使用して高度な一致条件を定義します。

このページでは、高度な一致条件と、セキュリティ ポリシー ルールで高度な一致条件の式を記述するために使用する Google Cloud Armor のカスタムルール言語について説明します。Google Cloud Armor カスタムルール言語は Common Expression Language(CEL)のサブセットです。Google Cloud Armor カスタムルール言語で記述される式には、2 つのコンポーネントが必要です。

  • 属性: 検査するデータ
  • オペレーション: データの使用方法

たとえば、次の式では、演算 inIpRange() で属性 origin.ip9.9.9.0/24 が使用されています。この場合、origin.ip9.9.9.0/24 の IP アドレス範囲に含まれている場合、式は true を返します。

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

前述した式の例がソース IP アドレスに一致していても、Google Cloud Armor セキュリティ ポリシー ルールを使用する場合、ルールは割り当ての観点から、高度な一致条件を持つ一致条件とみなされます。詳細については、Google Cloud Armor の割り当てと上限をご覧ください。

属性

属性は、送信元 IP アドレスやリクエストされた URL パスなど、受信リクエストからの情報を表します。

フィールド タイプ フィールドの説明
origin.ip 文字列 リクエストの送信元 IP アドレス。
origin.user_ip 文字列 送信元クライアントの IP アドレス。アップストリーム プロキシによってHTTP-HEADER に含まれています。この属性を使用する前に、セキュリティ ポリシーの advancedOptionsConfig フィールドで userIpRequestHeaders[] オプションを構成して、True-Client-IPX-Forwarded-ForX-Real-IP などのソースに一致させる必要があります。

userIpRequestHeaders[] オプションを構成しない場合、構成されたヘッダーに無効な IP アドレス値が含まれている場合、または構成されたヘッダーが存在しない場合は、origin.user_ip はデフォルトで origin.ip になります。詳細については、securityPolicy リソース リファレンスをご覧ください。

origin.tls_ja3_fingerprint 文字列 JA3 TLS / SSL フィンガープリント(クライアントが HTTPSHTTP/2HTTP/3 を使用して接続している場合)。使用できない場合、空の文字列が返されます。
request.headers 地図 HTTP リクエスト ヘッダーの文字列間マップヘッダーに複数の値が含まれている場合、このマップの値はヘッダーのすべての値のカンマ区切り文字列になります。このマップのキーはすべて小文字です。外部アプリケーション ロードバランサによって受け入れられるすべてのヘッダーが検査され、同じヘッダー制限が適用されます。

最初に has()has(request.headers['header-key']) && request.headers['header-key'] != 'header-value' など)を使用して使用可能かどうかを確認することをおすすめします。

request.method 文字列 GETPOST などの HTTP リクエスト メソッド。
request.path 文字列 リクエストした HTTP URL パス。
request.scheme 文字列 httphttps などの HTTP URL スキーム。この属性の値はすべて小文字です。
request.query 文字列 HTTP リクエストの第 1 行に現れるような、name1=value&name2=value2 形式の HTTP URL クエリ。デコードは行われません。
origin.region_code 文字列 送信元 IP に関連付けられた Unicode の国コード(US など)。ISO 3166-1 alpha 2 の国コードや地域コードを使用するルールまたは式を作成する場合、Google Cloud Armor は各コードを個別に処理します。Google Cloud Armor のルールと式では、これらの地域コードを明示的に使用して、リクエストを許可または拒否します。

詳細については、Unicode 技術標準の unicode_region_subtag をご覧ください。

origin.asn 整数 送信元 IP アドレスに関連付けられている自律システム番号(ASN)グローバルに一意の ASN は、送信元 IP アドレスを含む IP アドレス接頭辞をサポートするネットワーク事業者に基づいて決定されます。

reCAPTCHA の属性

このセクションでは、reCAPTCHA トークンまたは除外 Cookie にのみ適用される属性を示します。評価対象の reCAPTCHA トークンまたは除外 Cookie が利用できないか、次のいずれかの理由で無効な場合、これらの属性に基づくサブ式は false を返します。

  • トークンが不正な形式で、デコードできません。
  • トークンに無効な属性が含まれています。たとえば、トークンが、ルールに関連付けられた reCAPTCHA キーと一致しない reCAPTCHA キーを使用して生成された場合などです。
  • トークンの有効期限が切れています。
フィールド タイプ フィールドの説明
token.recaptcha_exemption.valid bool 有効な reCAPTCHA 除外 Cookie の存在。

アクション トークンの属性

フィールド タイプ フィールドの説明
token.recaptcha_action.score float reCAPTCHA アクション トークンからのスコア。有効なスコアの範囲は 0.01.0 で、0.0 は不正なユーザー、1.0 は正当なユーザーです。
token.recaptcha_action.captcha_status string reCAPTCHA アクション トークンのキャプチャ ステータス。有効なステータスは NONEPASS、または FAIL です。NONE は、reCAPTCHA 評価中にチャレンジがまったく発生しなかった場合を意味します。この場合、アクション トークンに captcha フィールドはありません。
token.recaptcha_action.action string reCAPTCHA Enterprise トークンのアクション名(最大 100 文字)。アクション名をご覧ください。
token.recaptcha_action.valid bool 有効な reCAPTCHA アクション トークンがある。

セッション トークンの属性

フィールド タイプ フィールドの説明
token.recaptcha_session.score float reCAPTCHA Enterprise トークンからのスコア。有効なスコアの範囲は 0.01.0 で、0.0 は不正なユーザー、1.0 は正当なユーザーです。
token.recaptcha_session.valid bool 有効な reCAPTCHA セッション トークンの存在。

運用

次の表では、ルールの式を定義するために、属性(xyk で表現)と一緒に使用できる演算子について説明します。

説明
x == "foo" x が指定した定数文字列リテラルと等しい場合、true を返します。x
x == R"fo'o" x がエスケープ シーケンスを解釈しない所定の生文字列リテラルと等しい場合、true を返します。x生文字列リテラルは、文字列自体がエスケープ シーケンス文字を使用する必要がある文字列を表現するのに便利です。
x == y X が Y と等しい場合、true を返します。
x != y X が Y と等しくない場合、true を返します。
x + y 連結された文字列 xy を返します。
x && y x と y の両方が true の場合、true を返します。
x || y x、y、または両方が true の場合、true を返します。
!x ブール値 x が false の場合は true を返し、ブール値 x が true の場合は false を返します。
x.contains(y) 文字列 x に部分文字列 y が含まれている場合、true を返します。
x.startsWith(y) 文字列 x が部分文字列 y で始まる場合、true を返します。
x.endsWith(y) 文字列 x が部分文字列 y で終わる場合、true を返します。
x.matches(y) 文字列 x が指定の RE2 パターン y と部分的に一致する場合、true を返します。RE2 パターンは、Unicode 機能を無効にする RE2::Latin1 オプションを使用してコンパイルされます。
inIpRange(x, y) IP アドレス x が IP 範囲 y に含まれている場合、true を返します。IPv6 アドレスのサブネット マスクは /64 以下にしてください。
x.lower() 文字列 x の小文字の値を返します。x
x.upper() 文字列 x の大文字の値を返します。x
x.base64Decode() Base64 でデコードされた x の値を返します。文字 _ - は、最初に / + にそれぞれ置き換えられます。xx が有効な base64 値でない場合、""(空の文字列)を返します。x
has(m['k']) キー k がマップ m で使用可能な場合、true を返します。
m['k'] k が使用可能な場合、文字列間マップ m のキー k の値を返します。使用可能でない場合は、エラーを返します。最初に "has(m['k'])==true" を使用して使用可能かどうかを確認することをおすすめします。
int(x) x の文字列の結果を int 型に変換します。x変換後は、> や <= などの標準の算術演算子を使用して整数の比較が行えます。これは、文字列が整数とみなされる場合に限り機能します。
size(x) 文字列 x の長さを返します。
x.urlDecode() URL デコードされた x の値を返します。%## 形式の文字シーケンスは ASCII 以外の同等のものに置き換えられ、+ はスペースに置き換えられます。無効なエンコードはそのまま返されます。
x.urlDecodeUni() URL デコードされた x の値を返します。urlDecode() に加えて、これは %u### 形式の Unicode 文字シーケンスも処理します。無効なエンコードはそのまま返されます。
x.utf8ToUnicode() UTF-8 でエンコードされた x小文字の Unicode 表現を返します。

式の例

以降の各式は、その式が拒否ルールに含まれるか、許可ルールに含まれるかによってアクションが変わります。

IPv4 または IPv6 の IP アドレス範囲に基づいてアクセスを許可または拒否する

  • 次の式は、198.51.100.0/24 IP アドレス範囲からのリクエストと一致します。

    inIpRange(origin.ip, '198.51.100.0/24')
    
  • 次の式は、2001:db8::/32 IP アドレス範囲からのリクエストと一致します。

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

アップストリーム プロキシの背後にあるカスタム クライアント IP アドレス範囲に基づいてアクセスを許可または拒否する

origin.user_ip オペレーターをすでに構成している場合は、advancedOptionsConfig.userIpRequestHeaders[] フィールドで指定したヘッダーの値に基づいて照合できます。

  • 次の式は、192.0.2.0/24 IP アドレス範囲から発信されたリクエストと一致します。

    inIpRange(origin.user_ip, '192.0.2.0/24')
    
  • 次の式は、2001:db8::/32 IP アドレス範囲から発信されたリクエストと一致します。

    inIpRange(origin.user_ip, '2001:db8::/32')
    
  • 次の式は、80=BLAH を含む Cookie を持つリクエストと一致します。

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

空でない referer ヘッダーを使用してトラフィックを許可または拒否する

  • 次の式は、空ではない referer ヘッダーを持つリクエストと一致します。

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

ヘッダー内のホスト URL に基づいてトラフィックを許可または拒否する

  • 次の式は、特定の URL へのリクエストと一致します。

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

特定のリージョンからのトラフィックを許可またはブロックする

AU リージョンでウェブ アプリケーションが利用できない場合は、そのリージョンからのリクエストをすべてブロックする必要があります。

  • 拒否ルールで次の式を使用します。これは、AU リージョンからのリクエストを照合します。

    origin.region_code == 'AU'
    

ウェブ アプリケーションが AU リージョンでのみ利用可能である場合、他のリージョンからのリクエストもブロックする必要があります。

  • 拒否ルールで次の式を使用します。これは、AU リージョン以外のすべてのリージョンからのリクエストを照合します。

    origin.region_code != 'AU'
    

リージョン コードは、ISO 3166-1 alpha 2 コードに基づいています。1 つのリージョンは 1 つの国に対応する場合がありますが、必ずしもそうならない場合もあります。たとえば、US コードには米国のすべての州、1 つの特別区、6 つの海外領土が含まれます。

特定の ASN からのトラフィックを許可またはブロックする

特定のネットワーク事業者によるサービスを受けるユーザーに対してウェブ アプリケーションをブロックする必要がある場合は、ネットワーク事業者の ASN 番号を使用するとブロックできます。

  • 拒否ルールで次の式を使用します。これは、特定の ASN からのリクエストに一致します。

    origin.asn == 123
    

また、ウェブ アプリケーションを、特定のネットワーク事業者のユーザーのみが使用できるようにするには、他のすべてのネットワーク事業者からのリクエストをブロックする必要があります。

  • 拒否ルールで次の式を使用します。これは、許可するネットワーク事業者以外のすべてのネットワーク事業者に一致します。

    origin.asn != 123
    

複数の式

1 つのルールに複数の条件を含めるには、複数のサブ式を組み合わせます。

  • 次の例では、AU リージョンの 1.2.3.0/24(アルファ テスターなど)からのリクエストが次の式と一致します。

    origin.region_code == "AU" && inIpRange(origin.ip, '1.2.3.0/24')
    
  • 次の式は、ユーザー エージェントに文字列 WordPress が含まれている 1.2.3.4 からのリクエストに一致します。

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

正規表現と一致するリクエスト URI のトラフィックを許可または拒否する

  • 次の式は、URI に文字列 example_path を含むリクエストと一致します。

    request.path.matches('/example_path/')
    
  • 次の式は、User-Agent ヘッダー フィールドに Chrome が含まれるリクエストと一致します。

    request.headers['user-agent'].matches('Chrome')
    
  • 次の式は、wordpress を含む User-Agent ヘッダーで大文字と小文字を区別しない一致を示します。これは、User-Agent:WordPress/605.1.15User-Agent:wordPress、その他の wordpress のパターンと一致します。

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

特定の base64 デコード値を含むトラフィックを許可または拒否する

  • 次の式は、user-id ヘッダー用の Base64 でデコードされた myValue の値を含むリクエストと一致します。

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

特定の長さの文字列値を含むトラフィックを許可または拒否する

  • 次の式は、URL の長さが 10 文字を超えるリクエストと一致します。

    size(request.path) > 10
    
  • 次の式は、ヘッダー x-data の長さが 1,024 文字以上のリクエストと一致します。

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

HTTP 本文で content-length がゼロのトラフィックを許可または拒否する

  • 次の式は、HTTP 本文で content-length がゼロのリクエストに一致します。

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

特定の URL エンコード値を含むトラフィックを許可または拒否する

  • 次の式は、%3c を含む Cookie 値を持つリクエストと一致します。

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

Unicode 文字列の特定の URL エンコード値を含むトラフィックを許可または拒否する

  • 次の式は、Cookie 値が Match%2BValue または Match%u002BValue と等しいリクエストと一致します。

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

UTF-8 テキストの特定の Unicode 文字列を含むトラフィックを許可または拒否する

  • 次の式は、Cookie 値が ¬ と等しいリクエストと一致します。

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

既知の JA3 フィンガープリントに基づいてトラフィックを許可または拒否する

  • 次の式は、JA3 フィンガープリントが e7d705a3286e19ea42f587b344ee6865 と等しいリクエストと一致します。

    origin.tls_ja3_fingerprint == 'e7d705a3286e19ea42f587b344ee6865'
    

JA3 フィンガープリントのリストに基づくトラフィックを許可または拒否します。

  • 次の式は、次の JA3 フィンガープリントのいずれかと等しい JA3 フィンガープリントがあるリクエストと一致します。

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

事前構成 WAF ルール

事前構成 WAF ルールでは、事前構成された静的シグネチャ、正規表現、またはその両方を使用して HTTP POST 本文、HTTP リクエスト ヘッダーとクエリ パラメータを照合します。使用可能な事前構成 WAF ルールは、OWASP Modsecurity Core Rule Set バージョン 3.3 に基づいています。Google Cloud Armor には、事前定義 WAF ルールがいくつか用意されています。事前構成 WAF ルールの一覧については、Google Cloud Armor の事前構成 WAF ルールの概要をご覧ください。

使用可能なすべての事前構成 WAF ルールを一覧表示するには、使用可能な事前構成 WAF ルールを一覧表示するをご覧ください。

事前構成 WAF ルールの詳細については、使用例: 事前構成 WAF ルールを使用してアプリケーション レイヤ攻撃を軽減するをご覧ください。

事前構成 WAF ルールの名前

事前構成 WAF ルール名の形式は <attack category>-<ModSecurity CRS version>-<version field> です。attack category には、xss(クロスサイト スクリプティング)や sqli(SQL インジェクション)など、防御対象となる攻撃タイプを指定します。

サポートされているバージョン フィールドは stablecanary です。ルールへの追加と変更は、最初に canary バージョンでリリースされます。追加と変更が安全で安定しているとみなされると、stable バージョンに昇格します。

事前構成 WAF ルールのメンバー ID

事前構成 WAF ルールには、それぞれシグネチャを持つ複数の式が含まれています。たとえば、事前構成 WAF ルール xss-v33-stable には、owasp-crs-v030301-id941100-xss という式が含まれています。これは、バージョン 3.3 のルール ID id941100 に対応します。シグネチャを使用して、特定の式が使用されないように除外できます。これは、特定の式が一貫して誤検出をトリガーする場合に便利です。詳しくは、誤検出のトラブルシューティング情報をご覧ください。

コアルール セットとさまざまな感度レベルでの調整の詳細については、Google Cloud Armor WAF ルールのチューニングをご覧ください。

事前構成 WAF ルールのオペレーター

説明
evaluatePreconfiguredWaf(string, MAP<string, dyn>) 指定された WAF ルールセット内の WAF シグネチャのいずれかが true を返す場合、true を返します。最初の引数は、WAF ルールセットの名前(xss-v33-stable など)です。2 番目の引数(省略可)は、キーと値のマッピングです。キーは文字列です。値は、キーに応じて動的に設定されます。この引数は、評価する WAF シグネチャを微調整することを目的としています。使用できるキーは次のとおりです。
  • sensitivity: ModSecurity Core Rule Set のパラノアレベル(1~4 の 4 つのレベル)に対応します。この値は、0 から 4 までの有効な範囲を持つ整数です。0 は、opt_in_rule_ids(後述)と組み合わせて使用すると有効な値として予約されます。x の感度を指定すると(x >= 1)、感度値が 1~x の関連する WAF シグネチャがすべて評価されます。省略した場合、感度値は 4 です。
  • opt_out_rule_ids: 評価からオプトアウトする WAF シグネチャ(ルール ID で表します)。基本セットは感度の値によって決まります。値は文字列のリストです。指定できるルール ID の最大数は 128 です。
  • opt_in_rule_ids: 評価セットにオプトインする WAF シグネチャ(ルール ID で表します)。基本セットは空です。値は文字列のリストです。指定できるルール ID の最大数は 128 です。これを使用する場合は、0 の sensitivity を指定する必要があります。

キー opt_out_rule_ids と opt_in_rule_ids は相互に排他的です。既存のルールセットに新たに追加された WAF シグネチャを確認して手動で有効にする場合は、opt_in_rule_ids を使用できます。

evaluatePreconfiguredExpr(string, LIST)

指定された事前構成 WAF ルール内の式のいずれかが true を返す場合、true を返します。

最初の引数は、事前構成 WAF ルールの名前です(xss-stable など)。2 番目の引数(省略可)は、評価から除外される必要がある ID のカンマ区切りの文字列リストです。除外リストは、事前構成 WAF ルールの特定のメンバーが誤検出をトリガーする場合に便利です。

事前構成 WAF ルールの例

  • 次の式は、xss-v33-stable 事前構成 WAF ルールを使用して XSS 攻撃を軽減します。

    evaluatePreconfiguredExpr('xss-v33-stable')
    
  • 次の式は、メンバー ID 941100941110 を除いて、xss-v33-stable 事前構成 WAF ルールのすべての式を使用します。

    evaluatePreconfiguredExpr('xss-v33-stable', ['owasp-crs-v030301-id941100-xss',
    'owasp-crs-v030301-id941110-xss'])
    
  • 次の式は、事前構成 WAF ルールを使用して 198.51.100.0/24 IP アドレス範囲からの SQLi 攻撃を軽減します。

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

次のステップ