Alternative Architecture DOJO

オルターブースのクラウドネイティブ特化型ブログです。

Azure WAFのJavaScript チャレンジ機能を試してみた

こんにちは、公文に通っている娘が先日「公文でお友達とおしゃべりしちゃうのが良くないから、今日は皆で離れた席に座るようにしてみた!」と言っていて、「おしゃべりしないように気をつける」ではなくちゃんと仕組みで解決したことに感心した木村です。

この記事はオルターブース2025年のアドベントカレンダーの16日目の記事です。前日はマイクロソフトTop Partner EngineerのはっしーによるGHAS + Defenderのお話でした。

adventar.org

また、15日目はみっつーのGitHub Copilot の自動モデル選択の記事も投稿されています。こちらはInfocomアドベントカレンダーの時期になっています。
気がつけば弊社もメンバーが25人を超えて、1つのアドベントカレンダーでは全員はかけなくなったんだなと思うと感慨深いものがあります。

qiita.com

さて、2025年11月11日、Azure Web Application Firewall(WAF)の「JavaScript チャレンジ」という新機能がFront DoorでGA(一般提供)しました。
本機能はApplication Gatewayでは2025年12月現在パブリックプレビュー中ですが、早速この機能を試してみたので、その体験を共有したいと思います。

azure.microsoft.com

JavaScript チャレンジとは?

JavaScript チャレンジは、ボット攻撃からWebアプリケーションを保護するための機能です。ブラウザベースのJavaScriptチャレンジを使って、正規のブラウザからのアクセスとボットによるアクセスを区別できるようになります。

learn.microsoft.com

仕組み

Azure WAFでJavaScript チャレンジがアクティブな状態で、クライアントのHTTP(S)要求が特定のルールと一致すると、以下のような流れで処理が行われます:

  1. クライアントにMicrosoft JavaScript チャレンジページが表示される
  2. ブラウザがバックグラウンドでチャレンジを計算(ユーザーには数秒間このページが表示される)
  3. 計算に成功すると、結果がAzure WAFのエンドポイントに送信される
  4. WAFは要求を非ボットクライアントとして検証し、残りのWAFルールを実行
  5. チャレンジに失敗した要求はブロックされる

なお、このエンドポイントはパブリックに公開されますが、送信された要求はバックエンドに転送されず、レート制限機能にもカウントされません。

CORS要求とIPアドレス変更への対応

特筆すべき点として、以下のケースでは再度チャレンジが発行されます:

  • CORS要求:クライアントが、チャレンジをホストしているドメインとは異なるドメインからJavaScript チャレンジをトリガーするページにアクセスした場合
  • IPアドレス変更:クライアントがJavaScript チャレンジを解決した後、IPアドレスが変更された場合

これらの仕様により、セキュリティが保たれる一方で、ユーザー体験への影響も考慮する必要があります。

試してみた手順

Front Doorのプレミアムプランは高額でなかなか試しづらいため、今回はApplication Gatewayで検証を行いました。
繰り返しになりますが、Application GatewayでのJavaScript チャレンジは2025年12月現在パブリックプレビュー中ですのでGA(一般提供)前の機能であることに注意してください。

1. Blob Storageに静的Webサイトをホスト

まず、検証用のコンテンツをホストするために、Azure Blob Storageに静的Webサイトを作成しました。手順については以下のドキュメントを参照してください。

learn.microsoft.com

今回は以下のようなシンプルなHTMLファイルを用意しました。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSチャレンジ成功!</title>
</head>
<body>
    <h1>JSチャレンジ成功!</h1>
</body>
</html>

2. Application Gatewayを作成

次に、Application Gatewayを作成します。今回はAzure portalを使用しました。

まず、レベルを「WAF V2」とし、WAFルールも作成します。この時に「ボット保護の追加」にチェックを入れておきます。

Application Gatewayの作成

次にバックエンドプールにBlob StorageのエンドポイントのFQDNを指定しました。

バックエンドプールの設定

あとはIPアドレスの追加やHTTPリスナーの追加などを行いますが、詳細な手順は割愛します。

3. WAFポリシーの確認

作成されたWAFのポリシーを確認します。JavaScriptチャレンジの有効期限を設定できるようになっているのが分かります。デフォルト値はキャプチャの通り30分です。

WAFポリシーの確認

また、WAFを防止モードに切り替えるのを忘れないようにします。

防止モードへの切り替えを忘れない

4. カスタムルールの追加

続いて、カスタムルールを追加します。今回は条件の所はアクセス元のIPアドレスを指定し、結果のアクションで「JSチャレンジ(プレビュー)」を選択します。

カスタムルールの追加

5. 動作確認

Application GatewayのパブリックIPアドレスにアクセスすると、JavaScript チャレンジのページが表示されました。数秒後、自動的にBlob Storageのコンテンツが表示されました。

JavaScriptチャレンジの画面

ブラウザの開発者ツールで確認すると、チャレンジに成功すると「appgw_azwaf_jsclearance」というクッキーが保存されているのが分かります。

クッキーが保存されている

値がJWT形式のトークンのようなのでデコードしてみると以下のような形でした。

{
  "alg": "HS256",
  "typ": "JWT"
}.{
  "Data": {
    "PS": "Global",
    "PSName": "Global",
    "State": 2
  },
  "sub": "xxx.xxx.xxx.xxx", // クライアントのIPアドレス
  "aud": [
    "yyy.yyy.yyy.yyy" // Application GatewayのIPアドレス
  ],
  "exp": 17nnnnnnnn.nnnnnn // 有効期限(UNIX時間)
}.[Signature]

有効期限もアクセス時間にポリシー設定で指定したタイムアウト時間を追加した値になっていました。

感想

JavaScript チャレンジ機能を実際に試してみて、ボット攻撃対策として非常に有効な手段だと感じました。特に、CAPTCHAのようなユーザーの手間をかけずに、自動的にボットを検出できる点が優れています。

一方で、CORS要求やIPアドレス変更時に再度チャレンジが発行される仕様については、Webアプリケーションの性質によってはユーザー体験に影響を与える可能性があります。導入を検討する際は、実際のユースケースに応じて、この機能の有効化範囲を適切に設定することが重要だと思いました。

JavaScriptチャレンジはApplication Gatewayでは現在パブリックプレビュー中ですが、今後GAとなることで、より多くの環境で活用できるようになることを期待しています。

皆さんの参考になれば幸いです。


サービス一覧 www.alterbooth.com cloudpointer.tech www.alterbooth.com