ChatGPTが使用するCloudflareのボット検知システム「Turnstile」の内部構造が、セキュリティ研究者によって詳細に解析されました。ブラウザ・ネットワーク・アプリケーション層の55のプロパティをチェックする多層的な検知メカニズムと、XOR暗号化による難読化の手法が明かされています。
ChatGPTが利用するCloudflareのボット検知システム「Turnstile」の内部構造および関連するSentinelチャレンジに関する詳細な解析結果が、セキュリティ研究やリバースエンジニアリングを扱う技術ブログサイトのBuchodiによって公開されました。ネットワークトラフィックの傍受とSDKの難読化解除を通じて解析が行われ、どのようにボットが検知されトークンが生成されるのかという仕組みが明らかにされています。
ChatGPTからの全メッセージはブラウザ内で秘密裏に実行されるCloudflare Turnstileプログラムをトリガーします。このプログラムは単なるブラウザのフィンガープリンティングにとどまらず「ブラウザ」「Cloudflareネットワーク」「ChatGPTアプリケーション自体」の3つのレイヤーにわたる55ものプロパティをチェックします。具体的には、WebGL・画面解像度・ハードウェア情報・フォント測定・DOM操作・ストレージ利用状況といったブラウザ固有の情報に加え、Cloudflareのエッジヘッダー情報も収集されます。さらにChatGPTのReactアプリケーションが完全にレンダリング・ハイドレーションされているかどうかも確認しています。多層的なチェックを行うことによりブラウザのフィンガープリントが偽装されていたとしても実際のChatGPTシングルページアプリケーション(SPA)を正常にレンダリングしないボットは検知され失敗します。
Turnstileのバイトコードは受信時に暗号化されています。まず準備レスポンスに含まれるBase64エンコードされたフィールド(turnstile.dx)は準備リクエストからのトークン(p)とのXOR演算によって復号されます。外側のレイヤーの復号は両者が同じHTTP通信でやり取りされるため比較的容易です。外側のレイヤーを復号することにより約89個の仮想マシン(VM)命令が得られますが、VM命令の中に実際のフィンガープリントプログラムを含む19KBの暗号化されたデータブロックが含まれており、外側のレイヤーとは異なるXORキーを使用します。当初このキーはperformance.now()から派生するものと考えられていましたが、詳細な解析の結果キーはVM命令の中に浮動小数点リテラルとして直接埋め込まれていることが判明しました。キーはサーバーによって生成されバイトコードに埋め込まれ、解析者はキーを知ることで内部プログラムを復号できます。
完全な復号チェーンはHTTPリクエストとレスポンスのみで完結し、以下の5ステップで構成されます。1つ目は準備リクエストからpを読み取ることです。2つ目は準備レスポンスからturnstile.dxを読み取ります。3つ目はbase64decode(dx)とpをXOR演算し外部バイトコードを取得します。4つ目は19KBのブロブの後に続く5引数命令を探し、その最後の引数をキーとして取得します。最後に5つ目はbase64decode(blob)とキーの文字列表現をXOR演算し、内部プログラム(417〜580 VM命令)を取得します。
TurnstileはSentinelシステムが提供する3つのチャレンジのうちの1つです。残りの2つはSignal Orchestrator(SO)とPoWチャレンジです。Signal Orchestratorはキーダウン・ポインター移動・クリックなどのユーザーインタラクションイベントリスナーをインストールし、window.__oai_so_*プロパティを監視することでキーストロークのタイミングやマウスの速度といった行動バイオメトリクスを追跡する、行動生体認証のレイヤーです。
分析結果によると、プログラムの復号は377/377で100%の精度を達成しました。ユニークユーザー数は32、プログラムごとのプロパティは55で全サンプルで同一です。プログラムごとの手順は417~580で平均480、固有のXORキーは41個確認されています。SOの挙動特性は36種類、PoWフィンガープリントフィールドは25種類、PoW解決時間は72%が5ms未満です。
XORキーを用いて難読化することにより、静的解析からフィンガープリントチェックリストを隠蔽する、ウェブサイト運営者(OpenAI)がリバースエンジニアリングなしに生のフィンガープリント値を読み取ることを防ぐ、各トークンを一意にすることによりリプレイ攻撃を防ぐといった運用上の目的を達成しています。ただし実際には同じデータストリーム内でのXOR演算に過ぎないため、簡単な読み取りであればともかくとして分析には大きな障壁とはなりません。
