ChatGPTへのメッセージ送信前、Cloudflareはあなたのブラウザで何かを実行している

ChatGPTにメッセージを入力するたびに、Cloudflare Turnstileと呼ばれるプログラムがバックグラウンドでひっそりと動いている。セキュリティ研究者がネットワークトラフィックからこのプログラムを377件解読したところ、一般的なブラウザフィンガープリンティングを大きく超える仕組みが明らかになった。

55項目、3層構造のチェック

このプログラムが収集するデータは55種類にのぼり、以下の3つの層に分類される。

Layer 1: ブラウザフィンガープリント

  • WebGL(8項目): GPUベンダー名・レンダラー情報など
  • スクリーン(8項目): 解像度、色深度、有効表示領域など
  • ハードウェア(5項目): CPUコア数、搭載メモリ、タッチポイント数など
  • フォント計測(4項目): 非表示のdiv要素を生成し、特定フォントでテキストを描画して寸法を測定
  • DOM操作・ストレージ(計13項目): localStorage にフィンガープリントを保存し、ページ再読み込みをまたいで継続的に追跡

Layer 2: Cloudflareネットワーク情報

  • エッジサーバが付与するヘッダから、接続元都市・緯度経度・IPアドレス・地域を取得。Cloudflareのネットワークを経由していないリクエストではこれらの値が欠落するため、直接オリジンサーバに接続するボットを検知できる。

Layer 3: ChatGPTのReactアプリ状態

ここが最も注目すべき点だ。プログラムは __reactRouterContextloaderDataclientBootstrap といったChatGPT固有のReact内部状態を直接参照する。つまりTurnstileは「本物のブラウザが動いているか」だけでなく、「本物のブラウザ上でChatGPTのSPAが完全に起動しているか」まで検証している。ブラウザフィンガープリントを偽装しても、実際にChatGPTのSPAをレンダリングしていないボットはここで弾かれる。

暗号化の仕組みと解読方法

Turnstileのバイトコードは暗号化されて届く。サーバはレスポンス内の turnstile.dx フィールドに約28,000文字のBase64データを送信し、これはリクエストごとに変化する。

外側の暗号化はprepareリクエストの p トークンとのXOR演算で解除できる。両者は同一のHTTPやり取りの中に存在するため、復号は難しくない。

内側には19KBの暗号化ブロブが存在し、最初は performance.now() 由来のエフェメラルキーを使用していると思われた。しかしバイトコードを詳しく調べると、XORキーそのものがバイトコード内に 97.35 という浮動小数点リテラルとして埋め込まれていることが判明。377件中すべてのリクエストで、この値を使えば正しいJSONに復号できることが確認された。

復号に必要なものは、HTTPリクエストとレスポンスだけだ。

ボット対策の最前線

解読されたプログラムは、28種類のオペコード(ADD、XOR、CALL、JSON_STRINGIFYなど)を持つカスタムVMで動作し、レジスタのアドレスはリクエストごとにランダム化される。

この仕組みは、現代のボット対策がどこまで深く踏み込んでいるかを示している。GPUの種類やフォントの描画寸法といった低レベルな情報から、アプリケーション固有のJavaScript状態まで、ブラウザ環境全体を丸ごと検証することで、巧妙なボットを排除しようとしている。裏を返せば、プライバシーの観点から「どこまでが許容範囲か」という問いを改めて提起している。


元記事: ChatGPT won’t let you type until Cloudflare reads your React state