💂‍♂️

Google Cloud(GCP)でWAF導入 ~ Cloud Armorを使ったWAF構築方法

に公開

構築の流れ

Google Cloudでは、WAFは Google Cloud Armor (以下 Cloud Armorと呼びます)に含まれています。
Cloud Armorは複数の料金がありますが、初めから使える スタンダードでWAFを使うことができます。

まず、Cloud Armorで通信のルール(ポリシー)にWAFを設定します。
次に、Cloud Armorをロード バランシングに設定することで通信にWAFルールを適用することができます。

余談ですが、Cloud ArmorはWAF以外に特定のパスに通信できるIPを制限するなど様々なルールを適用することができます。
Cloud Armorに設定を変更すると、1分くらい(?)で通信に設定が反映されます。

Cloud ArmorでWAF設定

それは、Cloud ArmorでWAFのポリシーを作っていきましょう。

コンソール画面でCloud Armorのポリシーを開いてください

通信を制限するポリシーとして、WAFを設定します。
それ以外の、IP制限などもまとめて設定することが可能です。

ポリシーを作る

「ポリシー生成」を開きます


適当な名前でポリシーを作成します。
ここでは、「デフォルトのルール アクション」を通過できるようにしています。
これで、一旦ポリシーを作成します。

WAFルールを追加する

適用できるWAFルールはここに書かれています。
https://cloud.google.com/armor/docs/waf-rules?hl=ja


用意されたWAFルール

  • SQL インジェクション
  • クロスサイト スクリプティング
  • ローカル ファイル インクルード
  • リモートコード実行
  • メソッドの適用
  • スキャナ検出
  • プロトコル攻撃
  • PHP インジェクション攻撃
  • セッション修正攻撃
  • Java 攻撃
  • NodeJS 攻撃
  • CVE とその他の脆弱性
  • JSON 形式のコンテンツの SQLi の脆弱性

13個のルールが存在します。

この中から、必要なものだけを設定することができます。
例えば、NodeJSを使っていなのに「NodeJS 攻撃」から防御するルール入れたりする必要はありません。

そして、この項目はルールの「大項目」で実際のルールは、もう少し細かく分かれています。

詳細ルールと感度レベル

一例として、「Java 攻撃」のルールを見ます。


表のように「Java 攻撃」のルールは複数のルールがセットになっています。
また、通信をどこまで攻撃とみなすか感度レベルも記載されています。
感度レベルが高いほどセキュリティは高まりますが、通常の通信を攻撃だと誤検知するリスクも高まります。
状況に応じて適当なレベルを選択します。

ルールとしては、 で記載されている箇所を記載します。
例えば、「Java 攻撃」の感度レベル3だと

evaluatePreconfiguredWaf('java-v33-stable', {'sensitivity': 3})

感度レベルは指定された値以下のレベルが適用対象になります。
つまり、

  • 感度レベル3指定だと、3・2・1のルールを適用
  • 感度レベル2指定だと、2・1のルールを適用
  • 感度レベル1指定だと、1のルールを適用

「Java 攻撃」は感度レベル3にすることで、表にある全部のルールが適用さます。

また、感度レベルを指定し、特定ルールのみ除外することも可能です。

ポリシーにWAFルールを追加する

設定すべきWAFが決まったら、ポリシーに追加していきます。

さきほど追加したポリシーを開き


「ルールを追加」を開きます


  1. 「詳細に変更」
  2. 先ほどのWAFルールを入れます
  3. 通信を「拒否」していることを確認
  4. (普通は)優先度は小さめの数値にします(ここでは、千番台をWAFに振っています)

※優先度について:ルールは複数設定でき、優先度の数値が低いものから先にチェックされます。

設定したルールや優先度は後から変更できます。


「追加」ボタンを押すことで、ルールが追加されます。


ルールは複数追加できるので、同じ要領で他の攻撃への対策も追加していきます。


いくつかのWAFルールを追加した例です。

(何を追加するかは状況次第ですが)個人的には、よくある設定ファイル(例 .env)などをスキャンする攻撃を防ぐ「ローカル ファイル インクルード」は基本的にいれた方が良いと思います。
通信を見る限り、「ローカル ファイル インクルード」の攻撃頻度は高いです。

Cloud Armorをロード バランシングに追加

Cloud Armorをロード バランシングに追加することで、ポリシーに従って通信がフィルタリングされます。
ポリシーに追加されたWAFも適用されます。

ロード バランシングを開きます


Cloud Armorを導入したいロード バランシングを「編集」します。


「バックエンドの構成」からバックエンドを変更します


用意したCloud Armorのポリシーを選択します。
合わせて、しばらくの間は通信を監視できるように、通信ログの取得も行います。

設定を反映させることで、WAFを含むCloud Armorのポリシーが適用されます。
(反映には少し時間がかかります)

お疲れ様でした。

Cloud Armorのポリシーを調整する

実際に運用にするとWAFが必要な通信までブロックしてしまうことがあります。

通信のログを確認し、WAFがブロックを行ったか、ブロックしている場合は、どのルールがブロックしているかを確認しましょう。

ログを確認する

ログが集まっている「Logging」を開きます。

ログを絞り込む

Cloud Armorがブロックしたログを絞り込みましょう。

jsonPayload.enforcedSecurityPolicy.outcome="DENY

の項目で、絞り込みをかけてください。


絞り込まれた項目の中から、時間やURLをヒントに該当の通信を探してください。

通信をブロックしたルール

通信をブロックをしたルールは、
jsonPayload.enforcedSecurityPolicy.preconfiguredExprIdsの中にあります。

この例では、owasp-crs-v030301-id942100-sqliのルールにより通信をブロックしています。

ルールを除外する

ポリシーのルールが正常な通信を妨害していた場合、ポリシーからそのルールを除外しましょう。
上の例、owasp-crs-v030301-id942100-sqliをルールから除外してみましょう。

ルールの大項目を探す

owasp-crs-v030301-id942100-sqliの末尾が、sqliなので、「SQL インジェクション」用のsqli-v33-stableだとわかります。

念のため、ドキュメントを開いて確認してみましょう
https://cloud.google.com/armor/docs/waf-rules?hl=ja

項目を絞り込むと、「SQL インジェクション」のルールがヒットしました


ポリシーの変更

それでは、ポリシーを変更します。
Cloud Armorのポリシーを開きます。


ルールから、今回変更を行いたいsqli-v33-stableを探します。


ルールの記載は、ドキュメントに従います。
https://cloud.google.com/armor/docs/rule-tuning?hl=ja

opt_out_rule_idsに除外したいルールを記載します。

今回だと元の記載

変更前
evaluatePreconfiguredWaf(
  'sqli-v33-stable',
  {
    'sensitivity': 1
  }
)

変更後
evaluatePreconfiguredWaf(
  'sqli-v33-stable',
  {
    'sensitivity': 1,
    'opt_out_rule_ids': ['owasp-crs-v030301-id942100-sqli']
  }
)

実際に変更するとこの画像のようになります↓

この変更で、owasp-crs-v030301-id942100-sqliのみ除外されました。
変更後、1分くらい(?)で設定が反映されます。

なお、opt_out_rule_ids複数いれることで複数のルールを除外することができます。

複数除外する例
evaluatePreconfiguredWaf(
  'sqli-v33-stable',
  {
    'sensitivity': 1,
    'opt_out_rule_ids': ['owasp-crs-v030301-id942100-sqli', 'owasp-crs-v030301-id942140-sqli', 'owasp-crs-v030301-id942160-sqli']
  }
)

これで、WAF関係の基本的な運用は行えるかと思います。
お疲れ様でした!!

おまけ

WAF以外でCloud Armorがブロックしたとき

WAF以外のルールでCloud Armorがブロックしている場合、
jsonPayload.enforcedSecurityPolicy.priorityに優先度の番号が表示されます。

この例だと、Cloud Armorで「優先度」が9999で設定されているルールが通信をブロックしています。

そのようなログの見方は、こちらのドキュメントにまとめられています
https://cloud.google.com/armor/docs/request-logging?hl=ja

Discussion