WAFは「ブロックするための装置」であると同時に、攻撃の兆候と被害範囲を追うための一次情報源です。ログを有効化していなければ、インシデント発生後に「誰が・いつ・何を試し・どうなったか」を確かめる手段の多くが失われます。
Webアプリケーションへの攻撃は、偵察(スキャン)から始まり、手法を変えながら侵入を試みるのが定石です。ログを取得しておけば、その過程を後から追跡できます。
本記事はAWS WAFを対象とし、ログのフィールドはAWS公式ドキュメントに基づいて記載します。CloudflareなどほかのWAFでも考え方は共通ですが、記録される項目は製品ごとに異なります。
1. AWS WAFログから取得できるデータ
AWS WAFのログには、リクエストのメタデータ(IP・URI・クエリ文字列・ヘッダーなど)と、どのルールがどう判定したかが記録されます。以下はAWS公式のログフィールド一覧から、調査でよく使う項目を抜粋したものです。
| カテゴリ | フィールド | 内容 | 調査での使い方 |
|---|---|---|---|
| 基本識別 | timestamp | リクエストの日時(ミリ秒単位) | 時系列の整理、他ログとの突合 |
| 基本識別 | httpRequest.requestId | 基盤サービスが発行するリクエストID(ALBではトレースID) | Webサーバー・ALB・CloudFrontログとの突合キー |
| 基本識別 | webaclId / httpSourceName / httpSourceId | Web ACL、および保護対象(CF / ALB / APIGWなど)の識別子 | どのリソースへの攻撃かの切り分け |
| 送信元 | httpRequest.clientIp | 送信元クライアントのIPアドレス | IPレピュテーション照会、集計、ブロック判断 |
| 送信元 | httpRequest.country | 送信元の国(判定不能時は -) | 地域偏りの把握、Geo制限の判断 |
| 送信元 | clientAsn / forwardedAsn | 送信元のASN。clientAsnはASN一致ステートメントを使う場合のみ記録 | ホスティング事業者・クラウド由来の攻撃の把握 |
| 送信元 | ja3Fingerprint / ja4Fingerprint | TLS Client Helloから算出した指紋(CloudFront・ALBのみ) | IPを変えても同じツールからの通信かを識別 |
| 判定結果 | action | 終端アクション(ALLOW / BLOCK / CAPTCHA / CHALLENGE) | 遮断できたか、通過したかの確認 |
| 判定結果 | terminatingRuleId / terminatingRuleType | 終端したルールのIDと種別。何も一致しなければ Default_Action | どのルールで止まったか、素通りかの確認 |
| 判定結果 | terminatingRuleMatchDetails | 一致した箇所と値(SQLi・XSS一致ルールのみ) | 攻撃文字列とその位置の特定 |
| 判定結果 | nonTerminatingMatchingRules | 一致したが終端しなかったルール(COUNTなど) | COUNTモードで「検知だけされて通過した」リクエストの抽出 |
| 判定結果 | ruleGroupList / labels | マネージドルールグループの判定結果とラベル(先頭100件) | Bot・既知の脆弱性・IPレピュテーションなどの分類 |
| 判定結果 | rateBasedRuleList | 評価されたレートベースルール、集計キー、上限値、評価時間 | レートリミット発動状況、閾値の妥当性確認 |
| 判定結果 | captchaResponse / challengeResponse | CAPTCHA・チャレンジの結果と失敗理由 | Bot対策の効果測定 |
| HTTP情報 | httpRequest.httpMethod / httpVersion | HTTPメソッドとバージョン | 状態変更を伴う操作(POST/PUT/DELETE)の特定 |
| HTTP情報 | httpRequest.uri | リクエストURI(パス) | 攻撃対象のエンドポイント特定 |
| HTTP情報 | httpRequest.args | クエリ文字列 | GETパラメーターに含まれる攻撃文字列の確認 |
| HTTP情報 | httpRequest.headers | ヘッダー一覧(User-Agent、Host、X-Forwarded-Forなど) | 攻撃ツールの識別、ヘッダー経由の攻撃の確認 |
| その他 | oversizeFields | 検査上限を超えたBody・ヘッダー・Cookie | 検査を回避する巨大リクエストの検出 |
| その他 | responseCodeSent | カスタムレスポンスで返したステータスコード | WAF自身が返した応答の確認 |
記録されないもの(重要)
リクエストBodyは記録されません。 フィールド一覧にBodyの中身はなく、oversizeFields でサイズ超過が分かるだけです。POSTで送られた攻撃文字列やログインIDは、terminatingRuleMatchDetails(SQLi・XSSのみ)か、アプリ側のログで確認します。
オリジンの応答(ステータスコード・レスポンス本文)も記録されません。 WAFが分かるのは「リクエストを通したか止めたか」までです。200や404が返ったかは、ALB・CloudFront・Webサーバーのログで確認します。
なお、ログ設定のフィールドの伏せ字(Field redaction)で、URIパス・クエリ文字列・特定ヘッダー・メソッドを伏せ字にできます。逆に、何も設定しないとCookieやAuthorizationヘッダーがそのまま残るため、ログ自体の保護も必要です。
2. 有名なサイバー攻撃ごとの確認観点
攻撃の種類によって、見るべきフィールドは異なります。下表は、代表的な攻撃ごとに「どのフィールドで」「どんな兆候を見て」「次に何をするか」をまとめたものです。
| 攻撃(代表例) | 見るべきフィールド | ログ上の兆候 | 次のアクション |
|---|---|---|---|
| 偵察・脆弱性スキャン(Nikto、sqlmap、ffuf、gobusterなど) | httpRequest.clientIp、httpRequest.uri、httpRequest.headers(User-Agent)、ja3Fingerprint / ja4Fingerprint | 同一IPから /.env、/.git/config、/wp-admin など、存在しないはずのパスへの短時間の大量リクエスト。ツール名を含むUser-Agent | 悪性と判断できるIPやJA3/JA4をブロック候補にする。実際に404だったかはALB・Webサーバーログで確認 |
| SQLインジェクション | httpRequest.args、terminatingRuleMatchDetails、nonTerminatingMatchingRules(COUNT時は内部の ruleMatchDetails)、labels、action | UNION SELECT、' OR 1=1 などのSQLインジェクションを疑う文字列。terminatingRuleMatchDetails には一致した検査内容の詳細が記録される場合がある | BLOCKされていればWAFで遮断。ALLOWやCOUNTで通過していた場合は、アプリログ・DBログで到達・実行の有無を確認 |
| クロスサイトスクリプティング(XSS) | httpRequest.args、terminatingRuleMatchDetails、nonTerminatingMatchingRules(COUNT時は内部の ruleMatchDetails)、labels、action | <script>、onerror= など、XSSを疑う文字列 | 通過していれば、入力値が保存・反映されたかをアプリ側で確認。実際のスクリプト実行は被害者のブラウザ側で発生するため、WAF・サーバーログだけでは確定できない |
| Log4Shell(CVE-2021-44228)などの既知脆弱性悪用 | httpRequest.headers、httpRequest.args、httpRequest.uri、labels、action | ${jndi:ldap://...} などの文字列。AWS Managed RulesのLog4JRCE系ラベル | 該当コンポーネントのバージョン・パッチ状況を確認。通過していた場合はサーバーからの外向き通信(DNS・LDAP等)も確認 |
| OSコマンドインジェクション・パストラバーサル | httpRequest.args、httpRequest.uri、labels、action | ;cat /etc/passwd、../../、%2e%2e%2f など | 通過していれば、プロセス実行・ファイルアクセスなどのサーバー側の痕跡を確認 |
| SSRF | httpRequest.args、httpRequest.uri、labels、action | パラメーターに 169.254.169.254(AWS IMDS)や内部ホスト名を含むURL | IMDSv2の強制、IAMロールの権限・利用状況、CloudTrailなどを確認 |
| ブルートフォース | httpRequest.uri、httpRequest.clientIp、rateBasedRuleList、httpRequest.httpMethod | ログインURIへの同一IPからの集中したPOST | レートベースルールの閾値を見直す。認証の成否は認証ログで確認 |
| パスワードスプレー・クレデンシャルスタッフィング | httpRequest.uri、httpRequest.clientIp、clientAsn※、ja3Fingerprint / ja4Fingerprint、labels | 多数のIPからログインURIへの分散したPOST。IPは異なるが指紋やUser-Agentが共通する場合がある | 試行されたアカウントはBody等のアプリ側データに含まれるため、認証ログで確認。成功が疑われるアカウントはパスワードリセットやMFA強制などを検討 |
| L7 DDoS(HTTPフラッド) | timestamp、httpRequest.clientIp、httpRequest.country、clientAsn※、httpRequest.uri、rateBasedRuleList | 特定URIへの急激なリクエスト増加。特定の国・ASNへの偏りなど | レートベースルール、Geo制限、Challenge/CAPTCHAなどを検討 |
| 悪性Bot・スクレイピング | labels、httpRequest.headers、ja3Fingerprint / ja4Fingerprint、challengeResponse | 規則的な間隔で多数のページを巡回するアクセス。Bot Control系ラベル、Challenge失敗の多発など | Challenge/CAPTCHA、Bot ControlなどのBot対策を検討 |
※ clientAsn は、AWS WAFログではASN match statementを使用した場合のみ記録される点に注意。
パスワードスプレーは「少数のよくあるパスワードを多数のアカウントに試す」手法、クレデンシャルスタッフィングは「他サービスから漏えいしたID・パスワードの組を試す」手法です。どちらもWAFログだけでは「どのアカウントが狙われたか」は分からない点に注意してください。
3. インシデント発生時のフォレンジック調査フロー
調査の起点は「WAFが止めた通信」ではなく「WAFを通過した通信」です。ブロックログが出ていないことは安全の証明になりません。
- WAFログから通過した通信を抽出する
該当時間帯について、actionがALLOWのもの、およびnonTerminatingMatchingRulesにCOUNTが記録されたもの(検知したが止めていない通信)を抽出します。terminatingRuleIdがDefault_Actionの通信は、どのルールにも一致せず素通りした通信です。 - 他のログと突合する
requestIdをキーに、ALB・CloudFront・Webサーバーのログと紐付けます。ALBではこの値がトレースID(X-Amzn-Trace-Id)です。IPと時刻で突合する場合、CDNやALBの背後ではWebサーバーに中継元のIPが記録されるため、X-Forwarded-Forヘッダーで実際の送信元を確認します。 - 到達・実行を確認する
突合したログで、200 OKや302リダイレクトが返ったリクエストを特定します。POSTの中身はWAFログにないため、アプリログで処理内容を確認します。 - 影響範囲を確定する
データベースの更新・読み出し、不正なファイルアップロード、外部への通信、認証の成功などを、DB・OS・CloudTrailなどのログで特定します。
4. WAFログだけでは分からないことと補完すべきログ
WAFログは「リクエストの入口」の記録です。結果や中身を確かめるには、次のログを併せて保管しておく必要があります。
| WAFログで分からないこと | 補完するログ |
|---|---|
| リクエストBodyの中身(POSTされたID・パスワード・攻撃文字列) | アプリケーションログ、認証ログ |
| オリジンが返したステータスコード・応答時間 | ALBアクセスログ、CloudFrontアクセスログ、Nginx・Apacheログ |
| DBやOSで実際に何が実行されたか | DB監査ログ、OSログ、EDR |
| AWSリソースの操作(盗まれた認証情報の悪用など) | CloudTrail |
| サーバーからの外向き通信 | VPCフローログ、Route 53 Resolverクエリログ |
また、ログ設定のフィルターで「BLOCKのみ記録」にしていると、COUNTやALLOWの通信が残らず、3章の調査ができません。少なくとも調査対象期間はALLOW・COUNTも記録する設定にしておくことをおすすめします。
AWS WAFはリクエストBodyの先頭の一定サイズ(検査上限)までしか検査しません。サイズ超過は oversizeFields に記録されるため、巨大なリクエストで検査をすり抜ける試みも確認対象に含めます。
まとめ
WAFログの有効化は、インシデント時の「防犯カメラの映像」を確保することと同じです。ただし映るのはリクエストの入口までで、Bodyやオリジンの応答は映りません。
WAFログで「誰が・いつ・どの手法を試したか」を押さえ、ALB・アプリ・CloudTrailなどのログで「結果どうなったか」を確かめる。この組み合わせで初めて、根本的なアプリ改修やルールのチューニングにつなげられます。
まだログを有効化していない場合や、CloudWatch Logs・Amazon S3などへの保管、DatadogやSplunkなどのSIEMとの連携をしていない場合は、早期の設定をおすすめします。
参考資料
- Log fields for protection pack (web ACL) traffic(AWS WAF Developer Guide)
- Finding your protection pack (web ACL) records(AWS WAF Developer Guide)
- AWS Managed Rules(AWS Security Services Best Practices)
ここまで読んでいただき、ありがとうございます。もしこの記事の技術や考え方に少しでも興味を持っていただけたら、ネクストのエンジニアと気軽に話してみませんか。
- 選考ではありません
- 履歴書不要
- 技術の話が中心
- 所要時間30分程度
- オンラインOK