AWS WAFの誤検知とEKSの脆弱性対応|ログから修正完了まで

AWS WAFの誤検知調査とEKSコンテナの脆弱性修正 AWS監視・オブザーバビリティ


WAFの誤検知は、403を返したルールをログで特定し、必要な経路だけに例外を設けます。EKSの脆弱性対応では、検出されたイメージと稼働中のPodを照合すると、どのサービスから対応すべきかを判断できます。

この記事でわかること

  • WAFとアプリのどちらが403を返したかをログで見分ける方法
  • 正常な注文を通しながら、既存の遮断が働くことを確認する手順
  • PHP2Shellを例に、影響調査から修正版の展開・再スキャンまで進める手順

前提条件として、AWS WAFを関連付けたApplication Load Balancer(ALB)の背後で、Amazon EKS上の購入APIが動く架空の環境を使います。調査には対象のWAF・ALBログへの読み取り権限と、対象クラスタのPodを取得できる kubectl が必要です。ログ、件数、コマンド出力は説明用の例です。

1. 403を返した場所をログで確かめる

アラートを「どのリクエストが失敗したか」に落とす

10時にAWSのマネージドルールを有効化しました。直後の5分間で、購入APIの403が4件から160件に増えたとします。入口のログで同じホスト、パス、HTTPメソッドに絞ると、変更前後ともリクエストは2,000件。403率は0.2%から8%へ悪化しています。アプリに到達した購入リクエストも同じ時間に減っています。

ここまでで分かるのは、変更時刻と症状が重なっていることです。アプリの認可処理やALBの固定応答でも403は返り得ます。ステータスコードだけでWAFを原因と判断せず、Web ACLのログとALBのアクセスログを照らし合わせます。対象リクエストが同一かは、突合に使える識別子があればそれを、使えなければ時刻、ホスト、パス、メソッドなどを組み合わせて確かめます。

CloudWatch Logs Insightsで遮断を集計する

対象Web ACLのログをCloudWatch Logsへ配信している前提です。変更前後の時間範囲を選び、対象ホストと購入APIを絞ります。次の例ではホストを共有しないロググループを使っています。

fields @timestamp, action, terminatingRuleId
| filter httpRequest.uri = "/api/checkout"
    and httpRequest.httpMethod = "POST"
    and action = "BLOCK"
| stats count(*) as blocked by bin(5m) as window, terminatingRuleId
| sort window asc
window   terminatingRuleId     blocked
10:00    CommonRuleSet            152
10:00    RateLimit                  4

terminatingRuleId は評価を終了させたルールの識別子です。遮断のない時間帯は行が表示されません。この例ではWAFの遮断が156件あり、大半はマネージドルールグループに集中しています。ALB側の160件の403と件数は近いですが、この集計だけでは個々の403の原因は分かりません。WAF側の件数をそのまま全体の403率として扱わず、入口側で同じ条件を集計した分母を使います。 AWS WAFのログ項目

個別ログでルール名を確認し、再現する

グループ内の個別ルールは、該当イベントの ruleGroupList[].terminatingRule.ruleId で確認します。例では SizeRestrictions_BODY で、labels に awswaf:managed:aws:core-rule-set:SizeRestrictions_Body が残っています。これは8,192バイトを超えるリクエスト本文に一致するルールです。検証環境で同じAPIに架空の注文を送り、約6KBでは通過し、約10KBでは同じルールで止まることを確かめます。本文のバイト数を比較し、個人情報を含む実注文は再送しません。 AWSマネージドルールの仕様

一方、403が出た時刻に遮断ログが0件なら、Web ACLとALBの関連付け、ロググループ、タイムゾーン、ログフィルターを先に確認します。ALBログの target_status_code が 403 なら、ターゲットが返した応答なので、認可の変更やアプリログを調べます。elb_status_code=403 かつ target_status_code=- の場合は、actions_executed が waf で終わっているかを見て、WAFによる遮断と固定応答を切り分けます。 ALBアクセスログ

2. AWS WAFの例外を絞り、守るべき通信を再確認する

WAFのログで正常な注文の遮断を調べ、例外を絞る流れ
WAF誤検知の対応イメージ。購入APIに限って例外を設け、別経路で同じルールに該当する通信が引き続き遮断されるかを確認します。

どの経路で大きな本文が必要かを決める

アプリ担当に確認すると、商品点数の多い注文では10KB程度のJSONが正規仕様でした。今回例外を検討する対象は shop.example.com の POST /api/checkout です。同じWeb ACLが別ホストも保護しているなら、同じパスがあっても例外の対象に含めません。正常な注文がすべて8KB以内に収まる設計なら、本文の肥大化をアプリ側で直す判断もあります。

ALBでWAFが検査できる本文は先頭8,192バイトです。ルールのサイズ制限を緩めて10KBを通すと、WAFが本文の末尾まで検査できるわけではありません。アプリ側で本文全体に対するサイズ上限、JSONスキーマ、認証・認可を確認します。本文全体を検証できる見通しが立たない間は、大きな注文の扱いをアプリ担当と決めます。 AWS WAFの本文検査上限

Countとラベルで1ルールの例外を作る

マネージドルールグループの中で SizeRestrictions_BODY だけを RuleActionOverrides で Count にします。Countは一致を記録して評価を続けるアクションです。その後に、対象ラベルが付き、かつ購入APIのホスト・メソッド・パスの組に一致しない場合に遮断するカスタムルールを置きます。

優先順位 100  CommonRuleSet
              SizeRestrictions_BODY のみ Count
優先順位 110  対象ラベルあり AND NOT(購入APIのホスト・メソッド・パス)
              → Block
以降          既存のルールを評価

購入APIに対する早い順位の Allow は、そこで評価を終わらせます。上の構成は、その経路でも後続ルールを評価します。既存の終端ルールによりラベル参照まで届かない通信や、別ルールが先に止める通信もあるので、Web ACL全体の評価順を確認します。パスの照合では、末尾スラッシュやURLエンコードをアプリ側がどう扱うかも確認します。 AWS WAFのラベル・AWSの誤検知管理ガイド

正常系と遮断系をセットで試し、切り戻し条件を決める

検証環境の入力 期待する結果
購入APIへ正規の10KBの注文 購入が成功し、サイズルールへの一致が記録される
別パスへ同じサイズの本文 ラベルを参照するカスタムルールで遮断される
購入APIへ別の有効な遮断ルールに一致するテスト入力 該当する別ルールで遮断される
購入APIへ仕様上の上限を超える本文 アプリが拒否し、注文が作られない

Count変更後のログでは、最終アクションと途中で一致したルールを分けて見ます。ラベルが付いていても、最終アクションが ALLOW の場合と、別ルールの BLOCK の場合があります。Countの件数だけでは注文の成否は分かりません。

本番反映前に、購入成功率、購入APIの403率、別経路での遮断件数を変更前と比較できるようにします。別経路で止めるべき通信が通過した場合は、保存したWeb ACL設定に戻します。元に戻せば大きな注文も再び止まるため、その影響と暫定運用をアプリ担当と共有します。例外を恒久化するか、アプリの改修後に撤去するかは、担当者と見直し日を決めて記録します。

3. PHP2Shellを例に、EKSコンテナの影響範囲を判定する

速報から自分たちが確認すべき条件を抜き出す

IPAが2026年10月22日に公表したPHP2Shellの注意喚起では、PHPの2つの脆弱性(CVE-2026-109618、CVE-2026-109619)による遠隔からのコード実行の可能性を説明しています。10月26日には、米国CISAの悪用が確認された脆弱性のカタログに掲載されました。IPAの情報は11月2日に更新されています。ここまでが公表情報です。自分たちの環境に影響があるかは、実際のPHPの配布元・バージョンと、外から到達する処理を照合して判断します。 IPAのPHP2Shell注意喚起・AWSのセキュリティ速報

たとえば上流PHPの8.4系では、IPAが8.4.27を修正版として挙げています。ディストリビューションが修正をバックポートする場合は、上流のバージョン文字列だけで決めず、配布元のパッケージ版とアドバイザリを確認します。アプリの依存関係だけを棚卸しすると、ベースイメージのPHPランタイムを見落とすことがあります。

Inspectorの検出を実行中のPodと照合する

ECRの拡張スキャンでは、InspectorがOSや言語パッケージの脆弱性を検出します。対象リポジトリ、イメージのダイジェスト、パッケージ名、検出バージョン、修正情報を控えます。ダイジェストはイメージの内容を識別する値です。Inspectorの実行環境との関連付けを手がかりに、対象クラスタでも稼働中の値を確認します。 InspectorによるECRイメージスキャン

kubectl -n shop get pods -l app=checkout \
  -o custom-columns='POD:.metadata.name,IMAGE:.spec.containers[*].image,IMAGE_ID:.status.containerStatuses[*].imageID'
POD            IMAGE           IMAGE_ID(抜粋)
checkout-a     checkout:prod   …@sha256:aaaa…
checkout-b     checkout:prod   …@sha256:aaaa…
checkout-c     checkout:prod   …@sha256:bbbb…

IMAGE はPod仕様の参照、IMAGE_ID はランタイムが報告する識別子です。この例で検出対象が aaaa… なら、同じタグを使っていても2台で対象イメージが稼働しています。複数CPUアーキテクチャ向けのイメージでは、イメージインデックスとプラットフォーム別マニフェストを区別し、実際の参照を照合します。このコマンドの範囲は一つの名前空間とラベルに限られるため、別クラスタ、サイドカー、JobやCronJobのテンプレートも確認します。 Kubernetesのコンテナイメージ

稼働、到達性、悪用の証拠を別々に判断する

観測したこと 次の判断
対象ダイジェストのPodが公開サービスの配下にある 公開経路とPHPの構成を確認し、修正を優先する。修正版が間に合わなければ該当経路の一時停止を検討する
対象は外部入口のない定期ジョブで使われている ジョブの入力や内部からの到達性も確認し、影響と修正期限を決める
対象はレジストリにあるが稼働先が見つからない 休止中の処理や過去の展開を確認し、再利用されないようにする
悪用を疑うリクエストや異常な実行の痕跡がある ログを保全し、修正と並行してインシデント対応を進める

PHP2Shellのような速報が出たときに、WAFルールの一致だけで悪用の成否を判定することはできません。入口のログ、アプリのログ、利用できる実行時の証跡を時系列で確認します。調べた期間、保存期間の制約、取得できなかった証跡も記録します。

4. 修正版を展開し、完了を証明する

脆弱なイメージを稼働中のPodと照合し、修正版へ段階的に切り替える流れ
検出されたイメージのダイジェストを稼働中のPodと照合し、少数のPodから修正版へ切り替えます。

修正する層に合わせてイメージを作り直す

アプリ依存の脆弱性ならロックファイルを更新し、OSパッケージなら配布元の修正版を含むベースイメージを選びます。今回のPHPの例では、実際にランタイムを供給するベースイメージやパッケージを更新します。EKS on Fargateでも、AWSが管理する基盤OSと自チームが配るコンテナイメージは管理範囲が別です。ベースのダイジェストを更新した変更をレビューし、再ビルドしたイメージのパッケージ版とスキャン対象を確認します。 EKS FargateのOSパッチ・Dockerのビルド指針

少数に展開し、サービスが正常かを確かめる

修正版のダイジェストを指定し、既存の段階展開の仕組みで少数のPodから切り替えます。まず正常な注文と、修正したランタイムを実際に通る機能をテストします。本番では変更前と同じ経路の成功率、5xx率、処理時間を比較します。段階展開に必要なリクエスト数が集まっていなければ、数分間エラーが出なかったことだけで全体へ進めません。

異常があれば展開を止め、原因を切り分けます。旧イメージに戻す必要がある場合は、脆弱性が戻ることを前提に、該当経路の停止などの暫定策を継続します。先に安定版の修正済みイメージが用意できていれば、切り戻し候補として使えます。

修正完了と侵害調査の進捗を分けて報告する

最後に、対象の全Podやジョブ定義で修正版を参照し、稼働中の識別子も一致することを確認します。新しいダイジェストのスキャンが完了し、対象CVEの指摘が解消したことを確認します。結果が空なら、スキャン対象外や未完了でも空になり得るため、スキャン状態を見ます。旧ダイジェストがレジストリに残っていれば、旧イメージへの指摘は引き続き表示されることがあります。 ECR拡張スキャンの対象条件

公開の購入APIで対象イメージが2 Pod稼働していました。全Podで修正版のダイジェストを確認し、新イメージのスキャンと購入テストが完了しました。過去ログの調査は継続中です。確認済みの時間範囲と次回報告時刻は対応記録に記載しました。

手元のランブックにも、WAFなら「どのルールが遮断したか」、コンテナなら「どのダイジェストが稼働していたか」を記録する欄を作っておくと、次の当番が判断の根拠を引き継げます。役に立ったら、いいねで知らせてもらえるとうれしいです。

コメント

タイトルとURLをコピーしました