Referer偽装型HTTP GET Flood攻撃分析:Cloudflareログから見るL7 DDoS対策事例

本文中に含まれるドメイン名や数値は、公開用に一部変更しています。
数多く存在するDDoS攻撃の一例として参考にしてください。

概要

4月の某日、Cloudflare Security AnalyticsとHTTP Trafficログを確認していたところ、通常のアクセスとは考えにくい大量のHTTPリクエストを確認しました。

一見すると、さまざまな外部Refererから流入している通常のWebトラフィックのようにも見えます。しかし、ログを細かく確認すると、通常のユーザー流入とは考えにくい特徴が複数ありました。

今回確認できた主な特徴は次のとおりです。

- HTTP MethodはほぼGET
- 攻撃対象のPathはほとんどが `/`
- Refererは有名サイトのドメインに偽装
- User-AgentはAndroid / Windows Chrome系のブラウザに偽装
- Cloudflare HTTP DDoS Rulesでknown botnet / known bad sourcesとして大量にBlock
- Blockされたトラフィックとは別に、同じ時間帯で200 OKのレスポンスも大量に存在

今回のケースは、Refererを偽装したルートパスを対象としたHTTP GET Flood攻撃と考えるのが妥当でした。 この攻撃によってOriginサーバーまで大量のトラフィックが流れてしまったので、下記に書いたことを確認し、Custom WAF Ruleを追加し、不審なリクエストに対する追加対策を行いました。


1. Cloudflareの自動防御で確認されたトラフィック

Cloudflareの攻撃防御システムで自動的にBlockされたイベントは、約2,777万件でした。

Referer偽装攻撃グラフ

Actionで見ると、ほとんどがBlockとして処理されており、HTTP MethodはほぼすべてGETでした。

Total blocked events : 約 27.77M
Action               : Block
HTTP Method          : GET

HTTP DDoS Rulesでは、次のような検知が確認されました。

HTTP requests from known botnet        : 約 25.73M
Requests coming from known bad sources : 約 2.04M

つまりCloudflareは、このトラフィックを単なる通常リクエストではなく、既知のBotnetまたは悪性ソースに由来するL7 DDoSトラフィックとして判断し、Blockしたと考えられます。

CloudflareのHTTP DDoS Attack Protection managed rulesetは、アプリケーション層、つまりL7の既知のDDoS攻撃ベクトル、不審なパターン、プロトコル違反、OriginやCacheに過度に集中するトラフィックなどを検出するための管理型ルールセットです。

参考文書:


2. 攻撃の中心Pathは/

当初は、/notice_on.asp/realtime.asp/main.aspのような動的ページも攻撃対象の候補として考えられました。

しかしPath単位で確認すると、実際の攻撃の中心は特定のASPファイルではなく、サイトのルートパスである/でした。

Cloudflareの自動防御によってBlockされたトラフィックのPathは、次のような傾向でした。

/                                      約 27.76M
/cdn-cgi/challenge-platform/...        数十件程度
/favicon.ico                           少量

全体のBlockイベントが約2,777万件であったことを考えると、自動的にBlockされたリクエストのほとんどが/に集中していたと見てよいでしょう。

したがって今回の攻撃は、ログインページ、API、掲示板、特定のASPファイルを狙ったものというより、トップページのルートパスに対して大量のGETリクエストを発生させるHTTP GET Floodに近いものでした。

整理すると、次のようになります。

攻撃Method : GET
攻撃Path   : /
攻撃種別   : L7 HTTP GET Flood
偽装要素   : Referer偽装 + 一般ブラウザ風User-Agent
検知根拠   : Cloudflare HTTP DDoS Rules - known botnet / bad sources

3. Refererは通常流入のように見せるために偽装

Referer一覧を見ると、最初は複数の有名サイトから流入しているように見えます。

Referer偽装攻撃内訳

HTTP 200 OKのトラフィック側でも、似たようなRefererの傾向が確認されました。

Referer 200 OK通過内訳

Referer 200 OK通過内訳

通常のWeb流入であれば、検索エンジン、SNS、広告キャンペーン、特定の外部リンクなど、ある程度の偏りが出るのが自然です。

しかし今回のログでは、互いに関連性の薄い有名ドメインが、ほぼ似たようなボリュームで繰り返し出現していました。これは自然なReferer分布とは考えにくいです。

そのため、これらのトラフィックは「該当サイトから実際に流入したアクセス」ではなく、攻撃者がHTTP Refererヘッダーを任意に設定し、通常の外部流入のように見せかけたものだと判断しました。

つまり今回の攻撃は、Referer偽装型HTTP GET Flood攻撃だと判断しました。


4. User-Agentも通常ブラウザのように偽装

User-Agentにも、繰り返し使われているパターンがありました。

Referer User-Agent

代表的には、次のような系統が多く確認されました。

Mozilla/5.0 (Linux; Android 14; SM-S928B) ...
Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...

表面上は、最新のAndroid端末やWindows Chromeブラウザのように見えます。

しかし、同一または非常によく似たUser-Agentが数百万件単位で繰り返されている場合、それを自然なユーザー分布と見るのは難しいです。

これはBotが一般的なブラウザに見えるよう、User-Agentをテンプレート化して使用していたものと考えられます。

ただし、ここで注意すべき点があります。

User-AgentだけでBlockするのは危険です。

Windows NT 10.0; Win64; x64やChrome系のUser-Agentは、実際の正常ユーザーでも広く使われます。

そのためUser-Agentは単独のBlock条件ではなく、次のような条件と組み合わせて使うのが安全です。

- 攻撃対象のPath
- 不自然なReferer
- 過剰なリクエスト数
- Bot Score
- Verified Botの除外
- Rate Limitの超過

5. Edge Status Code 200 OKトラフィックはどう解釈すべきか

同じ時間帯のHTTP Trafficグラフで Edge Status Code200 OKだけをフィルタリングしても、大量のリクエストが確認されました。

Referer 200 OK

Path単位で見ると、200 OKトラフィックでも/が最も多くなっていました。

ここで重要なのは、200 OKが必ずしもOriginサーバーまで到達したことを意味しない点です。

200 OKには、次の3つの可能性があります。

1. Originサーバーが実際に200 OKを返した
2. Cloudflare Cacheが200 OKを返した
3. Cloudflare Edge、Worker、Challenge/Error pageの処理過程で200 OKが返された

したがって、「Cloudflareの自動防御を通過したトラフィックがすべてOriginまで到達した」と断定することはできません。

実運用では、次のフィールドを併せて確認する必要があります。

ClientRequestPath
ClientRequestReferer
ClientRequestUserAgent
EdgeResponseStatus
OriginResponseStatus
CacheCacheStatus
OriginResponseTime
RayID

判断基準としては、次のように考えるとよいです。

CacheCacheStatus = hit
→ Cloudflare Edgeで応答した可能性が高い

CacheCacheStatus = miss / dynamic / bypass
OriginResponseStatus = 200
→ Originまで到達した可能性が高い

EdgeResponseStatus = 200
OriginResponseStatusが空
→ EdgeまたはCloudflare機能側で応答した可能性がある

今回の攻撃では、CacheCacheStatus = miss / dynamic / bypassのトラフィックがOriginまで流入し、サーバー負荷を発生させた可能性が高いと考えました。

ただし、これを最終判断するにはCloudflare側のログだけではなく、Origin側のaccess_log、CPU使用率、Webサーバーやアプリケーションの応答時間も併せて確認する必要があります。


6. /cdn-cgi/challenge-platform/は攻撃対象ではない

Path一覧には、/cdn-cgi/challenge-platform/...へのリクエストも一部見えていました。

しかしこのPathは、攻撃者が直接狙った対象というより、CloudflareのChallenge、Bot Detection、JavaScript Detection関連の処理で利用される管理用Pathと見るべきです。

Cloudflareのドキュメントでも、/cdn-cgi/ endpointはCloudflareの機能のために使われる管理対象のendpointであり、/cdn-cgi/challenge-platform/はJavaScript DetectionなどBot関連機能で利用されると説明されています。

参考文書:

そのため、WAFルールを作成する際に次のような設定は避けるべきです。

悪い例:
- /cdn-cgi/* を一括でBlockする
- /cdn-cgi/challenge-platform/* をBlockする

このPathを誤ってBlockすると、Cloudflare Challengeが正常に動作しなかったり、ユーザーがChallengeループに入ったりする可能性があります。


7. RefererだけでBlockすると危険な理由

今回の攻撃における重要な手がかりはRefererでした。

しかし、RefererだけでBlockするのは危険です。

たとえば、次のようなルールは範囲が広すぎます。

http.referer ne ""

この条件では、Refererを持つすべての外部流入がBlock対象になってしまいます。

検索エンジン、SNS、外部ブログ、広告、取引先サイトからのリンクなど、正常な流入まで一緒に遮断してしまう可能性があります。

逆に、次の条件だけを見ても十分ではありません。

http.referer eq ""

Refererが存在しないNone (direct)のリクエストも攻撃に含まれていましたが、実際のユーザーがアドレスバーにURLを直接入力した場合や、メッセンジャーアプリ、ブラウザ設定、セキュリティポリシーの影響でRefererが付かない場合もあります。

したがってRefererは単独条件としてではなく、次のような条件と組み合わせて使う必要があります。

- Host
- Path
- Method
- Referer
- User-Agent
- Bot判定
- Rate Limit
- Bot Score

Cloudflare Custom Rulesでは、リクエスト条件をフィルタリングし、BlockManaged ChallengeなどのActionを実行できます。

参考文書:


8. 実効性のあるWAFルール例

今回のケースでは、攻撃対象がほとんど/だったため、WAFルールも/を中心に設計するのが効果的です。

以下の例では、実際のドメインをexample.comとして表記しています。

実際に適用する場合は、運用中のドメインに置き換えてください。


Rule 1. ルートパス/への外部RefererリクエストをChallengeする

外部Refererを持つ/へのリクエストのうち、自ドメイン由来のRefererとVerified Botを除外し、Managed Challengeを実行するルールです。

(
  http.request.method eq "GET"
  and http.request.uri.path eq "/"
  and http.referer ne ""
  and not cf.client.bot
  and not http.referer matches r"^https?://(www\.)?example\.com(/|$)"
)

推奨Action:

Managed Challenge

攻撃中で、かつ正常な外部流入がほとんどないサイトであれば、一時的にBlockする選択肢もあります。

ただし、ブログや企業サイトのように外部リンクからの流入がある場合、最初からBlockするのは慎重に判断すべきです。

  • regex matchesは Cloudflare Business/Enterpriseにて使用可能です。Free Planの場合はWildcard条件で代替する方が現実的です。

Rule 2. ルートパス/にRate Limitingを適用する

今回の攻撃は/に集中していたため、Rate Limitingも/を基準に適用するのが効果的です。

Expression:

(
  http.request.method eq "GET"
  and http.request.uri.path eq "/"
  and not cf.client.bot
)

初期しきい値の例:

30 requests / 10 seconds / IP

推奨Action:

Managed Challenge

攻撃が強い場合は、一定時間だけBlockを適用することも検討できます。

Cloudflare Rate Limiting Rulesは、特定のExpressionに一致するリクエストが指定したリクエスト数を超えた場合にActionを実行する機能です。

参考文書:


Rule 3. 攻撃時に繰り返されたUser-Agentパターンに一時的なChallengeを適用する

攻撃時にSM-S928Bや特定のChromeバージョン文字列が繰り返し見えていた場合、それらを一時的な対策ルールとして利用できます。

(
  http.request.method eq "GET"
  and http.request.uri.path eq "/"
  and not cf.client.bot
  and http.referer ne ""
  and http.user_agent matches r"(SM-S928B|Chrome/142\.0\.7444)"
)
  • regex matchesは Cloudflare Business/Enterpriseにて使用可能です。Free Planの場合はWildcard条件で代替する方が現実的です。

推奨Action:

Managed Challenge

このルールは恒久的なルールではなく、攻撃時のパターンに合わせた一時対応ルールとして扱うのが適切です。

Chrome、Windows、Android関連のUser-Agentは正常ユーザーでも広く利用されるため、User-Agent単独でのBlockは避けるべきです。


Rule 4. /cdn-cgi/challenge-platform/を例外として扱う

広範囲のWAFルールを作成する場合は、Cloudflareの管理用Pathを誤ってBlockしないように注意が必要です。

たとえば特定Path全体に強い制御をかける場合は、次のような例外条件を追加しておくと安全です。

and not starts_with(http.request.uri.path, "/cdn-cgi/challenge-platform/")

starts_with()は、Cloudflare Rules languageで文字列が特定の値で始まるかを確認するための関数です。

参考文書:


9. 最終結論

今回のログを見る限り、この攻撃は単なるReferer異常トラフィックではありません。

要点は次のとおりです。

- 攻撃者はサイトのルートパス `/` に大量のGETリクエストを発生させていた
- RefererはSoundCloud、WashingtonPost、YouTube、Amazon、Facebookなどの有名ドメインに偽装されていた
- User-AgentはAndroid端末やWindows Chromeブラウザのように見える形で構成されていた
- Cloudflare HTTP DDoS Protectionは、このうち約2,777万件をknown botnet / bad sourceとしてBlockした
- 一方で、同じ時間帯に200 OKを返した`/`リクエストも大量に確認された
- そのため、自動DDoS防御だけではなく、`/`を中心としたWAFルールとRate Limitingが必要になる

今回のケースから得られる重要な教訓は、次の2点です。

1つ目は、Refererは信頼できる送信元情報ではないということです。

HTTP Refererヘッダーは攻撃者が容易に操作できるため、Refererだけを見て正常流入か攻撃流入かを判断すべきではありません。

2つ目は、200 OKはOrigin到達を意味しないということです。

200 OKはCloudflare Edge、Cache、Worker、Challenge/Error page、Originサーバーのいずれでも発生し得ます。

そのため、実際にOriginへ到達したかどうかを判断するには、OriginResponseStatusCacheCacheStatusOriginResponseTimeなどを併せて確認する必要があります。

最終的に、今回の攻撃は次のように定義できます。

Referer偽装型ルートパス対象L7 HTTP GET Flood攻撃

実務上の対策優先順位は、次のとおりです。

1. Cloudflare HTTP DDoS Protectionを維持する
2. `/`へのRate Limitingを適用する
3. `/`への外部RefererリクエストにManaged Challengeを適用する
4. 攻撃時に繰り返されたUser-Agentパターンは一時的なChallengeルールとして対応する
5. Bot Scoreが利用できる場合は、低スコアのリクエストにChallengeまたはBlockを適用する
6. `/cdn-cgi/challenge-platform/`はBlockしないように例外扱いする
7. Cloudflare LogpushとOrigin access_logを比較し、実際にOriginへ到達したか確認する

Cloudflareの自動防御は、今回の攻撃に対してかなり有効に機能していました。

しかし、自動防御だけですべての攻撃性リクエストを完全に取り除けるわけではありません。

安定した運用を続けるためには、CloudflareのManaged DDoS Protection、Custom WAF Rules、Rate Limiting、Bot Managementなどのセキュリティ機能を組み合わせ、サイトの実トラフィックに合わせた多層防御を構成することが重要です。