個人開発のWebアプリにAWS WAFを入れてみた

この記事はヌーラボブログリレー2025夏の8日目として投稿しています。

Backlogのソフトウェアエンジニアの林です。
この記事では、私が個人開発しているWebアプリにWeb Application Firewall (以下WAFと呼称します)を試験導入してみたので、その内容や得た知見について紹介します。

背景

Webの大前提として、アプリ/静的ページ等の形式に関わらずインターネット上にホストされたサイトは必ず攻撃の標的になります。

地球上に存在するグローバルIPには限りがある(特にIPv4であれば)ため、Googleのクローラーを拒否して検索インデックスに登録してなかったとしても、構成する全ページに認証やIP制限をしていたとしても、攻撃者のツールはどこからか嗅ぎつけてお構いなしに攻撃のリクエストを送りつけてきます。

PHPパッケージ等で任意コード実行ができそうなポイントの探索を試みているリクエストPHPパッケージ等で任意コード実行ができそうなポイントの探索を試みているリクエスト

WordPress管理画面の存在を検知を試みているリクエストWordPress管理画面の存在を検知を試みているリクエスト

上のコンソール画像はそのようなアクセスログの一例で、私の個人開発しているアプリのアクセスログから一部抜粋したものです。管理者ページを開こうとするリクエスト(なおこのサーバーにはWordPressは入っていません)や、任意コード実行を狙うようなパスへのアクセスが散見されますね。

AWSのWAFには、このような脅威から防御するためプログラミング言語を問わずWebアプリについての既知の脆弱性およびその攻撃に対する検査がルールセットとして多数プリセットされています。ELBの設定画面から簡単にアタッチできるので、どのくらい攻撃を拾えるのか今回試してみました。

適用したルール

試験的に適用してみるにあたりにあたって、今回下記のマネージドなルールセットを適用しました。概要を紹介します。(PHP/Laravel/RDS/Amazon Linuxによる構成であるため、関連するルールが含まれます。)

設定したルールセット一覧

  • AWS-AWSManagedRulesCommonRuleSet
    • 一般的なWebアプリケーション攻撃対策
    • クロスサイトスクリプティング(XSS)、コマンドインジェクション、ローカルファイルインクルード、パストラバーサルなどの検知
  • AWS-AWSManagedRulesKnownBadInputsRuleSet
    • 既知の悪意ある入力パターン対策
    • 明らかに不正なHTTPリクエスト、危険な文字列やパターン(例:NULLバイト、制御文字、過剰な長さの入力など)の検知
  • AWS-AWSManagedRulesPHPRuleSet
    • PHPアプリケーション特有の脆弱性対策
    • PHPのリモートコード実行、ファイルインクルード、セッションIDの漏洩、PHPエラーの露出などの検知
  • AWS-AWSManagedRulesSQLiRuleSet
    • SQLインジェクション対策
    • SQLインジェクション攻撃パターン(例:OR 1=1、UNION SELECTなど)の検知
  • AWS-AWSManagedRulesAmazonIpReputationList
    • 悪意あるIPアドレスからのアクセス制御
    • ボットネット、スパム、DDoS攻撃などで知られるIPアドレスからのリクエストのブロック
  • AWS-AWSManagedRulesLinuxRuleSet
    • Linuxサーバー向けの攻撃対策
    • Linuxコマンドインジェクション、シェルショック(Shellshock)、パストラバーサルなどの検知

実際に適用した後のメトリクス

攻撃の種類とアクセス元となる国の内訳攻撃の種類とアクセス元となる国の内訳

上の横向き棒グラフは、攻撃タイプ(左)とリクエスト送信元の国(右)に関するデータを示しています。

左側の「Attack types」グラフでは、「NoUserAgent」が最も多く検出されており、次いで「KnownBadInputs」、「BadBots」と続いています。「NoUserAgent」は文字通りユーザーエージェント情報が付与されていないリクエストであり、ボットや自動化ツールによるアクセスである可能性が高いです。「KnownBadInputs」は既知の悪質な入力パターン(例:SQLインジェクションやクロスサイトスクリプティングなど)を検知したことを示し、「BadBots」は悪質なボットによるアクセスを示しています。これらの結果から、アプリに対して自動化された攻撃や不正な入力を試みるアクセスが一定数存在していることが分かります。

右側の「Top 10 countries」グラフでは、やはり日本からのリクエストが圧倒的に多いものの、アメリカ、イラン、ブラジル、中国などもカウントされています。個人的に使用するだけのサービスであり利用者は日本国内に限定されるはずであるため、他国からのアクセスは基本的にbotによる機械的なアクセス、または手動による悪意あるリクエストである可能性が高いと考えられます。

ボットとデバイスタイプの内訳ボットとデバイスタイプの内訳

上画像の左の円グラフは、アクセスのうちボット等の内訳がどうなっているかを表すグラフです。検索クローラー等のBots:verifiedにカウントされている検証済botはごく僅かで、得体のしれないbotからのアクセスがそれを大きく上回り一定数存在することがわかります。右側のdevice typesは、今回の観点ではあまり意味を持たないため割愛します。

ヒットしたルールとマネージドグループの時系列推移ヒットしたルールとマネージドグループの時系列推移

上画像の左の折れ線グラフでは、どのWAFルールがリクエストにラベル付けされたかを時系列で可視化しています。aws:core-rule-set:NoUserAgent_Headerやaws:amazon-ip-list:AWSManagedIPReputationListなど、複数のルールが一時的に多く発動していることが分かります。特に14:30〜15:00の間にaws:amazon-ip-list:AWSManagedIPReputationListのラベルが急増しており、これは悪意のあるIPアドレスからのアクセスが集中した可能性を示唆します。

右の折れ線グラフは、どのマネージドルールグループによってリクエストが遮断されたかを示しています。AWSManagedRulesAmazonIpReputationListやAWSManagedRulesKnownBadInputsRuleSetなどが該当し、左グラフと同様に14:30〜15:00の間で遮断数が急増しています。これは、WAFが不審なアクセスや既知の悪質な入力を効果的にブロックしていることを意味します。

まとめ

WAFを試験導入した結果、ユーザーエージェント未設定や既知の悪質な入力による攻撃が多く検知されました。アクセス元は日本が大半ですが、海外からの不審なリクエストも一定数存在します。WAFの導入により、こうした攻撃を可視化・遮断できることを実感でき、セキュリティ強化の有効性を体験できました。

おまけ:無効化したルール

ルールセット内の一部のルールについてはアプリの正常動作の妨げになったので無効化しました。

  • AWS-AWSManagedRulesPHPRuleSet -> PHPHighRiskMethodsVariables_HEADER
    • セッション切断時にログイン状態を復元する機能が一時機能しなくなり、上記ルールを無効化することで解消しました。
    • 当該アプリでは採用しているLaravelのログイン維持Cookieはキーはremember_web_59ba36addc2b2f9401580f014c7f58ea4e30989dなどといった形式なのですが、おそらくはcookieのキーに無作為文字列が含まれていることで不審なHeaderと見做されたと考えられます。
  • AWS-AWSManagedRulesCommonRuleSet → SizeRestrictions_BODY
    • 8 KB (8,192 バイト) を超えるリクエストボディを遮断するルールです。
    • ファイル送信を含むユースケースが存在する場合はそのままでは事実上適用不可能なルールですので、無効化することにしました。

なお、今回は無効化で済ませましたが、商用アプリなら該当のケースだけをパスし他は制限するようカスタムルールを作成するのがよいと思います。

さいごに

今回はAWS WAFを触ってみました。自サイトに対する悪意あるリクエストを少ない設定で簡単に抑制できるため、ある程度のセキュリティ要件がありつつも構築にあまり大きな工数を割けない場合にとても有用な選択肢になりそうなので、ぜひ触ってみてください。それではまた。

開発メンバー募集中

より良いチームワークを生み出す

チームの創造力を高めるコラボレーションツール

製品をみる