- Lors de l’envoi d’un message dans ChatGPT, le programme Cloudflare Turnstile s’exécute et inspecte non seulement l’empreinte du navigateur, mais aussi l’état de l’application React
- Le programme déchiffré collecte 55 propriétés et applique une procédure de vérification en trois couches : navigateur, réseau et application
- La vérification ne peut être réussie que dans un véritable environnement SPA où le rendu React est terminé, ce qui signifie que les navigateurs headless et les simples requêtes de bot échouent
- L’empreinte collectée est chiffrée puis convertie en
OpenAI-Sentinel-Turnstile-Token, auquel s’ajoutent ensuite les modules Signal Orchestrator et Proof of Work - Comme seuls les serveurs de Cloudflare connaissent la clé de déchiffrement, la frontière de confidentialité est définie par la politique plutôt que par la technique
Analyse du fonctionnement de Cloudflare Turnstile lors de l’envoi d’un message dans ChatGPT
- À chaque envoi de message dans ChatGPT, le programme Cloudflare Turnstile s’exécute automatiquement dans le navigateur
- L’analyse de 377 programmes Turnstile déchiffrés à partir du trafic réseau montre qu’il ne se limite pas à une collecte classique d’empreinte navigateur, mais inspecte aussi l’état de l’application React
- Les bots qui ne font que falsifier l’empreinte du navigateur ne passent pas la vérification ; il faut rendre complètement la SPA (application monopage) de ChatGPT pour la réussir
Structure de chiffrement et processus de déchiffrement
- Le bytecode Turnstile est transmis dans le champ
turnstile.dxde la réponse serveur et il est chiffré à chaque requête sous la forme d’une chaîne base64 de 28 000 caractères- La couche de chiffrement externe peut être déchiffrée par une opération XOR avec le jeton
p, les deux valeurs étant échangées dans la même requête HTTP - Le résultat déchiffré est un bytecode JSON composé de 89 instructions de VM
- La couche de chiffrement externe peut être déchiffrée par une opération XOR avec le jeton
- À l’intérieur se trouve un blob chiffré supplémentaire de 19 KB, lui aussi chiffré avec une autre clé XOR
- La clé est incluse dans le bytecode sous la forme d’une valeur littérale flottante (par ex.
97.35), générée par le serveur puis envoyée au navigateur - Sur 50 requêtes, un déchiffrement valide en JSON a été confirmé selon le même procédé
- La clé est incluse dans le bytecode sous la forme d’une valeur littérale flottante (par ex.
- La procédure complète de déchiffrement se compose des 5 étapes suivantes
- Lire le jeton
pdans la requête - Lire
turnstile.dxdans la réponse XOR(base64decode(dx), p)→ génération du bytecode externe- Extraire la dernière valeur comme clé depuis l’instruction à 5 arguments située après le blob de 19 KB
XOR(base64decode(blob), str(key))→ déchiffrement du programme interne (417 à 580 instructions)
- Lire le jeton
Éléments inspectés par le programme déchiffré
- Le programme interne s’exécute sur une VM personnalisée avec 28 instructions (opcodes), et les adresses des registres flottants changent aléatoirement à chaque requête
- Il collecte au total 55 propriétés, identiques dans les 377 échantillons
-
Couche 1 : empreinte du navigateur
- 8 propriétés liées à WebGL :
UNMASKED_VENDOR_WEBGL,UNMASKED_RENDERER_WEBGL,WEBGL_debug_renderer_info, etc. - 8 informations d’écran :
colorDepth,pixelDepth,width,height,availWidth,availHeight,availLeft,availTop - 5 éléments matériels :
hardwareConcurrency,deviceMemory,maxTouchPoints,platform,vendor - 4 mesures de police : création d’un div caché puis mesure de la taille de rendu via
fontFamily,fontSize,getBoundingClientRect,innerText - 8 éléments d’exploration du DOM :
createElement,appendChild,removeChild,style,position,visibility,ariaHidden, etc. - 5 éléments de stockage :
storage,quota,estimate,setItem,usage- Les résultats sont stockés dans
localStoragesous la clé6f376b6560133c2cafin de persister entre les rechargements de page
- Les résultats sont stockés dans
- 8 propriétés liées à WebGL :
-
Couche 2 : réseau Cloudflare
- 5 en-têtes edge :
cfIpCity,cfIpLatitude,cfIpLongitude,cfConnectingIp,userRegion - Ces valeurs n’existent qu’au sein du réseau Cloudflare ; les bots accédant directement au serveur d’origine obtiennent donc des champs absents ou incohérents
- 5 en-têtes edge :
-
Couche 3 : état de l’application
- 3 structures internes React :
__reactRouterContext,loaderData,clientBootstrap - Ces éléments n’existent que lorsque l’application React de ChatGPT a été entièrement rendue et que l’hydratation SSR est terminée
- Les navigateurs headless qui ne chargent que le HTML ou n’exécutent pas les bundles JS, ainsi que les frameworks de bots qui n’exécutent pas réellement React, échouent
- 3 structures internes React :
Processus de génération du jeton
- Après la collecte des 55 propriétés, le programme déchiffre un blob chiffré de 116 octets puis exécute 4 instructions finales
JSON.stringify(fingerprint)→store→XOR(json, key)→RESOLVE- La valeur obtenue est convertie en en-tête
OpenAI-Sentinel-Turnstile-Tokenet incluse dans toutes les requêtes de conversation
Composants supplémentaires de Sentinel
- En plus de Turnstile, deux modules de vérification supplémentaires sont présents
-
Signal Orchestrator
- Composé de 271 instructions
- Installe des écouteurs d’événements
keydown,pointermove,click,scroll,paste,wheel - Suit 36 propriétés
window.__oai_so_*afin de surveiller le timing de frappe, la vitesse de la souris, les schémas de défilement, le temps d’inactivité et les événements de collage - Il joue le rôle d’une couche biométrique comportementale en plus de la collecte d’empreinte
-
Proof of Work
- Basé sur une empreinte de 25 champs + SHA-256 hashcash
- La difficulté est un nombre aléatoire uniforme dans une plage de 400K à 500K ; 72 % sont résolus en 5 ms ou moins
- Il inclut 7 indicateurs binaires de détection :
ai,createPRNG,cache,solana,dump,InstallTrigger,data(tous à 0 dans 100 échantillons) - Il ajoute un coût de calcul, mais ne constitue pas le principal moyen de défense
Qui peut déchiffrer le jeton et implications de sécurité
- Comme la clé XOR du programme interne est générée par le serveur puis intégrée au bytecode, seul le serveur qui a généré
turnstile.dxconnaît cette clé - La frontière de confidentialité entre l’utilisateur et l’opérateur du système est définie par une décision de politique, et non par une contrainte cryptographique
- L’objectif de l’obfuscation est de
- masquer les éléments collectés contre l’analyse statique
- empêcher l’exploitant du site (OpenAI) de lire directement les valeurs brutes de l’empreinte
- rendre chaque jeton unique afin d’éviter la réutilisation (replay)
- rendre difficile la détection externe des changements opérés par Cloudflare sur les éléments inspectés
- Cependant, le chiffrement repose sur une opération XOR avec la clé dans le même flux de données, ce qui n’est qu’une obfuscation destinée à compliquer l’analyse
Statistiques de collecte et d’analyse
| Élément | Valeur |
|---|---|
| Programmes déchiffrés | 377/377 (100 %) |
| Utilisateurs uniques observés | 32 |
| Nombre de propriétés par programme | 55 (identiques pour tous) |
| Nombre d’instructions | 417–580 (moyenne 480) |
| Clés XOR (50 échantillons) | 41 |
| Propriétés de Signal Orchestrator | 36 |
| Champs de Proof of Work | 25 |
| Temps de résolution du PoW | 72 % en 5 ms ou moins |
Méthodologie d’analyse
- Seul du trafic collecté selon une procédure légale a été utilisé
- Aucune donnée personnelle d’utilisateurs n’a été publiée
- Tout le trafic a été observé avec le consentement des participants
- Le SDK Sentinel (
sdk.js, 1 411 lignes) a fait l’objet d’une désobfuscation manuelle et d’un déchiffrement hors ligne - Le déchiffrement a été réalisé hors ligne en Python
1 commentaires
Commentaires sur Hacker News
Bonjour, je m'appelle Nick et je travaille dans l’équipe Integrity d’OpenAI
Cette vérification fait partie des mesures de protection visant à empêcher les abus de la plateforme, comme les bots, le scraping ou la fraude
L’objectif est de continuer à offrir l’accès aux utilisateurs gratuits et non connectés tout en priorisant les ressources GPU pour les vrais utilisateurs
Nous surveillons le temps de chargement des pages, le délai avant le premier token, la taille des payloads, etc., et nous nous concentrons sur la réduction maximale de la surcharge induite par ces protections
L’impact est minime pour la plupart des utilisateurs, et seul un très petit nombre pourrait subir un léger ralentissement
Nous continuons aussi à évaluer des améliorations de précision afin de réduire les faux positifs tout en rendant les abus plus difficiles
Je comprends l’explication de Nick, mais je me demande si nous allons continuer à vivre dans un monde où il faut choisir entre vie privée et fonctionnalité
Il y a de la latence à la saisie, des saccades de rendu, voire des blocages complets
Je constate la même chose sur Safari de l’iPhone 16 et sur Chrome d’un MacBook Pro M3
Il y a aussi une suggestion mi-sérieuse, mi-plaisante, de lancer les outils intrusifs de Cloudflare et de partager le résultat
Je suis abonné Pro et mon équipe dépense plus de 2 000 dollars par mois
Mais quand j’utilise un VPN (Mullvad), l’interface Chat se coupe souvent ou expire, même en étant connecté
Ce serait bien que les utilisateurs payants puissent l’utiliser de manière stable, avec ou sans VPN
Une plainte affirme que Cloudflare rend le web presque inutilisable en raison de navigateurs ou d’IP jugés « suspects »
La personne dit être tombée dans un enfer de CAPTCHAs simplement parce qu’elle utilise Firefox
Les VPN, les navigateurs axés sur la confidentialité, les plages d’IP rares et autres utilisateurs soucieux de leur vie privée sont justement ceux qui se retrouvent le plus ciblés
Pendant ce temps, les bots contournent facilement ce type de filtres
Cette personne utilise aussi Firefox, mais ne voit qu’un niveau normal de CAPTCHAs
J’ai désactivé le CGNAT, donc je me demande si cela fait une différence
La banque avait déjà vérifié son identité, donc elle trouve difficile à comprendre qu’un site soit incapable de distinguer un humain d’un bot
Comme OpenAI propose ChatGPT gratuit aux utilisateurs non connectés, il semble logique qu’ils cherchent à empêcher qu’il soit détourné comme une API gratuite
Dans l’application Android, il y a un contrôle Play Integrity, alors que l’app Claude demande seulement une connexion sans ce type de vérification
Elle a été surprise d’obtenir une réponse en entrant simplement une question, sans cookie ni compte
Le modèle d’abonnement revient bien moins cher que l’API, donc il faut limiter les abus
Un simple contrôle au chargement d’une SPA ne constitue pas un gros obstacle, et ceux qui en ont conscience ont déjà les compétences pour le contourner
D’autres entreprises mettent elles aussi en place leurs propres systèmes anti-bot
Il est intéressant que certaines propriétés n’existent que lorsque l’application React de ChatGPT est entièrement rendue
Cela signifie qu’il s’agit d’une détection de bots au niveau de la couche applicative, et non du navigateur
Je pensais que la plupart des systèmes de détection avancés fonctionnaient déjà ainsi, donc je me demande ce que cette découverte a de particulièrement notable
Quelqu’un aurait aimé que l’auteur explique plus clairement pourquoi ce point devrait être important
Au fond, OpenAI veut simplement que les utilisateurs passent par l’application React officielle, et il n’est pas évident en quoi cela pose problème
D’un point de vue technique, c’est intéressant
Turnstile est censé fonctionner sans configuration propre à chaque site, donc on se demande comment OpenAI a pu combiner les données de Turnstile avec sa propre API
Quelqu’un dit ne pas comprendre pourquoi les opérateurs de bots ne lancent pas simplement des VM Windows 11 + Chrome
Avec la déduplication mémoire, on pourrait faire tourner 50 VM en parallèle, et sur AWS cela reviendrait à environ 1 centime pour 1 000 chargements de page, donc ce serait très bon marché
Rotation d’IP, usurpation de localisation, réglages de langue, parseurs intégrés, etc. : les options sont variées et le coût de changement est faible, donc il y a peu d’intérêt à tout construire soi-même
Comme suggéré, utiliser des conteneurs Linux au lieu de Windows serait bien plus léger et efficace
Critique d’un article bâclé qui semble avoir été rédigé par ChatGPT
Quelqu’un dit avoir utilisé en 2023~2024 une extension appelée KeepChatGPT
Il trouvait intéressant qu’elle fonctionne en se faisant passer pour un utilisateur, sans API
Il a ensuite arrêté de l’utiliser à cause de l’arrivée de Gemini et des erreurs fréquentes, mais il appréciait l’option permettant de déplacer le panneau IA sur la droite
Lien GitHub de KeepChatGPT
Cette méthode ne déclenche pas du tout le système anti-bot d’OpenAI
Question sur le fait de savoir si l’intégration entre Cloudflare et l’application relève de fonctionnalités personnalisées au-delà du Turnstile standard, ou s’il s’agit d’une option réservée à l’édition Enterprise