各 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.ip
と 9.9.9.0/24
が使用されています。この場合、origin.ip
が 9.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-IP 、X-Forwarded-For 、X-Real-IP などのソースに一致させる必要があります。
|
origin.tls_ja3_fingerprint |
文字列 | JA3 TLS / SSL フィンガープリント(クライアントが HTTPS 、HTTP/2 、HTTP/3 を使用して接続している場合)。使用できない場合、空の文字列が返されます。 |
request.headers |
地図 | HTTP リクエスト ヘッダーの文字列間マップヘッダーに複数の値が含まれている場合、このマップの値はヘッダーのすべての値のカンマ区切り文字列になります。このマップのキーはすべて小文字です。外部アプリケーション ロードバランサによって受け入れられるすべてのヘッダーが検査され、同じヘッダー制限が適用されます。 最初に |
request.method |
文字列 | GET や POST などの HTTP リクエスト メソッド。 |
request.path |
文字列 | リクエストした HTTP URL パス。 |
request.scheme |
文字列 | http 、https などの 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 キーを使用して生成された場合などです。
- トークンの有効期限が切れています。
除外 Cookie の属性
項目 | タイプ | フィールドの説明 |
---|---|---|
token.recaptcha_exemption.valid |
bool |
有効な reCAPTCHA 除外 Cookie の存在。 |
アクション トークンの属性
項目 | タイプ | フィールドの説明 |
---|---|---|
token.recaptcha_action.score |
float |
reCAPTCHA アクション トークンからのスコア。有効なスコアの範囲は 0.0 ~ 1.0 で、0.0 は不正なユーザー、1.0 は正当なユーザーです。 |
token.recaptcha_action.captcha_status |
string |
reCAPTCHA アクション トークンのキャプチャ ステータス。有効なステータスは NONE 、PASS 、または 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.0 ~ 1.0 で、0.0 は不正なユーザー、1.0 は正当なユーザーです。 |
token.recaptcha_session.valid |
bool |
有効な reCAPTCHA セッション トークンの存在。 |
運用
次の表では、ルールの式を定義するために、属性(x
、y
、k
で表現)と一緒に使用できる演算子について説明します。
式 | 説明 |
---|---|
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 を返します。 |
x.lower() |
文字列 x の小文字の値を返します。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 型に変換します。変換後は、> や <= などの標準の算術演算子を使用して整数の比較が行えます。これは、文字列が整数とみなされる場合に限り機能します。 |
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')
特定の Cookie を持つトラフィックを許可または拒否する
次の式は、
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.15
、User-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 インジェクション)など、防御対象となる攻撃タイプを指定します。
サポートされているバージョン フィールドは stable
と canary
です。ルールへの追加と変更は、最初に 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 シグネチャを微調整することを目的としています。使用できるキーは次のとおりです。
キー opt_out_rule_ids と opt_in_rule_ids は相互に排他的です。既存のルールセットに新たに追加された WAF シグネチャを確認して手動で有効にする場合は、opt_in_rule_ids を使用できます。 |
evaluatePreconfiguredExpr(string, LIST) |
指定された事前構成 WAF ルール内の式のいずれかが true を返す場合、true を返します。 最初の引数は、事前構成 WAF ルールの名前です( |
事前構成 WAF ルールの例
次の式は、
xss-v33-stable
事前構成 WAF ルールを使用して XSS 攻撃を軽減します。evaluatePreconfiguredExpr('xss-v33-stable')
次の式は、メンバー ID
941100
と941110
を除いて、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')