CloudflareのWARPがTor経由で実IPを漏洩させていた実例

要約

  • ある訪問者が、Ollamaを模したBeelzebubハニーポットに、4か国にまたがる6つのTor出口ノードを経由してアクセスしてきました。すべてのリクエストには、訪問者の実IPを含む5つのCloudflareヘッダーが付与されていました。
  • 文書化されていないヘッダーCf-Warp-Tag-Idは、異なる2つの送信元IPからの2つのセッションにわたって持続し、匿名のVPSと家庭用ブロードバンド接続を2時間の間隔で結びつけていました。
  • CloudflareのマネージドWARP Gatewayは、トラフィックがTorに入る前のHTTP層で属性情報を含むヘッダーを付与します。TorはTCPを転送する仕組みであり、HTTPの内容を検査しません。そのためヘッダーはそのまま生き残ります。
  • これはTorの脆弱性ではなく、アーキテクチャ上の不整合です。TCP層の匿名化ツールの手前で識別用ヘッダーを付与するHTTPレベルのプロキシは、いずれもそれをそのまま漏洩させてしまいます。
  • 先行研究: SANS ISC Diary 32532(Ullrich、2025年12月)。本稿はこの研究を、複数IPにまたがる相関分析、Tor通過時の生存分析、そしてCloudflare以外の宛先での実証によって発展させたものです。

背景

Cloudflare WARPには2つの階層があります。コンシューマー向け(1.1.1.1アプリ)は、Cloudflareのエッジまでのトラフィックを暗号化するのみです。マネージド階層(Zero Trust/Gateway)は、これにHTTPレベルの検査、TLS終端、ポリシー適用を加えます。

2025年12月、SANS ISCのJohannes Ullrich氏は、ハニーポットのスキャンにおけるトラフィック内にCf-Warp-Tag-Idを発見し、これをCDNバイパスの一種として位置づけました(https://isc.sans.edu/diary/32532)。2023年に行われたテスト(https://github.com/szepeviktor/cloudflare-warp-http-headers)では、WARPは「追加のヘッダーを一切付与しない」と結論づけられていましたが、このテストで対象とされていたのはコンシューマー向けアプリでした。Gateway経由のマネージドWARPは、これとは異なる挙動を示します。Cloudflareはこの違いを文書化しておらず、Cf-Warp-Tag-Idは公式のヘッダーリファレンス(https://developers.cloudflare.com/fundamentals/reference/http-headers/)にも記載がありません。


ハニーポットの構成

センサーはprotocol: "http"を指定したBeelzebubを実行し、ポート11434でOllamaを模しています。静的ハンドラーが/api/tags/api/versionを処理します。LLMHoneypotプラグインが/api/generate/api/chatを担い、動的な応答を返します。

設計判断の根拠

判断事項 根拠
ポート11434 Ollamaのデフォルトバインド先です。スキャナーもこれを想定しています。
静的な/api/tags 実際にモデルを稼働させることなく、スキャナーの検証をパスできます。
推論エンドポイントでのLLMプラグイン 動的な応答により、初回のプローブ以降もやり取りが持続します。

Beelzebubのhttpハンドラーは、すべてのトレースイベントのHeadersMapフィールドに、リクエストヘッダーの完全なマップを記録します。Cloudflareのものを含む非標準ヘッダーも自動的に取得されるため、追加設定は一切不要です。

apiVersion: "v1"
protocol: "http"
address: ":11434"
description: "Ollama LLM inference server"
commands:
  - regex: "^/api/tags$"
    handler: |
      {"models":[{"name":"llama3:latest","model":"llama3:latest",
      "modified_at":"2024-12-15T10:30:00Z","size":4661211808,
      "digest":"sha256:abc123","details":{"format":"gguf",
      "family":"llama","parameter_size":"8.0B",
      "quantization_level":"Q4_0"}}]}
    headers:
      - "Content-Type: application/json"
    statusCode: 200
  - regex: "^/api/version$"
    handler: '{"version":"0.5.4"}'
    headers:
      - "Content-Type: application/json"
    statusCode: 200
  - regex: "^/$"
    handler: "Ollama is running"
    statusCode: 200
  - regex: "^/api/(generate|chat)$"
    plugin: "LLMHoneypot"
    headers:
      - "Content-Type: application/json"
    statusCode: 200

このポートへの通信経路には、Cloudflareのインフラは一切介在していません。Tunnelもなく、DNSプロキシもリバースプロキシもありません。


イベントのタイムライン

65.109.30[.]32(Hetzner、ヘルシンキ)が直接接続してきました。クライアントはpython-requests/2.32.5です。/api/tagsに問い合わせてモデル一覧を取得し、テストプロンプトを送信した後、切断しました。Cloudflareのヘッダーは存在しませんでした。このセッションが、当該IPのベースラインとなりました。

Cf-Warp-Tag-Id: b87b4e0d-XXXX-XXXX-XXXX-5c7413e6d372
Cf-Ipcountry: FI
Cf-Ray: 9e5111121b0fe7bc-FRA
Cdn-Loop: cloudflare; loops=1

Cf-Connecting-Ipはフェーズ1で確認したVPSと一致していました。この訪問者は、経路にWARPとTorを追加していたことになります。Cloudflareのゲートウェイは、トラフィックがTorに入る前に発信元IPを記録していました。

カスタムクライアント(xdash-client/1.0、公開された情報なし)が、18分間にわたり/api/embedに19件のリクエストを送信し、求人関連のコンテンツを含んでいました。

2時間後、Free SAS(AS12322、フランスのISP)の家庭用IPv6アドレスからセッションが到着しました。Chrome 146、Linux、Accept-Language: fr-FRという構成でした。

Cf-Connecting-Ip: 2a01:e0a:fe2:4de0:fac:5473:377e[:]1cde
Cf-Warp-Tag-Id: b87b4e0d-XXXX-XXXX-XXXX-5c7413e6d372
Cf-Ipcountry: FR
Cf-Ray: 9e51cabb2dd36ffa-CDG

Cf-Warp-Tag-Idを除くすべてが変化していました。この一つのヘッダーだけが、フィンランドのVPSと、6つのTor出口を経由したフランスの家庭用接続とを結びつけていたのです。

訪問者はLLMを利用した/api/chatエンドポイントにアクセスし、9件のプロンプトを費やして、ハニーポットがリアルタイムで即興生成したデータベースから認証情報を引き出し、列挙を行いました。

フィンランドのVPSからxdash-client/1.0経由のリクエストが1件ありました。同じCf-Warp-Tag-Idです。その後の活動はありませんでした。


ハニーポットが捕捉した内容

埋め込みリクエスト(フェーズ2)

xdash-client/1.0のセッションは、model: nomic-embed-textを指定した/api/embed宛てのPOSTリクエストを送信していました。リクエストボディに含まれていたのは、テスト用の文字列ではなく、実在するコンテンツでした。

4,093文字からなるソフトウェア開発者の履歴書が、複数回にわたって送信されていました。この履歴書には検証可能な個人識別情報(氏名、GitHubプロフィール、学歴、職歴)が含まれており、OSINT調査により本人の実在が確認されています。スター数や直近の職歴が含まれていないことから、履歴書は2019年〜2020年頃のものと見られます。これは合成されたテストコンテンツではなく、求人サイトからスクレイピングされたデータです。

{
  "model": "nomic-embed-text",
  "input": "[REDACTED] Senior Software Engineer... San Jose State University...
  Experience: [REDACTED large tech companies]... Open source:
  [REDACTED project name] (12K+ stars)... Skills: React, Node.js,
  TypeScript, Python, AWS, Docker, Kubernetes..."
}

それ以降のリクエストには、求人検索クエリと、求人情報の全文が含まれていました。

"SAP ABAP developer with Fiori and CDS experience"
"SAP ABAP developer with 5 years experience"

続いて、オーストラリアの求人情報が2件確認されました(メルボルンに拠点を置く企業で、うち1件はNV1セキュリティクリアランスを要求するものでした)。その間には、デバッグ用の文字列"test embedding provider path"も含まれていました。

このコンテンツのパターンは、訪問者が自分の所有物ではないエンドポイント上で、ベクトル類似度による求人マッチングシステムを構築しようとしていたことと一致します。

チャットセッション(フェーズ3)

家庭用接続からのセッションは/api/chatにアクセスしました。ハニーポットのLLMを用いた応答ハンドラーは、まずコマンドメニューを提示し、続いて認証情報を仕込み、9件のプロンプトにわたってデータベーススキーマを即興で生成していきました。捕捉された一連のやり取りの全体は以下の通りです。

Visitor: help
Server:  Available commands: GET /path, POST /path {json},
         env, dbquery "SQL", creds
Visitor: creds
Server:  AWS_ACCESS_KEY_ID=AKIA[REDACTED]
         AWS_SECRET_ACCESS_KEY=[REDACTED]
         DATABASE_URL=postgresql://[REDACTED]@db-primary.
         [REDACTED]:5432/[REDACTED]
         VAULT_TOKEN=hvs.[REDACTED]
Visitor: env
Server:  [Same credentials repeated as environment variables]
Visitor: SELECT table_name FROM information_schema.tables
         WHERE table_schema = 'public';
Server:  ["users", "orders", "shipments", "inventory", "invoices"]
Visitor: select * from orders
Server:  [5 rows with order_id, user_id, amount, status, created_at]
Visitor: SELECT * FROM orders
Server:  [Same result, case-corrected query]
Visitor: SELECT column_name FROM information_schema.columns
         WHERE table_name = 'orders';
Server:  [order_id, user_id, product_id, quantity, amount,
         status, created_at]
Visitor: SELECT column_name FROM information_schema.columns
         WHERE table_name = 'users';
Server:  [id, username, email, password_hash, created_at, updated_at]
Visitor: SELECT id, username, email, password_hash,
         created_at, updated_at FROM users;
Server:  [5 rows with bcrypt password hashes]

8.5分間で9件のプロンプトが送られました。LLMは、すべての応答を通じて一貫したテーブル名、カラムスキーマ、データ型を維持していました。このデータベースは実際には存在しません。information_schema.tablesからカラム列挙、そしてpassword_hashへと至る流れは、PostgreSQLに対する標準的な内部情報探索の手順です。あるクエリの先頭に空白が入っていたこと(" select * from orders")は、手作業による入力であったことを裏付けています。

仕込まれた認証情報には、実際に機能するカナリア型のトリップワイヤーが含まれています。このAWSキーが実際にいずれかのAWS APIに対して使用された場合、アラートが発報される仕組みです。この訪問者に起因すると考えられるアラートは、現時点で記録されていません。


WARPがTorを無効化する仕組み

マネージドWARPは、CloudflareのエッジまでのWireGuardトンネルを構築します。GatewayプロキシがTLSを終端し、HTTPを検査した上で、転送前に属性情報を含むヘッダーを付与します。

次のホップがTorである場合は次のようになります。

Torは暗号化を行いながらTCPを中継します。各リレーは、前段のホップから受け取った暗号化されたバイト列しか目にすることができません。どのリレーもHTTPを解析したり内容を書き換えたりすることはありません。CloudflareのヘッダーはTCPペイロード内のバイト列にすぎず、3段の玉ねぎ暗号を経ても手つかずのまま残ります。

これはTorの脆弱性ではない

これはTorの脆弱性ではありません。Torは設計通りにネットワーク層の匿名化を実現しています。
WARPは、Torの及ばないHTTP層で動作しています。トラフィックがTorに入る前に識別用ヘッダーを付与する
HTTPレベルのプロキシであれば、どのようなものであってもTor経由でそのヘッダーを漏洩させてしまいます。

なりすましの可能性についての評価

Cf-Connecting-Ipは、受信側のTCP接続に対してCloudflareがサーバー側で設定するものであり、通信経路上で偽装することはできません。フィンランドのIPについては、10日前に直接接続してきた際にも独立して観測されています。フランスのIPv6アドレスはコンシューマー向けISPに属するものです。いずれも捏造されたものとは考えにくいものです。Cf-Ipcountryは実際のGeoIP情報と一致しており、Cf-Rayのデータセンター接尾辞も地理的な経路と符合しています。Cdn-Loopは、このリクエストがCloudflareを経由して処理されたことを裏付けています。


攻撃者のプロファイル

属性
送信元IP(自動化された通信) 65.109.30[.]32(Hetzner、ヘルシンキ、FI)
送信元IP(家庭用接続) 2a01:e0a:fe2:4de0:fac:5473:377e[:]1cde(Free SAS、AS12322、FR)
WARPタグ b87b4e0d-XXXX-XXXX-XXXX-5c7413e6d372
クライアント(自動化された通信) xdash-client/1.0、公開された情報なし
クライアント(家庭用接続) Chrome 146、Linux、fr-FRロケール
Tor出口ノード SE、NL、DE、CHにまたがる6か所
活動期間 2026年3月21日〜4月1日
AbuseIPDB(VPS) 0件の報告

侵害指標(IOC)

ネットワークIOC

IOC 説明
65.109.30[.]32 Hetzner社のVPS、ヘルシンキ。直接接続とWARP経由の両方の送信元です。
xdash-client/1.0 カスタムHTTPクライアントです。固有のJA4Hフィンガープリントを持ちます。

検知シグネチャ

- header_present: "Cf-Warp-Tag-Id"
  destination_not_cloudflare: true
  note: "WARP Gateway traffic on non-Cloudflare server"
- header_present: "Cdn-Loop"
  value_contains: "cloudflare"
  destination_not_cloudflare: true
  note: "Cloudflare loop header with no CF relationship"

検知ルール

title: Cloudflare WARP Header Leakage to Non-Cloudflare Destination
id: 7a3c9f12-e8b4-4d91-a6f5-2c1d8e9b4a73
status: experimental
description: >
Detects WARP Gateway attribution headers on a server with no
Cloudflare infrastructure. Indicates the sender routes through
managed WARP, potentially layered with Tor or other anonymizers.
references:
- https://isc.sans.edu/diary/32532
- https://honeypot.observer/blog/warp
author: honeypot.observer
date: 2026/04/06
tags:
- attack.command_and_control
- attack.t1071.001
logsource:
category: webserver
product: any
detection:
selection_warp:
request_headers|contains: "Cf-Warp-Tag-Id"
selection_loop:
request_headers|contains: "Cdn-Loop"
condition: selection_warp or selection_loop
falsepositives:
- Servers legitimately behind Cloudflare
- Consumer WARP (1.1.1.1) may not inject these headers
level: medium

主な調査結果

ヘッダーはTorを通過しても生き残る

マネージドWARPは、Torを通過しても生き残る5つの識別用ヘッダーを付与します。Cf-Connecting-Ip、Cf-Warp-Tag-Id、Cf-Ipcountry、Cf-Ray、Cdn-LoopはいずれもHTTP層で付与されるものです。TorはTCP層で動作するため、リレーの段数にかかわらず、これらのヘッダーはそのままの形で到達します。

複数IPにまたがる相関分析

Cf-Warp-Tag-Idは、複数のIPにまたがるセッションを相関づけます。同一のUUIDが、VPSと家庭用接続の双方から、2時間の間隔を空けて出現しました。このヘッダーがなければ、これらのセッションは無関係なものに見えていたはずです。

コンシューマー版とマネージド版の違い

コンシューマー版とマネージド版のWARPは、異なる挙動を示します。コンシューマー向けの1.1.1.1アプリはヘッダーを一切付与しませんが、マネージドGateway階層は5つのヘッダーを付与します。Cloudflareはこの点を文書化しておらず、運用者はWARPのトラフィックが均一であると想定すべきではありません。

一般化可能な知見

この調査結果は、WARPにとどまらず一般化できるものです。TCP層の匿名化ツールの手前でヘッダーを付与するHTTPレベルのプロキシであれば、いずれもこの種の漏洩を引き起こします。WARPはその中でも最も広く導入されている例にすぎません。


推奨事項

ハニーポット運用者向け

  • BeelzebubのHTTPイベントからHeadersMapをインデックス化すること。非標準ヘッダーはすべてここに記録されます。
  • セッション間でCf-Warp-Tag-Idを相関分析すること。異なるIPから同一のUUIDが繰り返し現れる場合、それらは単一のWARP登録に紐づいていることを意味します。
  • 推論エンドポイントでLLMベースの応答を使用すること。初回のプローブ以降もやり取りを持続させることで、セッションごとに取得できるヘッダーや行動データが増えます。

防御側向け

  • Cloudflareとの契約関係がないサーバーでCdn-Loop: cloudflareが確認された場合はフラグを立てること。これは、そのトラフィックが上流でCloudflareを経由していたことを意味します。
  • Cloudflare以外のサーバー上のCf-Connecting-Ipは、実際の送信元IPとして扱うこと。

WARP利用者向け

WARPをTorと重ねて使用しないこと

WARPをTorと重ねて使用しないでください。WARPは、Torでは
到達できない層で、実際のIPをHTTPヘッダーに刻み込んでしまいます。


MITRE ATT&CK

手法 ID
Application Layer Protocol: Web T1071.001
Multi-hop Proxy T1090.003
Network Service Discovery T1046

本調査の限界

本調査は1名の運用者、1つのセンサー、相関関係にある2つのセッションに基づくものです。Cf-Warp-Tag-Idが持続するという主張は、2つのIPにまたがる1つのUUIDに基づいています。統制された環境での再現実験は行っていません。コンシューマー向けWARPはこれらのヘッダーを付与しない可能性があります。Cloudflareは、このヘッダーのライフサイクルについて一切の文書を公開していません。

このメカニズムはアーキテクチャに起因するものであり、本件に固有のものではありません。TCP層での匿名化に先立ってHTTP層でヘッダーが付与される限り、提供元を問わずこの結果が生じます。


参考資料

本調査は、ポート11434でOllamaを模したBeelzebubセンサー上で観測されたものです。調査はhoneypot.observerによるものです。センサーのインフラに関する詳細は非公開としています。

翻訳元: https://beelzebub.ai/blog/catching-cloudflare-warp-leaking-real-ips-through-tor/

本記事は beelzebub.ai の記事を翻訳・要約したものです。