Money Forward Developers Blog

株式会社マネーフォワード公式開発者向けブログです。技術や開発手法、イベント登壇などを発信します。サービスに関するご質問は、各サービス窓口までご連絡ください。

20230215130734

Cloudflare WAF の活用法: Rate limiting の効果的な利用についての考察

はじめに

こんにちは!マネーフォワード CISO室 プロダクトセキュリティ部の中川 (@teramirai) です。普段は WAF の導入・運用や AeyeScan を用いた脆弱性診断を担当しています。

弊社では Cloudflare WAF を第一の選択肢としており、CISO室で WAF の導入・運用を支援しています。

本記事では、Cloudflare WAF が提案している Rate limiting(レートリミット)の各ユースケースについて、弊社が Cloudflare WAF を運用してきた経験から考察していきます。

Cloudflare におけるレートリミットについて

ドキュメント

以下の2つが公式ドキュメントです。 「レートリミットって何?」という方は、まずは「Learning Center」の記事をご一読ください。

レートリミット機能の種類

Cloudflare WAF においてレートリミット契約は2種類あります。 公式ページによると IP based Rate limiting は Free Plan 以上で利用可能なのに対し、Advanced Rate limiting は一番上の Enterprise Plan を契約した上で、さらにオプション購入が必要となっています。 Advanced Rate limiting は IP 以外の様々な特徴を元に条件を設定できるので高度なルール設定が可能となるのですが、利用可能プランの制約もあるため敷居も高いように思えます。 翻って IP based Rate limiting は誰にでも門戸が開放されているようですね。

レートリミットが有効なケースについての考察

本記事では「Free Plan でも利用可能な "IP based" Rate limiting を使ってどこまでできるか?」という観点で考察していきます。

本家のドキュメントでは、Rate limiting rules > Best practices というページが用意されており、一般的なユースケースを想定した設定例が多数紹介されています。

本記事を執筆した2025年5月時点で紹介されている21種類の設定例のうち、8個が IP based Rate limiting 単体でも設定可能でした。大きく分けて3つの利用方法が紹介されていましたので、それぞれについて私の経験を踏まえて考察していきます。

1. Protecting against credential stuffing / 不正ログイン防止

目的: 攻撃者による複数回の不正ログインの試みをブロックすることを目的とした設定

Money Forward ID Login Page

2024年8月に弊社も不正ログインの被害を受けた経験があり、不正ログイン対策については特に重点的に取り組んできました。

Best practices における設定例としては、以下の AND 条件に該当したリクエストに対して Managed Challenge を要求するルールが記載されています。 - 同一 IP から POST /login 宛に届いたリクエスト - 1分間に4リクエスト以上の頻度 - レスポンスコードが 401 or 403

有効なケース

この設定例をそのまま使用できるのは、認証が成功/失敗した場合に異なるレスポンスコードを返している場合です。 つまり、ログイン成功時は 200 を返していて、ログイン失敗時は 401 を返すアプリケーションであればレスポンスコードからログインの成否を判定できるので、この条件を使ってレートリミットの判定を行うことができるというわけです。

普通にレートリミットを設定しただけでは、ログイン試行回数をカウントすることになります。そのため、何かをきっかけにログイン数が急増した場合にもレートリミットが発動する可能性があります。Counting characteristics としてレスポンスコードまで確認した上でカウントすることにより、ブルートフォース攻撃にフォーカスし、精度を上げることができるのではないかと思います。

苦手なケース

  • 漏洩した認証情報(ID/パスワードセット)を使用した不正ログインのように、ログイン試行が一発で成功する場合はレートリミットが発動しづらいことが想定されます。
  • セキュリティの世界には「多層防御」という考え方があります。不正ログインの防止自体はレートリミットという単一の防御機構で守れるものではなく、reCAPTCHA のような Bot 対策や二要素認証といった複数のセキュリティ機構を組み合わせて対策する必要があります。

3段階のルール

Best practices の例で興味深いのは、同じ目的のルールを若干設定を変えて3種類設定していることです。

ルール 検知するイベント 設定条件 レート ルールアクション
1 "短期間"で複数回のログイン失敗 同一IPから POST /login 宛に届いたリクエストのうち、レスポンスが 401403 のもの 4リクエスト / 1分 Managed Challenge
2 "中期間"で多数のログイン失敗 同一IPから POST /login 宛に届いたリクエストのうち、レスポンスが 401403 のもの 10リクエスト / 10分 Managed Challenge
3 "長期間"で、通常のユーザーにおいて想定される試行数を超える多数のログイン失敗 同一IPから POST /login 宛に届いたリクエストのうち、レスポンスが 401403 のもの 20リクエスト / 1時間 対象Hostに対する全てのリクエストを1日間 Block
  1. 一つ目のルールでは、自動化された試みだけではなく、通常のユーザーもレートに引っかかる可能性があります。なので、ここではアクションは Managed Challenge とし、人間によるアクセスであれば Challenge 判定画面が出た後、引き続きログインを試行できるようにしています。

  2. 二つ目のルールでは、10分間に10回失敗した場合としています。自動化された機械的なリクエストはルール1で止められるケースがほとんどだと思いますが、仮に毎分1回というスローペースでログイン試行した場合でもこのルールで検知することができます。

  3. 三つ目のルールでは、1時間に20回ログイン試行をして失敗した場合、ログインパスだけではなくサイト全体へのアクセスを1日不可としています。サイトによるかもしれませんが、通常は20回もログインに失敗するのは異常なイベントです。多くのユーザーは途中でパスワードリセットを選ぶでしょう。自動化されたログインや IT スキルのある攻撃者によるログイン試行はルール2までで止められると思うのですが、もしかすると誰かが知り合いのユーザーになりすましてログインをしようとするかもしれませんね。人間による手動ログインだとしても20回も試行するのはセキュリティの観点から許容できないということでこのルールを設けたのかもしれません。対象サイト全体へのアクセスを禁じるのはいささか Too much な気もしますが、こういった設定もできるという可能性を設定例として示してくれています。

2. Prevent content scraping (via query string) / (クエリストリングを利用した) コンテンツスクレイピング防止

目的: ある特定のページを対象として、想定以上の過剰なリクエストを止めることを目的とした設定

EC サイトの商品ページにおいて、商品の価格を取得するためのスクレイピングを防止する設定例が紹介されています。 パスに加えて、クエリ action=lookup_price を条件(Expression)として用いることができるという紹介でした。

この例でも、緩いルール (10リクエスト / 2分, Managed Challenge) と厳しいルール (20リクエスト / 5分, Block) を二段構えで設定していますね。Bot はルール1で止められたはずなので、ルール2で閾値をより人間のユーザーにフォーカスして調整できる利点があるように思えます。 公式サイトにも以下のように記載されています。

the two rules will help reduce false positives in case of persistent (but legitimate) visitors.

3. Limit requests from bots / Botからのリクエスト制限

目的: Bot からのアクセスを制限することを目的とした設定

Best practices の例では、レスポンスが 401 または 403 のリクエストが3分間に5回来た場合を閾値とし、レートを超えた場合に Managed Challenge を要求しています。

WAF を運用していると、頻繁に脆弱性スキャナーによるアクセスが来ますよね。 Cloudflare WAF のルールでいうと Information Disclosure に分類される攻撃では、どちらかというと 404 を返すケースが多いと感じています。 例えば、WordPress を利用したサイトではないのに /wp- から始まるパスにアクセスを試みていたり、PHP を使っていないサイトでも phpinfo.php にアクセスしてきたり、といったイベントログはとても多いです。

実際の例として、弊社のとあるサイトの1ヶ月の検知状況を「Path が wp- で始まる」という条件でフィルターしたものを見てみましょう。

Cloudflare Dashboard Event Page

WordPress のサイトではないのですが、wp- から始まるパスに対して何千もリクエストが来ていて、ほとんどが 404 を返していました。この画面は5%サンプル値ですので、実際には約20倍のリクエスト (≒ 9万リクエスト) 来ていたと推定されます。

Cloudflare Dashboard Event - Paths

このサイトではキャッシュ機能は有効化しておらず、WAF のルールに合致しなかった85%のリクエストは Origin サーバーに届きました。

Cloudflare Dashboard Event - Cache Statuses

海外からの偵察のためのリクエストに、弊社のマシンリソースが消費されていたことになります。 弊社では約100の本番環境の Zone を運用しており、このようなリクエストは数えきれないほど日常的に届いています。 Cloudflare の裏(Origin)には AWS でいうと CloudFront・ALB・EC2 が控えている構成が多いかと思いますが、リクエスト数・データ転送量・vCPU によって従量制で課金されるかと思います。 「塵も積もれば山となる」ということわざがありますが、Bot 相手にリソースが消費されるのはもったいないですよね。

Cloudflare Dashboard Event - Countries

ルールの細かい設定値は実際のサイトの特性に合わせて調整が必要ですが、レートリミットを適切に利用することで、Bot からのリクエストを WAF で止め、 Origin に流さないというメリットについてご理解いただけたのではないでしょうか。

まとめ

ここまで、Cloudflare の推奨する設定例を元にレートリミットについて考えてみました。

個々のプロダクトの特性に合わせて適切なレートリミットを設定するというのはなかなか大変な作業でもあり、プロダクトチームの協力も欠かせません。「どんなページがサイトに存在して、レートリミットを活用して価値を出せるポイントはあるか?」ということを私たちセキュリティエンジニアがプロダクトチームに入り込んで実現していく必要があるからです。

このように一朝一夕では解決できない課題ではありますが、セキュリティとプロダクトの両面からアプローチすることで、より安全で効果的なシステムを構築していきたいと思います。

採用情報

現在、私たちのチームでは Senior Security Specialist を募集しています。日本人と外国籍メンバーの両方が活躍できるチームです。 興味をお持ちの方は 採用サイト からぜひチェックしてみてください。 お待ちしております!

関連記事

マネーフォワード CISO室は、セキュリティベンダー様の事例記事として紹介いただいております。