Google Cloud Armor カスタムルールの言語リファレンス

Google Cloud Armor を使用すると、セキュリティ ポリシーで構成可能な一致条件とアクションを使用して優先順位付けされたルールを定義できます。ルールが効力を発するということは、受信リクエストの属性と一致するルールで、そのルールの優先度が最も高いルールである場合に、構成されているアクションが適用されることを意味します。

一致条件には、次の 2 種類があります。

  • 基本一致条件。IP アドレスまたは IP アドレス範囲のリストで構成されます。
  • 詳細一致条件。受信リクエストのさまざまな属性と一致する複数のサブ式を含む式で構成されます。

カスタムルール言語は、セキュリティ ポリシー ルールの詳細一致条件の式を記述するために使用されます。Google Cloud Armor カスタムルール言語は、Common Expression Language(CEL)の拡張版です。

式には次の 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 アドレスやリクエストされた URL パスなど、受信リクエストからの情報を表します。

フィールド フィールドの説明
origin.ip 文字列 リクエストの送信元 IP アドレス。
request.headers マップ HTTP リクエスト ヘッダーの文字列間マップヘッダーに複数の値が含まれている場合、このマップの値はヘッダーのすべての値のカンマ区切り文字列になります。このマップのキーはすべて小文字です。検査に使用できるのは、各ヘッダー値の最初の 16 KB のみです。16 KB を超えるヘッダー値は、Google Cloud ロードバランサの仕様に従って切り捨てられます。
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 アドレス接頭辞をサポートするネットワーク事業者に基づいて決定されます。
token.recaptcha.score 浮動小数点数 reCAPTCHA Enterprise トークンからのスコア。有効なスコアは [0.0, 1.0] の範囲内です。0.0 はボットの可能性が非常に高く、1.0 は人間である可能性が非常に高いといえます。
token.recaptcha.captcha_status 文字列 reCAPTCHA Enterprise トークンからのキャプチャ ステータス(例: NONEPASSFAIL)。NONE は、reCAPTCHA Enterprise の評価中に確認が発生せず、キャプチャ ステータスがトークンに存在しないことを意味します。
token.recaptcha.action 文字列 reCAPTCHA Enterprise トークンのアクション名(最大 100 文字)。アクション トークンでのみ使用できます。アクション名をご覧ください。

演算

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

説明
x == "foo" x が指定した定数文字列リテラルと等しい場合、true を返します。
x == R"fo'o" x がエスケープ シーケンスを解釈しない所定の生文字列リテラルと等しい場合、true を返します。生文字列リテラルは、文字列自体がエスケープ シーケンス文字を使用する必要がある文字列を表現するのに便利です。
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.upper() 文字列 x の大文字の値を返します。
x.base64Decode() Base64 でデコードされた x の値を返します。文字 _ - は、最初に / + にそれぞれ置き換えられます。x が有効な base64 値でない場合、""(空の文字列)を返します。
has(m['k']) キー k がマップ m で使用可能な場合、true を返します。
m['k'] k が使用可能な場合、文字列間マップ m のキー k の値を返します。使用可能でない場合は、エラーを返します。最初に "has(m['k'])==true" を使用して使用可能かどうかを確認することをおすすめします。
int(x) x の文字列の結果を int 型に変換します。変換後は、> や <= などの標準の算術演算子を使用して整数の比較が行えます。これは、文字列が整数とみなされる場合に限り機能します。

式の例

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

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

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

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

    inIpRange(origin.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'] != ""
    

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

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 に文字列 bad_path を含むリクエストと一致します。

    request.path.matches('/bad_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')
    

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

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

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

事前構成されたルール

事前構成されたルールでは、事前構成された静的シグネチャ、正規表現、またはその両方を使用して HTTP リクエスト ヘッダーとクエリ パラメータを照合します。利用可能な事前構成されたルールは、OWASP Modsecurity コアルール セット バージョン 3.0.2 に基づいています。Google Cloud Armor では、次の定義済みの式セットが用意されています。

  • xss-<version>: クロスサイト スクリプティング攻撃から保護します
  • sqli-<version>: SQL インジェクション攻撃から保護します
  • lfi-<version>: ローカル ファイル インクルージョン攻撃から保護します
  • rfi-<version>: リモート ファイル インクルージョン攻撃から保護します
  • rce-<version>: リモートコード実行攻撃から保護します

利用可能なすべての事前構成されたルールの一覧は、利用可能な事前構成済みルールの一覧表示をご覧ください。

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

式セット名

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

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

式セットのメンバー ID

式セットには複数の式が含まれ、それぞれに独自のコアルール セット(CRS)ID があります。たとえば、式セット xss-stable には、version 2.9.1 のルール ID 981136 に対応する owasp-crs-v020901-id981136-xss という式が含まれています。CRS ID を使用して、特定の式が使用されないように除外できます。これは、特定の式が一貫して誤検出をトリガーする場合に便利です。詳しくは、誤検出のトラブルシューティング情報をご覧ください。

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

事前構成されたルールの演算子

説明
evaluatePreconfiguredExpr(string, LIST)

指定された式セット内の式のいずれかが true を返す場合、true を返します。

1 番目の引数は、式セットの名前です(xss-stable など)。2 番目の引数(省略可)は、評価から除外される必要がある ID のカンマ区切りの文字列リストです。除外リストは、式セットの特定の式が誤検出をトリガーする場合に役立ちます。

事前構成されたルールの例

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

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

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

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

次のステップ