Azure Front Door の WAF ログに「Microsoft_DefaultRuleSet‑2.x‑BLOCKING‑EVALUATION‑949110 / Inbound Anomaly Score Exceeded」が大量に出て、正当なリクエストまでブロックされてしまうことがあります。この記事では、この 949110 が何者なのか、直接無効化できない理由、そして実際にどうやって誤検知を調査・バイパスすればよいかを、Kusto クエリ例と運用パターンを交えて詳しく解説します。
Azure Front Door WAF の 949110(Inbound Anomaly Score Exceeded)とは
まず押さえておきたいのは、949110 は単体で攻撃パターンを検知するルールではなく、「アノマリースコアが閾値を超えたこと」を知らせる評価用メタルールだという点です。Azure Front Door WAF の既定マネージドルールセット(Microsoft_DefaultRuleSet 2.x、以下 DRS 2.x)は OWASP ModSecurity Core Rule Set をベースにした アノマリースコア方式を採用しており、複数のルールの「合計スコア」が一定値を超えたときに 949110 が発火します。
公式ドキュメントでは、949110 について「Inbound Anomaly Score Exceeded(インバウンドアノマリースコアが閾値を超えた)」ことを示すルールであり、実際に危険な文字列やパターンを検知しているのは、別の下位ルールだと説明されています。
949110 の概要
| 項目 | 値 |
|---|---|
| ルール ID | 949110 |
| ルール名(例) | Microsoft_DefaultRuleSet-2.1-BLOCKING-EVALUATION-949110 |
| 説明 | Inbound Anomaly Score Exceeded(アノマリースコアが閾値を超過) |
| 役割 | 複数のルールのスコア合計が閾値以上になったことを通知するメタルール |
| 直接攻撃を検知するか | いいえ。実際の検知は SQLi / XSS などの下位ルールが行う |
| 単独で無効化可能か | 不可(仕様上の制約) |
DRS 2.x とアノマリースコア方式の復習
DRS 2.0 以降では、WAF は「一致したルールごとにスコアを加算し、その合計値が閾値以上になったらアクションを取る」という振る舞いをします。各ルールには以下のような重大度とスコア値が設定されています。
| 重大度 | アノマリースコア | イメージ |
|---|---|---|
| Critical | 5 | その 1 つだけでブロック候補になるレベル |
| Error | 4 | 重大な攻撃の疑い |
| Warning | 3 | 攻撃の可能性あり |
| Notice | 2 | 軽微な異常・注意レベル |
DRS 2.x では通常、合計スコアが 5 以上になるとアノマリールール(949110)が発火し、WAF ポリシーが Prevention(防御)モード かつアノマリースコアのアクションが Block の場合にリクエストがブロックされます。Detection(検出)モードの場合はログのみが記録され、リクエストは通過します。
例えば、次のようなケースでは 949110 が発火します。
- Warning(3 点)のルールが 2 つマッチ → 合計 6 点 ≥ 5 → 949110 がトリガーされる
- Critical(5 点)のルールが 1 つマッチ → 合計 5 点 → 949110 がトリガーされる
- Notice(2 点)のルールが 2 つ、Warning(3 点)が 1 つ → 合計 7 点 → 949110 がトリガーされる
つまり、949110 自体は「スコアが閾値を超えた事実」を通知しているだけなので、これだけを無効化しても根本原因(スコアを積み上げた下位ルール)は残り続けます。
949110 を「無効化」できない理由とリスク
結論:949110 は仕様上、直接無効化・除外・バイパスできない
Microsoft Q&A でも明言されている通り、949110 は DRS 2.x における「必須メタルール」であり、個別ルールのように無効化・除外(exclusion)・カスタムルールでのバイパスはできません。
- 949110 が発火するのは「別のルールのアノマリースコアが閾値を超えた結果」である
- そのため、無効化できたとしても「スコアがいくら積み上がっても最終判断をしない状態」になり、アノマリースコア方式が機能不全になる
- 公式見解としても「949110 を直接バイパスするのではなく、スコアを加算している個々のルールに対して除外や無効化、カスタムルールで対処するべき」とされています
これは実運用の感覚からしても妥当で、949110 を丸ごとオフにしてしまうと「複数の軽微な異常の組み合わせで検知できる攻撃」を見落とすことになります。例えば、単発では弱いシグナルでも、SQL インジェクションのパターンが複数のパラメーターで繰り返し検出されるようなケースです。
「949110 だけ除外したい」はなぜ危険なのか
よくある要望が「949110 だけを除外して、下位ルールはそのままにしたい」というものですが、これは IDS(侵入検知)としてはログだけ残し、実際のブロックは行わない 状態に近づいてしまいます。
- ログ上は「SQLi / XSS / RCE ルールが大量にヒットしている」ものの、最終的な 949110 が無効化されているためブロックが発生しない
- 攻撃的なトラフィックと、たまたま同じパターンを含む正当なリクエストを、WAF だけでは区別できなくなる
- 結果として、WAF を導入しているのに 実質的に重要な攻撃を止められない リスクが生じる
したがって、949110 によるブロックが問題になっている場合は、「949110 を消す」のではなく「スコアを引き上げている下位ルールを特定してチューニングする」のが正攻法になります。
正しい対処方針:加点した下位ルールを特定してチューニングする
事前準備:WAF 診断ログを有効化する
まずは Azure Front Door WAF のログが Log Analytics に出力されていることを確認します。Azure Portal では、Front Door プロファイルまたは WAF ポリシーの「診断設定」から FrontDoorWebApplicationFirewallLog / FrontdoorWebApplicationFirewallLog を有効化し、Log Analytics ワークスペースに送る設定を行います。
Front Door Standard/Premium の場合、Log Analytics テーブルは一般的に AzureDiagnostics で、以下のような列が利用できます。
| 列名(例) | 意味 |
|---|---|
| ResourceProvider | 通常「MICROSOFT.CDN」(Standard/Premium Front Door) |
| Category | WAF ログの場合「FrontDoorWebApplicationFirewallLog」など |
| rulename_s / ruleName_s | マッチした WAF ルール名(Microsoft_DefaultRuleSet-2.1-XXXX-ID) |
| action_s | Block / AnomalyScoring / Log などのアクション |
| trackingReference_s | 1 リクエストを一意に表す ID(X-Azure-Ref と対応) |
| details_s | マッチした変数名や値などの詳細 JSON |
Step 1:949110 でブロックされたリクエストを抽出
まずは、949110 によって Block されたログだけを抽出します。Microsoft Q&A で紹介されているクエリ例をベースに、次のような Kusto クエリがよく使われます。
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.CDN"
and Category == "FrontDoorWebApplicationFirewallLog"
and action_s == "Block"
and rulename_s == "Microsoft_DefaultRuleSet-2.1-BLOCKING-EVALUATION-949110"
このクエリで、949110 によってブロックされたイベント一覧が取得できます。ここで重要なのは trackingReference_s 列で、同じリクエストに関する他の WAF ログを紐づけるキーとして利用します。
Step 2:trackingReference ごとに下位ルールを追跡
次に、取得した trackingReference_s を使って、同じリクエストで発火したすべてのルールを追いかけます。
let TargetTrackingId = "ここに trackingReference_s の値";
AzureDiagnostics
| where trackingReference_s == TargetTrackingId
| where Category == "FrontDoorWebApplicationFirewallLog"
| project TimeGenerated, rulename_s, action_s, details_s
| order by TimeGenerated asc
このクエリのポイントは次の通りです。
action_s == "AnomalyScoring"の行が、「スコア加算対象の下位ルール」です- 最後に
rulename_s == "Microsoft_DefaultRuleSet-2.1-BLOCKING-EVALUATION-949110"かつaction_s == "Block"の行が 949110 です details_sを展開すると、どのパラメーターやヘッダー値がヒットしたかが分かります
このように 1 リクエスト単位で追いかけることで、「どのルールが何点ずつスコアを積み上げた結果、949110 に到達したのか」を確認できます。
Step 3:頻出する原因ルールを集計する
単発リクエストの調査だけでなく、どのルールが頻繁にアノマリースコアを加算しているかを集計しておくと、優先的にチューニングすべき対象が見えてきます。
AzureDiagnostics
| where Category == "FrontDoorWebApplicationFirewallLog"
| where action_s == "AnomalyScoring"
| summarize count() by rulename_s
| order by count_ desc
この結果から、例えば Microsoft_DefaultRuleSet-2.1-SQLI-942110 や Microsoft_DefaultRuleSet-2.1-XSS-941130 など、特定の SQLi / XSS ルールが突出している場合、そのルールを重点的に見直すべきだと判断できます。
Step 4:原因ルールへの具体的な対処パターン
原因となるルールが特定できたら、Azure WAF で取り得る代表的な対処は次の 3 パターンです。
| 対処方法 | 概要 | メリット | 注意点 |
|---|---|---|---|
| マネージドルールの無効化 / Log 化 | 特定のルールまたはルールグループのアクションを Log に変更、あるいは無効化する | 即効性が高く、誤検知がすぐに減る | 該当ルールがカバーしていた攻撃に対して防御力が落ちる可能性 |
| WAF 除外(Exclusion) | 特定のヘッダー / クエリ文字列 / ボディ項目などを、対象ルールから除外する | 対象パラメーターだけ検査を外すため、防御範囲を狭めずに済みやすい | 除外対象の切り取り方を誤ると、意図せず広い範囲が検査対象外になる |
| Custom Rule での条件付きバイパス | 特定のパス・クライアント IP・ヘッダーなどに対して、先に Allow / Bypass するカスタムルールを作成 | テスト環境や内部システムなど、限定されたトラフィックだけ DRS をスキップできる | 条件が広すぎると、本来守りたいパスまで丸ごと無防備になりうる |
特に Exclusion の活用は重要です。DRS では、ルールセット単位・ルールグループ単位・個別ルール単位で「このヘッダー(例:Authorization)は検査対象外にする」といった指定が行えます。一方で、949110 を Exclusion の対象にすることはできません。あくまで「スコアを積み上げた側」のルールに対して除外を設定する必要があります。
「Log が基本、一部だけ Block」にできるか?
AFD WAF(グローバル WAF)の制約
質問として多いのが、次のような要件です。
- DRS 2.x のルールは基本「Log」にして誤検知を観察したい
- ただし、十分に検証できた一部のルールだけは「Block」として本番適用したい
しかし、Azure Front Door(グローバル WAF)での DRS 2.1 において、ポータルや CLI から設定できるルールアクションは「Log」か「AnomalyScoring」のみで、個別ルールを直接「Block」にすることはできません。Block / Allow などのアクションが選べるのは、基本的に Application Gateway(リージョナル WAF)側のポリシーです。
そのため、「ルールセット全体を Log にしておき、一部のルールだけ Block に戻す」という構成は、AFD WAF ではサポートされていません。
代替案 1:AnomalyScoring を活用して「実質 Block 対象」を絞る
最も現実的な代替案は、DRS のアクションを AnomalyScoring にし、Block の対象となるルールを絞り込む方法です。
- WAF ポリシーを Prevention モードにする
- DRS 2.x の「アノマリースコアのアクション」を Block に設定する
- 誤検知が多いルールはアクションを Log に変更し、アノマリースコアに加算しない
- 重要なルールだけ AnomalyScoring を維持し、スコアが 5 以上になったときのみ 949110 でブロックさせる
この構成では、厳密には「特定ルールだけ Block」というより、「特定ルールだけがスコアを加算する」状態になります。一つの Critical ルール(5 点)がマッチすればそれだけでブロックされますし、複数の Warning(3 点)ルールが組み合わさって 5 点を超えれば同様にブロックされます。
代替案 2:用途別に WAF ポリシーを分割する
アプリケーション全体で同じポリシー設定を使うと、どうしても「一部のエンドポイントだけ誤検知が多く、そのせいでルールを甘くせざるを得ない」といった状況になりがちです。その場合は、用途ごとに WAF ポリシーを分け、FRD ルールやホスト名で使い分けるのが有効です。
- ポリシー A: 公開 Web サイト用 → DRS 2.x を AnomalyScoring + Block、PL2 ルールも一部有効化して防御を厚くする
- ポリシー B: パートナー向け API やバッチ用エンドポイント → 誤検知が多いルールは積極的に Log 化・除外し、必要に応じて Custom Rule で別途防御
Front Door では、ルートごとに異なる WAF ポリシーを紐づけることができるため、「/api/** は緩め、/app/** は厳しめ」といった切り分けが可能です。
代替案 3:Custom Rule で Block 条件を明示的に定義する
DRS 2.x の managed rule だけで要件を満たそうとすると制約が多い場合、Custom Rule を併用して Block したい条件だけ明示的に書く方法も検討できます。
- DRS 側は一旦「Log」に寄せて誤検知を減らす
- その上で、特定のパス・クエリ・ヘッダーなどに対して Block する Custom Rule を作成
- Custom Rule は DRS よりも優先して評価されるため、「ここだけは必ず Block」というポリシーを作れる
もちろん、OWASP ルールそのものを完全に再現することは困難ですが、「危険なパスやメソッドを明示的に拒否する」「管理系パスは特定 IP からしか受け付けない」といった コードを書く前に決められるセキュリティポリシーは Custom Rule の方が実装しやすいケースも多くあります。
949110 調査を効率化するログの読み方
WAF ログとアクセスログを trackingReference で突き合わせる
WAF ログだけを眺めていると、「本当にユーザー影響が出ているのか」「レスポンスコードはどうなっているのか」が分かりにくいことがあります。そこで、WAF ログと Front Door のアクセスログを trackingReference で突き合わせると、以下のような確認が容易になります。
- ブロックされたリクエストが実際には 403 を返しているのか
- どの URL・どのクライアント IP・どの User-Agent から来ているのか
- レスポンス時間やリトライの有無など、アプリ側の観点も含めて把握できる
例えば、次のようなクエリで「Block されたリクエストと、そのときの HTTP ステータスコード」を一覧できます。
let BlockEvents = AzureDiagnostics
| where Category == "FrontDoorWebApplicationFirewallLog"
| where action_s == "Block"
| project trackingReference_s, waf_time = TimeGenerated,
waf_rule = rulename_s, waf_action = action_s;
AzureDiagnostics
| where Category == "FrontDoorAccessLog"
| project trackingReference_s, httpStatusCode_s, requestUri_s, clientIp_s, access_time = TimeGenerated
| join kind=inner BlockEvents on trackingReference_s
| project access_time, waf_time, trackingReference_s,
httpStatusCode_s, requestUri_s, clientIp_s,
waf_rule, waf_action
| order by access_time desc
949110 を対象にした場合は、BlockEvents 側の waf_rule を 949110 固定にすれば、「949110 によって 403 が返っているリクエスト」の一覧が取りやすくなります。
action_s の値で「どの段階か」を切り分ける
ログを読む際は、action_s の値に着目すると、「評価のどのフェーズか」を理解しやすくなります。
- AnomalyScoring → 下位ルールによるスコア加算。details_s からヒットしたパラメーターや値を確認する
- Block → アノマリースコアの閾値を超え、949110 などの評価ルールが最終的にブロックを決定した状態
- Log → Detection モードや、ルールアクションを Log にしている場合の記録のみ
アノマリースコア方式では「1 つのリクエストに対して複数のログ行が発生する」のが通常であることを意識しておくと、949110 の原因追跡がぐっとやりやすくなります。
誤検知が多いときに見直したいポイント
アプリケーション側の入力仕様を見直す
WAF チューニングというと「とりあえずルールを無効化する」方向に進みがちですが、アプリケーション側の入力仕様を見直すことで誤検知の元を断てるケースもよくあります。
- ユーザー入力として
<script>や SQL 断片をそのまま受け付けていないか - デバッグ用に「SELECT * FROM users」など、攻撃パターンに似た文字列をそのまま送っていないか
- HTML を自由入力させるフォームが本当に必要か、あるいはマークダウンなど別形式にできないか
特に、ログに出てくる details_s の「matchVariableValue」 を丁寧に見ると、「実は業務上不要なデータが飛んでいる」ことが判明することもあります。その場合は、WAF ではなくアプリケーション側で入力値を制限する方が根本的な対策になります。
DRS バージョンや Paranoia Level の調整
DRS 2.1 / 2.2 など、より新しいルールセットほど、一般的には 誤検知の削減や最新の脆弱性への対応が改善されています。また、ルールの「Paranoia Level(PL)」を下げることで、攻撃検出の鋭さと誤検知率のバランスを調整することもできます。
- まずは PL1(デフォルト)で運用し、必要なものだけ PL2 ルールを有効化する
- PL2 の中でも誤検知が多いルールは Log 化または無効化し、残りに集中してチューニングする
Application Gateway WAF を利用している場合は、OWASP CRS 3.x 系のルールセットへ移行することで、より細かな制御や最新のシグネチャを活用できるケースもあります。
よくある質問と落とし穴
Q. 949110 を除外するカスタムルールは本当に作れない?
A. はい。Custom Rule は「評価順序の先頭で独自条件を評価する仕組み」であり、特定の DRS ルール(949110 を含む)をピンポイントでスキップすることはできません。Custom Rule でできるのは、例えば次のようなことです。
- 特定のパス(例:/healthz)や IP レンジからのアクセスを、そのまま Allow する
- 特定ヘッダーの有無(例:監視系ツール専用ヘッダー)でバイパスする
これは「そのリクエスト全体を DRS から外す」動きになるため、対象を絞らないとセキュリティリスクが大きくなります。一方で、すでにゼロトラストなど別の仕組みで守られているエンドポイントであれば、WAF 側では Custom Rule によるバイパスを積極的に検討しても良いでしょう。
Q. Detection モードなら 949110 を気にしなくてよい?
WAF ポリシーを Detection(検出)モードにしている場合、アノマリースコアが 5 を超えてもリクエストはブロックされず、ログだけが残ります。チューニングの初期段階では Detection モードでしばらく様子を見るのは有効な戦略です。
ただし、Detection モードのまま本番運用を続けると、WAF が「検知するだけの存在」になってしまい、攻撃トラフィックを実際には止められません。949110 の発生件数が落ち着いてきたら、以下のようなフェーズ分けを行うことをおすすめします。
- Detection モード + DRS アクション Log で誤検知パターンを洗い出す
- 原因ルールを特定し、Exclusion / Log 化 / 無効化を実施
- DRS アクションを AnomalyScoring + Block に戻し、Prevention モードへ切り替える
Q. Front Door と Application Gateway で 949110 の扱いは違う?
アノマリースコアの考え方自体は同じですが、ポータルから設定できるアクションや UI は異なります。
| 項目 | Azure Front Door WAF(グローバル) | Application Gateway WAF(リージョナル) |
|---|---|---|
| DRS 2.x のルールアクション | Log / AnomalyScoring | Allow / Block / Log / AnomalyScoring など、より多彩 |
| アノマリースコア閾値 | 共通(通常 5) | 共通(通常 5) |
| 949110 の役割 | スコア閾値超過を示すメタルール(無効化不可) | 同様 |
| 「一部ルールだけ Block」 | DRS 2.x 単体では不可(Custom Rule などの併用が必要) | ルール単位の Block/Allow 設定が可能 |
マルチレイヤーで WAF を利用している場合は、「どのレイヤーでどこまで厳しく見るか」を明確に分担させると、949110 のチューニング方針も決めやすくなります。
Q. CRS 3.x に移行すれば 949110 は出なくなる?
Application Gateway で OWASP CRS 3.x 系のルールセットを使う場合でも、アノマリースコア方式と、それを集約する評価ルールという考え方は同じです。ルール ID が完全に同じとは限りませんが、「スコア閾値超過を検知するメタルール」が存在し、やはり個別に無効化することは推奨されません。
CRS 3.x への移行は、あくまで シグネチャの精度向上や最新脆弱性への対応強化が目的であり、「949110 相当のルールがなくなる」わけではない点に注意が必要です。
まとめ:949110 は「敵」ではなく「アラートのまとめ役」
Azure Front Door WAF の Microsoft_DefaultRuleSet‑2.x‑BLOCKING‑EVALUATION‑949110 は、一見すると「よく分からないのに正当なリクエストを止める厄介者」のように見えます。しかし、その正体はあくまで 複数の異常検知結果を 1 つにまとめる評価ルールです。
- 949110 自体を無効化・除外することはできない(そして、すべきでもない)
- 本当に見るべきなのは、trackingReference 単位でたどったときの下位ルールと、その matchVariableValue(実際にヒットした値)
- 「すべて Log、一部だけ Block」は AFD WAF の managed rules だけでは実現できないため、AnomalyScoring・複数ポリシー・Custom Rule を組み合わせた設計が必要
949110 を「消す」ことを考えるよりも、ログを使って下位ルールを丁寧に洗い出し、Exclusion・Log 化・Custom Rule などを組み合わせて、業務要件に合った WAF ポリシーを設計することが、結果的にはもっと安全で運用しやすい構成につながります。
この記事のクエリと考え方をベースに、ご自身の環境で 949110 の発生パターンを可視化し、少しずつ誤検知を削り込んでいってみてください。

コメント