手当たり次第に書くんだ

飽きっぽいのは本能

ModSecurity の audit log を Grafana で見る理由 – WAF を観測可能な防御点として扱う

WAF は、導入した時点で運用が終わる仕組みではありません。ModSecurity と OWASP Core Rule Set を有効にすれば、不審なリクエストを遮断できる可能性は高まります。しかし、実際の運用では「止めた」という結果だけでは不十分です。どのリクエストを、どのルールやスコアで、どの入口で止めたのかを後から確認できなければ、攻撃の可視化にも、誤検知の調整にもつながりません。

そのため、ModSecurity は通信を止める機能としてだけでなく、境界で発生した判断を記録する観測点として扱うべきです。audit log を Loki に集約し、Grafana でダッシュボード化すると、WAF の動作を「なんとなく効いている」状態から、運用上の判断材料へ変えられます。

この記事では、特定環境のホスト名や IP アドレスには踏み込まず、reverse proxy に置いた ModSecurity の audit log を Grafana で見る方法論を整理します。

WAF はアプリケーションの外側にある観測点である

Web アプリケーションの Pod や PHP プロセスの中だけを見ていると、アプリケーションに到達しなかった通信は見えにくくなります。WAF が reverse proxy に置かれている場合、アプリケーションへ渡す前の段階で、スキャン、認証攻撃、公開すべきではないファイルへのアクセス、異常な HTTP メソッド、ルールに一致したリクエストを観測できます。

この位置で記録する意味は、単に攻撃を数えることではありません。アプリケーションログ、Web サーバーログ、WAF audit log は、それぞれ見ている境界が違います。WAF audit log は、アプリケーションの手前で何が判断されたのかを残すためのログです。

ログ主に見えるもの見えにくいもの
アプリケーションログ処理されたリクエスト、例外、業務上の状態WAF や reverse proxy で遮断された通信
Web サーバーログHTTP ステータス、URL、User-Agent、転送量どの WAF ルールが判断したか
ModSecurity audit logリクエスト内容、判定理由、ルール、 anomaly score、遮断結果アプリケーション内部の業務処理

WAF audit log は、アプリケーションログの代替ではありません。むしろ、アプリケーションの外側にある防御点として、別の観測面を提供します。

audit log で見るべき情報

ModSecurity の audit log は情報量が多いため、すべてを人間が毎回読む運用には向きません。Grafana で見る場合は、まず運用判断に使うフィールドを決めます。

観点代表的なフィールド用途
いつ発生したかtransaction_time急増、継続、特定時間帯の偏りを見る
どこから来たかtransaction_remote_addressCF-Connecting-IP送信元単位の集中や地域傾向を見る
何を要求したかrequest_request_linewp-login.php.envwp-config.php などの探索を確認する
どう応答したかresponse_status403404500 の偏りを見る
なぜ止めたかaudit_data_action_message、anomaly scoreルール調整や誤検知判断の材料にする
どの Host かHostX-Forwarded-Host複数サイトやサブドメインの入口を分けて見る

重要なのは、WAF のログを「攻撃ログ」と決めつけないことです。403 が出ていても、それが期待通りの遮断なのか、正常な編集画面や API 呼び出しを壊しているのかは、リクエスト内容と判定理由を合わせて見なければ分かりません。

Loki へ JSON として入れる

Grafana で WAF audit log を扱いやすくするには、ログをただの文字列として保存するのではなく、JSON として検索できる状態にしておくことが重要です。Loki に source="modsecurity-audit" のようなラベルを付け、本文を JSON として扱える形にしておくと、LogQL の | json でフィールドを取り出せます。

実装上は、ModSecurity が出力する audit log をファイルとして受け、Grafana Alloy や Promtail などのログ収集エージェントで Loki へ送る構成になります。このとき、ホスト名、サービス名、ログ種別をラベルとして固定しておくと、Grafana のダッシュボードで扱いやすくなります。

ラベル意味
sourcemodsecurity-auditModSecurity audit log であることを示す
hostproxy-rev.example.localどの reverse proxy から来たログかを示す
jobmodsecurity-auditログ収集ジョブを分ける
filename/var/log/apache2/modsec_audit.json収集元ファイルを確認する

ラベルに入れる情報は検索の軸にするものへ絞ります。リクエスト URL や送信元 IP アドレスのように種類が増え続ける値をラベルに入れると、Loki のカーディナリティが増えすぎます。これらは JSON フィールドとして検索する方が扱いやすいです。

Grafana で見るべきパネル

ダッシュボードは、細かいログを読むためだけではなく、状況を短時間で把握するために作ります。最初に見るべきパネルは多くありません。

パネル目的
audit entriesWAF audit log 全体の量を見る
WAF blocks403 の増減を見る
status 別件数200403404500 の比率を見る
Top remote addresses特定送信元の集中を確認する
Top request lines狙われている URL や HTTP メソッドを見る
WordPress REST / login blocks正常操作と攻撃が混ざりやすい入口を確認する
Recent WAF blocks直近の遮断内容を時系列で読む

たとえば、過去 24 時間の status 別件数を見ると、403 が増えているのか、404 の探索が多いのか、500 が混ざっていないかを確認できます。WAF の正常性を見るには、遮断件数だけでなく、成功応答やアプリケーションエラーとの関係も見ます。

sum by (response_status) (
  count_over_time({source="modsecurity-audit", host="proxy-rev.example.local"} | json [24h])
)

遮断されたリクエストの傾向を見る場合は、request_request_line で集計します。これにより、.envwp-login.phpwp-comments-post.php、未知の HTTP メソッドなど、どの入口にアクセスが集中しているかを確認できます。

topk(10,
  sum by (request_request_line) (
    count_over_time(
      {source="modsecurity-audit", host="proxy-rev.example.local"}
      | json
      | response_status="403"
      [24h]
    )
  )
)

このようなクエリは、単に攻撃者を探すためのものではありません。正常な編集操作や API 呼び出しが WAF に巻き込まれていないかを確認するためにも使います。

403 を攻撃件数として扱わない

WAF のダッシュボードを作ると、どうしても 403 の件数に目が行きます。しかし、403 は攻撃件数そのものではありません。WAF が遮断した通信、Web サーバー側で拒否した通信、認可上拒否された通信が混ざることがあります。さらに、誤検知によって正常な通信が遮断されている可能性もあります。

そのため、403 は「確認すべき判断結果」として扱います。送信元、リクエスト行、Host、WAF の action message、発生時間帯を合わせて見て、期待通りの遮断なのか、ルール調整が必要なのかを判断します。

見えた状態すぐに断定しない理由次に見るもの
403 が増えた攻撃増加とも誤検知とも限らないrequest line、action message、対象 Host
.env 探索が多い一般的なスキャンであり、個別侵害とは限らない送信元集中、継続時間、他の探索 URL
wp-login.php が多いBot、正規ログイン、監視が混ざる可能性があるUser-Agent、送信元、成功応答との関係
特定 API が遮断された攻撃ではなく、アプリケーション更新後の仕様変更かもしれない直近の変更、WordPress / plugin の更新履歴

WAF ログを Grafana で見る価値は、数を眺めることではなく、判断を戻せることにあります。攻撃、誤検知、設定ミス、アプリケーション変更を分けて考えるための材料にします。

WAF ルール調整の流れ

ModSecurity のルール調整は、ログを見ながら例外を増やす作業ではありません。まず遮断結果を観測し、正常通信か不正通信かを分類し、必要な場合だけ範囲を限定した例外に落とします。

段階行うこと
観測status、request line、Host、送信元、action message を見る
分類スキャン、Bot、正常操作、アプリケーション変更、誤検知を分ける
影響確認編集、REST API、ログイン、コメント投稿などの正常系を確認する
例外設計URL、メソッド、パラメータ、Host、ルール ID などで範囲を絞る
反映後確認遮断が減ったかだけでなく、不要な許可が増えていないかを見る

例外は広く入れるほど楽になりますが、防御点としての意味は薄くなります。特定の plugin や管理画面に必要な通信だけを許可するなど、観測結果から範囲を絞ることが重要です。

公開してはいけない情報もある

WAF audit log は、公開記事や共有資料へそのまま貼るべきログではありません。実ホスト名、内部 IP アドレス、Cookie、認証ヘッダー、POST body、攻撃元 IP アドレス、WordPress の管理 URL、plugin 名などが含まれる場合があります。

ブログ記事や運用メモにする場合は、実データを匿名化し、クエリ例も proxy-rev.example.local のような仮名に置き換えます。Grafana のスクリーンショットを使う場合も、変数、Host、IP アドレス、request body が写り込まないようにします。

また、WAF ログはセキュリティ運用上の情報です。Grafana の閲覧権限、Loki の保存期間、ログに含まれる個人情報や機微情報の扱いも設計対象になります。可視化することと、誰でも見られるようにすることは別です。

参考資料

参考書籍

参考書籍
参考書籍

体系的に学ぶ 安全な Web アプリケーションの作り方 第 2 版

WAF だけに頼らず、Web アプリケーションの脆弱性、入力値、認証、セッション、運用上の防御を体系的に確認したい場合の参考書籍です。価格や在庫はリンク先で確認してください。

Amazon で見る

このリンクは Amazon アソシエイトリンクです。

関連する記事

WAF と WordPress 運用の関連記事

まとめ

ModSecurity を導入しても、遮断結果を確認できなければ、WAF はブラックボックスになります。audit log を Loki に集約し、Grafana で可視化すると、WAF が何を見て、どのように判断したのかを運用に戻せます。

見るべきものは、単純な 403 の件数ではありません。送信元、request line、Host、response status、action message、anomaly score を合わせて見て、攻撃、誤検知、設定ミス、アプリケーション変更を分けることが重要です。

WAF は通信を止める装置であると同時に、境界で発生した判断を記録する観測点です。Grafana で ModSecurity の audit log を見ることは、防御を強くするだけでなく、防御の理由を説明できる状態にするための運用設計です。

ModSecurity の audit log を Grafana で見る理由 – WAF を観測可能な防御点として扱う

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る