Azureを勉強して、ASP.NETでWebアプリを作ってみました。
Application Gateway(WAF)も立てて、セキュリティは万全!……のはずが、いざ公開してみると、自分や友人のログインが突然ブロックされるという謎の現象に遭遇しました。
今回は、初心者がハマりがちな「WAF運用いたちごっこ」の正体と、スマートな解決策を共有します。
1. 犯人は「ランダムすぎるCookie」
ASP.NET(特にCore)には、セキュリティを守るための仕組みが標準で備わっています。
その代表格が、以下のようなCookieやトークンです。
• .AspNetCore.Mvc.CookieTempDataProvider
• .AspNetCore.Antiforgery
これらの中身は、セキュリティのために「推測不可能なランダム文字列」になっています。
ところが、このランダムな文字列の中に、たまたまSQLインジェクション攻撃に似たパターン(-- など)が紛れ込んでしまうことがあるのです。
2. 初心者が陥る「ID除外の罠」
WAFのログ(Log Analytics)を見ると、「ルールID: 942440 でブロック」と出ます。
そこで「よし、この 942440 を許可リストに入れよう!」と設定するのが、最初の落とし穴です。
実は、Cookieの中身は毎回変わるため、「昨日は 942440 だったけど、今日は 942441 でブロックされる」という現象が起きます。これが「いたちごっこ」の始まりです。
3. 正解は「変数のグローバル除外」
特定のルール番号を許可するのではなく、「この名前のCookieについては、WAFの全検査をスキップしていいよ」という設定をするのが正解です。
設定のコツ(Azureポータル)
WAFポリシーの「管理ルール」→「除外」設定で、以下のように登録します。
• 一致変数: 要求のCookieの名前
• セレクター: .AspNetCore.Mvc.CookieTempDataProvider
• ルールセット: ここを特定のIDにせず、全体(Global)にするのがポイント!
これで、どんなランダムな値が入ってきても、WAFが「あ、このCookieは安全な枠組みのやつだね」とスルーしてくれるようになります。
4. もっと安心するために:Azure Advisorを活用しよう
「除外設定を増やすとセキュリティが弱くならない?」と不安になるかもしれません。
そんな時は、Azure Advisor や Microsoft Defender for Cloud の「セキュリティ態勢」をチェックしましょう。
「基盤となる CSPM(無料版)」を有効にするだけで、Azureが「他にも設定ミス(暗号化漏れなど)はない?」と自動で診断してくれます。今回のWAF設定だけでなく、サイト全体の健康診断をセットで行うのが、モダンなクラウド運用のコツです。
最後に
WAFは「ただ置くだけ」では、時に味方を攻撃してしまうことがあります。
「いたちごっこ」に疲れたら、ぜひ除外設定の「範囲(スコープ)」を見直してみてください。
「ログを見て、原因を突き止め、ベストプラクティスを適用する」。この流れを一度経験すると、クラウドのセキュリティがぐっと身近に感じられるようになりますよ!
【おまけ】WAFのブロック理由を特定するKQLクエリ
Azure WAFが「何を」「どのルールで」ブロックしたのかを調べるためのクエリです。
Azure Portalの Log Analytics で実行してください。
1. 直近のブロック履歴を一覧表示する
まずは「何が起きているか」の全体像を把握するクエリです。
// WAFのブロックログを新しい順に100件表示
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK"
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| project TimeGenerated, clientIp_s, requestUri_s, ruleId_s, Message, details_data_s
| order by TimeGenerated desc
| take 100
2. 特定のCookieが原因でブロックされているか特定する
今回の「犯人(Cookie)」を追い詰めるためのクエリです。
// 特定のCookie名が含まれるブロックログを抽出
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK"
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
// ↓ここに調べたいCookie名(.AspNetCore.Mvc.CookieTempDataProviderなど)を入れます
| where details_data_s contains "CookieTempDataProvider"
| project TimeGenerated, clientIp_s, ruleId_s, details_data_s, details_message_s
| order by TimeGenerated desc
3. どのルールIDによく引っかかっているか集計する
「いたちごっこ」が起きていることを証明するためのクエリです。
// ブロックされたルールIDのランキングを表示
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK"
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| summarize Count = count() by ruleId_s, Message
| order by Count desc
ワンポイントチェック
ruleId_s: どのルールに触れたかがわかります。
details_data_s: Cookieやリクエストの中身の「どの文字列」がダメだったのか、具体的な中身が表示されます。ここを見て Password=... ではなく、ランダムな英数字の羅列であれば、誤検知の可能性大です!
