何が起きたか
セキュリティ研究者がChatGPTのCloudflare Turnstileボット検知システムを詳細に分析し、377個の暗号化プログラムを復号化した。その結果、ブラウザのGPU情報やWebGL性能、スクリーン解像度といった従来のフィンガープリンティング手法に加え、ChatGPTのReact application内部状態(__reactRouterContext、loaderData、clientBootstrapなど)まで検査していることが判明。単なるボット検知ではなく、アプリケーション層での本物のブラウザ認証を行っている。
背景と経緯
ChatGPTはユーザーがメッセージを入力する際、毎回Turnstileプログラムが自動実行される。Cloudflareはこのプログラムを28,000文字のBase64エンコード暗号化データ(turnstile.dx)として配信し、復号化困難な設計にしていた。しかし研究者がネットワークトラフィックを分析したところ、暗号化キーが外層ではp トークン、内層ではプログラム内に浮動小数点数として埋め込まれていることを発見。この単純な暗号化スキームにより、外部ツールなしで完全な復号化が可能であることが明かされた。
暗号化と復号化の仕組み
暗号化チェーンは以下の構造:
- サーバーがprepare responseで turnstile.dx(Base64エンコード)を送信
- 外層:p tokenで XOR復号化 → 89個のVM命令を取得
- 内層:これらの命令内に埋め込まれた浮動小数点数(例:97.35)がXORキー
- 内層復号化 → 417~580個のVM命令を含む本体プログラム
研究者は50個のリクエストで検証し、50回とも完全に復号化成功。キーが毎回異なるサーバー生成値でありながら、HTTPレスポンス内に埋め込まれているため、攻撃者は準備ステップなしに即座に復号化可能。
検査される55個のプロパティ
Layer 1:ブラウザフィンガープリント(38個)
- WebGL(8個):UNMASKED_VENDOR_WEBGL、UNMASKED_RENDERER_WEBGL、レンダラー情報
- スクリーン(8個):colorDepth、pixelDepth、width、height、availWidth、availHeight、availLeft、availTop
- ハードウェア(5個):hardwareConcurrency、deviceMemory、maxTouchPoints、platform、vendor
- フォント測定(4個):hidden div を作成してフォント描画サイズを計測
- DOM操作(8個):createElement、appendChild、removeChild などの実行痕跡
- ストレージ(5個):localStorage に16進数キー「6f376b6560133c2c」でフィンガープリント保存
Layer 2:Cloudflareネットワーク境界(5個)
サーバーが注入するエッジヘッダー:cfIpCity、cfIpLatitude、cfIpLongitude、cfConnectingIp、userRegion。直接オリジンに接続またはCloudflare以外のプロキシ経由ではこれらの値が欠落。
Layer 3:アプリケーション層(3個)
- __reactRouterContext:React Router v6+ の内部オブジェクト
- loaderData:ルートローダー実行結果
- clientBootstrap:ChatGPT独自のSSRハイドレーション状態
この層が最も重要。JavaScriptを実行せずHTMLだけ読み込むボット、ブラウザAPIをスタブで偽装するツールは検出される。
セキュリティへの意味合い
この検査方法は従来のフィンガープリンティング回避技術を無効化する。単にUser-Agentやheaderを詐称するだけでなく、実際のGPUレンダラーを起動し、React SPA全体を正常に読み込む必要がある。オートメーションフレームワーク(Selenium、Puppeteer、Playwright)でも完全な回避は困難。ただし研究者が暗号化を破ったことで、攻撃側も同じ復号化コードを取得可能になり、検査項目を先読みした上での偽装が理論的には可能になった。
今後の展望
Cloudflareが暗号化強度を向上させるか、鍵導出方法を変更するかが注視される。一方、この分析手法はセキュリティ業界全体に波紋を広げる。他のSaaS企業も同様に暗号化されたクライアント側検査コードを配信していないか検証が進む見通し。業界標準としてどこまでの検査が許容されるかの議論も浮上。
参考リンク
この記事はAI業界の最新動向を速報でお届けする「AI Heartland ニュース」です。
よくある質問
Q. Turnstile の暗号化キーはどこに保管されていますか?
外層はprepareリクエストのpトークンで、内層は実行するVM命令内に浮動小数点数(97.35など)として埋め込まれています。サーバー生成値のため毎回異なりますが、HTTPレスポンスに含まれています。
Q. React内部状態を検査することの意味は?
__reactRouterContext、loaderData、clientBootstrapといったReact固有のプロパティは、JavaScriptが実行されてアプリが正常にハイドレーションされた場合のみ存在します。HTMLだけ読み込むボットやAPIスタブ詐称では検出されます。
Q. Cloudflareエッジヘッダーがない場合はどうなりますか?
cfIpCity、cfIpLatitudeなどのヘッダーはCloudflareネットワーク経由のみ注入されるため、直接オリジンに接続したリクエストではこれらの値が欠落し、ボットと判定される可能性があります。
Q. フォント測定はなぜ必要なのですか?
hidden divを作成してフォント描画サイズを計測することで、ブラウザのフォント表示能力を検証します。これはフィンガープリンティングの一部として機能します。
Q. ローカルストレージへのフィンガープリント保存の目的は何ですか?
16進数キー「6f376b6560133c2c」でフィンガープリントをlocalStorageに保存します。これはブラウザのフィンガープリンティング検査の一部です。