- Ao enviar uma mensagem no ChatGPT, o programa Cloudflare Turnstile é executado e inspeciona não apenas a impressão digital do navegador, mas também o estado da aplicação React
- O programa decriptografado coleta 55 propriedades e executa um processo de verificação em 3 camadas: navegador, rede e aplicação
- A aprovação só é possível em um ambiente SPA real com a renderização do React concluída, então navegadores headless ou requisições simples de bots falham
- A impressão digital coletada é criptografada e convertida em
OpenAI-Sentinel-Turnstile-Token, com os módulos Signal Orchestrator e Proof of Work atuando adicionalmente
- Como apenas os servidores da Cloudflare conhecem a chave de decriptação, a fronteira de privacidade é definida por política, não por tecnologia
Análise da estrutura de funcionamento do Cloudflare Turnstile no envio de mensagens do ChatGPT
- Em todo envio de mensagem no ChatGPT, o programa Cloudflare Turnstile é executado automaticamente dentro do navegador
- A decriptação de 377 programas Turnstile a partir do tráfego de rede mostrou que ele vai além da coleta comum de fingerprint do navegador e também inspeciona o estado da aplicação React
- Bots que apenas falsificam a fingerprint do navegador não passam; para ser aprovado, é necessário renderizar completamente a SPA (single-page application) do ChatGPT
Estrutura de criptografia e processo de decriptação
- O bytecode do Turnstile é enviado no campo
turnstile.dx da resposta do servidor e vem criptografado, em uma string base64 de 28.000 caracteres a cada requisição
- A camada externa de criptografia pode ser decriptada com a operação XOR usando o token
p, e os dois valores são trocados dentro da mesma requisição HTTP
- O resultado decriptografado é um bytecode em formato JSON composto por 89 instruções de VM
- No interior há um blob criptografado adicional de 19 KB, cifrado com outra chave XOR
- A chave é incluída no bytecode como um valor literal float (ex.: 97.35), gerado pelo servidor e enviado ao navegador
- Em todas as 50 requisições, foi confirmada a decriptação válida de JSON da mesma forma
- Todo o procedimento de decriptação é composto pelas 5 etapas a seguir
- Ler o token
p da requisição
- Ler
turnstile.dx da resposta
XOR(base64decode(dx), p) → gera o bytecode externo
- Extrair a chave do último argumento da instrução de 5 argumentos após o blob de 19 KB
XOR(base64decode(blob), str(key)) → decripta o programa interno (417 a 580 instruções)
Itens verificados pelo programa decriptografado
- O programa interno roda em uma VM customizada com 28 instruções (opcodes), e os endereços de registradores de ponto flutuante mudam aleatoriamente a cada requisição
- No total, ele coleta 55 propriedades, e os 377 samples continham exatamente os mesmos itens
-
Camada 1: fingerprint do navegador
- 8 propriedades relacionadas a WebGL:
UNMASKED_VENDOR_WEBGL, UNMASKED_RENDERER_WEBGL, WEBGL_debug_renderer_info etc.
- 8 informações de tela:
colorDepth, pixelDepth, width, height, availWidth, availHeight, availLeft, availTop
- 5 itens de hardware:
hardwareConcurrency, deviceMemory, maxTouchPoints, platform, vendor
- 4 medições de fonte: cria uma div oculta e mede o tamanho renderizado com
fontFamily, fontSize, getBoundingClientRect e innerText
- 8 itens de navegação no DOM:
createElement, appendChild, removeChild, style, position, visibility, ariaHidden etc.
- 5 itens de armazenamento:
storage, quota, estimate, setItem, usage
- O resultado é salvo no
localStorage com a chave 6f376b6560133c2c, persistindo entre recarregamentos da página
-
Camada 2: rede Cloudflare
- 5 headers de edge:
cfIpCity, cfIpLatitude, cfIpLongitude, cfConnectingIp, userRegion
- Esses valores só existem por meio da rede da Cloudflare, então bots que acessam diretamente o servidor de origem ficam com valores ausentes ou inconsistentes
-
Camada 3: estado da aplicação
- 3 estruturas internas do React:
__reactRouterContext, loaderData, clientBootstrap
- Esses itens só existem quando a aplicação React do ChatGPT foi totalmente renderizada e a hidratação SSR foi concluída
- Navegadores headless que carregam apenas o HTML ou não executam o bundle JS, assim como frameworks de bot que não executam React de fato, falham
Processo de geração do token
- Depois de coletar as 55 propriedades, o programa decripta um blob criptografado de 116 bytes e executa 4 instruções finais
JSON.stringify(fingerprint) → store → XOR(json, key) → RESOLVE
- O valor resultante é convertido no header
OpenAI-Sentinel-Turnstile-Token e incluído em todas as requisições de conversa
Componentes adicionais do Sentinel
- Além do Turnstile, existem mais dois módulos adicionais de verificação
-
Signal Orchestrator
- Composto por 271 instruções
- Instala listeners para os eventos
keydown, pointermove, click, scroll, paste, wheel
- Rastreia 36 propriedades
window.__oai_so_* para monitorar timing de digitação, velocidade do mouse, padrão de rolagem, tempo ocioso e eventos de colagem
- Além da coleta de fingerprint, atua como uma camada de autenticação biométrica comportamental
-
Proof of Work
- Baseado em fingerprint de 25 campos + SHA-256 hashcash
- A dificuldade é um número aleatório uniforme na faixa de 400K a 500K, e 72% são resolvidos em até 5 ms
- Inclui 7 flags binárias de detecção:
ai, createPRNG, cache, solana, dump, InstallTrigger, data (todas 0 em 100 samples)
- Adiciona custo computacional, mas não é o principal mecanismo de defesa
Quem pode decriptar o token e o significado de segurança
- Como a chave XOR do programa interno é gerada pelo servidor e incluída no bytecode, apenas o servidor que gerou
turnstile.dx conhece a chave
- A fronteira de privacidade entre usuário e operador do sistema é definida por uma decisão de política, não por uma restrição criptográfica
- Os objetivos da ofuscação são
- ocultar os itens coletados de fingerprint da análise estática
- impedir que o operador do site (OpenAI) leia diretamente os valores brutos de fingerprint
- tornar cada token único para evitar reutilização (replay)
- dificultar a percepção externa quando a Cloudflare altera os itens de inspeção
- Porém, a criptografia é feita por operação XOR com a chave e os dados no mesmo fluxo, então passa de ofuscação para dificultar análise, não de proteção robusta contra análise
Estatísticas de coleta e análise
| Item |
Valor |
| Programas decriptografados |
377/377 (100%) |
| Usuários únicos observados |
32 |
| Número de propriedades por programa |
55 (todos iguais) |
| Número de instruções |
417–580 (média de 480) |
| Chaves XOR (50 samples) |
41 |
| Propriedades do Signal Orchestrator |
36 |
| Campos do Proof of Work |
25 |
| Tempo de resolução do PoW |
72% em até 5 ms |
Metodologia de análise
- Foram usados apenas tráfegos coletados por meios legítimos
- Dados de usuários individuais não foram divulgados
- Todo o tráfego foi observado com consentimento dos participantes
- Foi feita desofuscação manual e decriptação offline do Sentinel SDK (
sdk.js, 1.411 linhas)
- A decriptação foi realizada em ambiente offline com Python
1 comentários
Comentários no Hacker News
Olá, sou Nick e trabalho na equipe de Integrity da OpenAI
Esta verificação faz parte das medidas de proteção para evitar abuso da plataforma, como bots, scraping e fraude
O objetivo é continuar oferecendo acesso a usuários gratuitos e não autenticados, priorizando recursos de GPU para usuários reais
Estamos monitorando tempo de carregamento da página, tempo até o primeiro token, tamanho do payload etc. e focando em minimizar o overhead das proteções
Para a maioria dos usuários, o impacto é mínimo, e apenas uma parcela muito pequena pode notar algum atraso
Também estamos avaliando continuamente melhorias de precisão para dificultar abusos enquanto reduzimos a taxa de falsos positivos
Entendo a explicação do Nick, mas fico me perguntando se vamos continuar vivendo em um mundo em que é preciso escolher entre privacidade e funcionalidade
Há atraso na digitação, travamentos na renderização e até congelamento completo
Tenho o mesmo problema no Safari do iPhone 16 e no Chrome de um MacBook Pro M3
Teve até uma sugestão em tom de brincadeira para rodar as ferramentas invasivas de privacidade da Cloudflare e compartilhar o resultado
Sou assinante Pro e minha equipe toda gasta mais de 2 mil dólares por mês
Mas quando uso VPN (Mullvad), mesmo logado, a interface do Chat costuma cair ou dar timeout
Seria bom se usuários pagos pudessem usar o serviço com estabilidade independentemente do uso de VPN
Reclamação de que a Cloudflare tornou a web quase inutilizável para certos navegadores ou IPs ‘suspeitos’
A pessoa diz que entrou em um verdadeiro inferno de captchas só por usar Firefox
VPNs, navegadores voltados à privacidade, faixas de IP raras e outros casos fazem com que usuários preocupados com privacidade sejam os mais afetados
Enquanto isso, bots de fato conseguem contornar esses filtros com facilidade
A pessoa diz que usa Firefox, mas vê apenas uma quantidade normal de captchas
Estou com o CGNAT desativado, então fico curioso se isso faz diferença
A pessoa diz que já havia sido autenticada pelo banco, então é difícil entender por que o site ainda não consegue distinguir um humano de um bot
Como a OpenAI oferece ChatGPT gratuito para usuários não autenticados, parece que ela está tentando impedir que isso seja explorado como uma API gratuita
No app Android, a checagem de Play Integrity funciona, mas o app do Claude exige apenas login e não faz esse tipo de validação
Ficou surpreso porque digitou uma pergunta sem cookies ou conta e mesmo assim recebeu resposta
O plano por assinatura é muito mais barato que a API, então é necessário evitar abuso
Um simples check no carregamento de uma SPA não é uma grande barreira, e quem percebe isso já tem capacidade técnica para contornar
Outras empresas também estão construindo seus próprios sistemas antibot
É interessante que certos atributos do app React do ChatGPT só existam quando a aplicação está totalmente renderizada
Isso indica uma detecção de bots na camada da aplicação, não no nível do navegador
Eu achava que a maioria dos sistemas avançados de detecção já funcionava assim, então fico em dúvida sobre o que há de especialmente relevante nessa descoberta
A pessoa gostaria que o autor tivesse explicado melhor por que esse problema deveria importar
No fim, a mensagem parece ser que a OpenAI quer que os usuários usem o app React oficial, e não fica claro por que isso seria um problema
Do ponto de vista técnico, isso é interessante
Pelo que a pessoa sabe, o Turnstile não costuma ter configuração específica por site, então fica a curiosidade sobre como a OpenAI combinou dados do Turnstile com sua própria API
Há quem não entenda por que operadores de bots não simplesmente rodam Windows 11 VM + Chrome
Com deduplicação de memória, daria para rodar 50 VMs ao mesmo tempo, e na AWS isso sairia por algo como 1 centavo a cada 1000 carregamentos de página, então seria muito barato
Há opções de rotação de IP, spoofing de localização, configuração de idioma, parser embutido etc., e o custo de troca é baixo, então há pouco motivo para montar tudo por conta própria
Afinal, ela é muito mais cara do que métodos simples
Como alternativa à sugestão, usar containers Linux em vez de Windows seria bem mais leve e eficiente
Crítica de que seria um artigo malfeito, com aparência de texto gerado pelo ChatGPT
Em 2023~2024, a pessoa usou uma extensão chamada KeepChatGPT
Achava interessante o fato de ela funcionar se passando por usuário, mesmo sem API
Depois parou de usar por causa da chegada do Gemini e dos erros frequentes, mas gostava da opção de mover o painel de IA para a direita
Link do GitHub do KeepChatGPT
Esse método não aciona em nada o sistema antibot da OpenAI
Pergunta sobre se a integração entre Cloudflare e o app é uma função personalizada além do Turnstile padrão ou algo exclusivo da versão enterprise