- Khi gửi tin nhắn trong ChatGPT, chương trình Cloudflare Turnstile sẽ chạy để kiểm tra không chỉ dấu vân tay trình duyệt mà còn cả trạng thái ứng dụng React
- Chương trình sau khi giải mã thu thập 55 thuộc tính, và thực hiện quy trình xác minh theo 3 lớp: trình duyệt, mạng và ứng dụng
- Chỉ có thể vượt qua trong môi trường SPA thực tế nơi React đã render xong, nên trình duyệt headless hoặc yêu cầu bot đơn giản sẽ thất bại
- Dấu vân tay thu thập được sẽ được mã hóa và chuyển thành
OpenAI-Sentinel-Turnstile-Token, đồng thời Signal Orchestrator và Proof of Work cũng hoạt động bổ sung
- Chỉ máy chủ Cloudflare mới biết khóa giải mã, nên ranh giới quyền riêng tư được quyết định bởi chính sách chứ không phải công nghệ
Phân tích cấu trúc hoạt động của Cloudflare Turnstile khi gửi tin nhắn ChatGPT
- Mỗi lần gửi tin nhắn trong ChatGPT, chương trình Cloudflare Turnstile sẽ tự động chạy trong trình duyệt
- Kết quả giải mã 377 chương trình Turnstile từ lưu lượng mạng cho thấy, ngoài việc thu thập dấu vân tay trình duyệt thông thường, nó còn kiểm tra cả trạng thái ứng dụng React
- Bot chỉ giả mạo dấu vân tay trình duyệt sẽ không vượt qua được; phải render đầy đủ SPA (ứng dụng một trang) của ChatGPT mới có thể qua xác minh
Cấu trúc mã hóa và quá trình giải mã
- Bytecode Turnstile được truyền trong trường
turnstile.dx của phản hồi máy chủ, và được mã hóa thành chuỗi base64 dài 28.000 ký tự cho mỗi yêu cầu
- Lớp mã hóa bên ngoài có thể được giải bằng phép XOR với token
p, và hai giá trị này được trao đổi trong cùng một yêu cầu HTTP
- Kết quả sau giải mã là bytecode dạng JSON gồm 89 lệnh VM
- Bên trong có thêm một blob mã hóa kích thước 19KB, blob này được mã hóa bằng một khóa XOR khác
- Khóa được nhúng dưới dạng giá trị literal float (ví dụ: 97.35) trong bytecode, do máy chủ tạo ra và gửi tới trình duyệt
- Cả 50 yêu cầu đều xác nhận giải mã thành JSON hợp lệ theo cùng một cách
- Toàn bộ quy trình giải mã gồm 5 bước sau
- Đọc token
p từ yêu cầu
- Đọc
turnstile.dx từ phản hồi
XOR(base64decode(dx), p) → tạo bytecode bên ngoài
- Trích tham số cuối làm khóa từ lệnh 5 đối số phía sau blob 19KB
XOR(base64decode(blob), str(key)) → giải mã chương trình bên trong (417~580 lệnh)
Các hạng mục kiểm tra của chương trình đã giải mã
- Chương trình bên trong chạy trên VM tùy biến có 28 lệnh (opcode), và địa chỉ thanh ghi dấu phẩy động được thay đổi ngẫu nhiên theo từng yêu cầu
- Thu thập tổng cộng 55 thuộc tính, và cả 377 mẫu đều chứa cùng các mục này
-
Lớp 1: Dấu vân tay trình duyệt
- 8 thuộc tính liên quan WebGL:
UNMASKED_VENDOR_WEBGL, UNMASKED_RENDERER_WEBGL, WEBGL_debug_renderer_info v.v.
- 8 thông tin màn hình:
colorDepth, pixelDepth, width, height, availWidth, availHeight, availLeft, availTop
- 5 thuộc tính phần cứng:
hardwareConcurrency, deviceMemory, maxTouchPoints, platform, vendor
- 4 phép đo font: tạo div ẩn rồi đo kích thước render bằng
fontFamily, fontSize, getBoundingClientRect, innerText
- 8 mục dò DOM:
createElement, appendChild, removeChild, style, position, visibility, ariaHidden v.v.
- 5 mục lưu trữ:
storage, quota, estimate, setItem, usage
- Kết quả được lưu vào khóa
6f376b6560133c2c trong localStorage để duy trì qua các lần tải lại trang
-
Lớp 2: Mạng Cloudflare
- 5 header edge:
cfIpCity, cfIpLatitude, cfIpLongitude, cfConnectingIp, userRegion
- Các giá trị này chỉ tồn tại khi đi qua mạng Cloudflare, nên bot truy cập trực tiếp máy chủ gốc sẽ bị thiếu hoặc sai lệch
-
Lớp 3: Trạng thái ứng dụng
- 3 cấu trúc nội bộ React:
__reactRouterContext, loaderData, clientBootstrap
- Các mục này chỉ tồn tại khi ứng dụng React của ChatGPT đã render hoàn chỉnh và SSR hydration đã hoàn tất
- Trình duyệt headless chỉ tải HTML hoặc không chạy bundle JS, hay framework bot không thực thi React thực sự, sẽ thất bại
Quá trình tạo token
- Sau khi thu thập 55 thuộc tính, chương trình sẽ giải mã một blob mã hóa 116 byte rồi thực thi 4 lệnh cuối
JSON.stringify(fingerprint) → store → XOR(json, key) → RESOLVE
- Kết quả được chuyển thành header
OpenAI-Sentinel-Turnstile-Token và được đưa vào mọi yêu cầu hội thoại
Các thành phần bổ sung của Sentinel
- Ngoài Turnstile, còn có thêm hai mô-đun xác minh bổ sung
-
Signal Orchestrator
- Gồm 271 lệnh
- Cài listener cho các sự kiện
keydown, pointermove, click, scroll, paste, wheel
- Theo dõi 36 thuộc tính
window.__oai_so_* để giám sát thời điểm gõ phím, tốc độ chuột, mẫu cuộn, thời gian nhàn rỗi, sự kiện dán v.v.
- Đóng vai trò là lớp xác thực sinh trắc học dựa trên hành vi ngoài việc thu thập dấu vân tay
-
Proof of Work
- Dựa trên dấu vân tay 25 trường + SHA-256 hashcash
- Độ khó là số ngẫu nhiên đều trong khoảng 400K~500K, 72% được giải trong dưới 5ms
- Gồm 7 cờ phát hiện nhị phân như
ai, createPRNG, cache, solana, dump, InstallTrigger, data (đều là 0 trong 100 mẫu)
- Làm tăng chi phí tính toán nhưng không phải biện pháp phòng thủ chính
Chủ thể có thể giải mã token và ý nghĩa bảo mật
- Vì khóa XOR của chương trình bên trong do máy chủ tạo và nhúng vào bytecode, nên chỉ máy chủ tạo ra
turnstile.dx mới biết khóa
- Ranh giới quyền riêng tư giữa người dùng và đơn vị vận hành hệ thống được xác định bởi quyết định chính sách chứ không phải ràng buộc mật mã
- Mục đích của việc làm rối mã là
- Che giấu các hạng mục thu thập dấu vân tay khỏi phân tích tĩnh
- Ngăn đơn vị vận hành website (OpenAI) đọc trực tiếp các giá trị dấu vân tay thô
- Làm cho mỗi token trở nên duy nhất để ngăn tái sử dụng (replay)
- Khi Cloudflare thay đổi hạng mục kiểm tra thì bên ngoài khó nhận ra
- Tuy nhiên, việc mã hóa được thực hiện bằng khóa và phép XOR trong cùng một luồng dữ liệu, nên chỉ là mức làm rối nhằm cản trở phân tích
Thống kê thu thập và phân tích
| Hạng mục |
Giá trị |
| Chương trình đã giải mã |
377/377 (100%) |
| Người dùng duy nhất quan sát được |
32 |
| Số thuộc tính mỗi chương trình |
55 (đều giống nhau) |
| Số lệnh |
417–580 (trung bình 480) |
| Khóa XOR (50 mẫu) |
41 |
| Thuộc tính Signal Orchestrator |
36 |
| Trường Proof of Work |
25 |
| Thời gian giải PoW |
72% dưới 5ms |
Phương pháp phân tích
- Chỉ sử dụng lưu lượng được thu thập theo quy trình hợp pháp
- Không công khai dữ liệu người dùng cá nhân
- Mọi lưu lượng đều được quan sát với sự đồng ý của người tham gia
- Thực hiện gỡ rối thủ công và giải mã ngoại tuyến đối với Sentinel SDK (
sdk.js, 1.411 dòng)
- Việc giải mã được tiến hành trong môi trường ngoại tuyến bằng Python
1 bình luận
Ý kiến trên Hacker News
Xin chào, tôi là Nick, làm việc trong nhóm Integrity của OpenAI
Đợt kiểm tra này là một phần của các biện pháp bảo vệ nhằm ngăn chặn lạm dụng nền tảng như bot, scraping, gian lận, v.v.
Mục tiêu là ưu tiên phân bổ tài nguyên GPU cho người dùng thật để có thể tiếp tục cung cấp quyền truy cập cho người dùng miễn phí và chưa đăng nhập
Chúng tôi đang theo dõi thời gian tải trang, thời gian đến token đầu tiên, kích thước payload, v.v., và tập trung vào việc giảm thiểu overhead của các biện pháp bảo vệ
Ảnh hưởng với đa số người dùng là không đáng kể, chỉ một bộ phận cực nhỏ có thể gặp độ trễ nhẹ
Ngoài ra, chúng tôi cũng đang liên tục đánh giá các cải tiến về độ chính xác để vừa giảm tỷ lệ dương tính giả vừa khiến việc lạm dụng trở nên khó hơn
Tôi hiểu lời giải thích của Nick, nhưng vẫn tự hỏi liệu thế giới buộc phải chọn giữa quyền riêng tư và tính năng có còn tiếp diễn hay không
Có độ trễ khi nhập, render giật cục, thậm chí treo hẳn
Tôi gặp y hệt trên Safari của iPhone 16 và Chrome trên MacBook Pro M3
Cũng có lời đề nghị đùa nửa thật rằng hãy chạy các công cụ xâm phạm quyền riêng tư của Cloudflare rồi chia sẻ kết quả
Tôi là thuê bao Pro và cả nhóm của tôi chi hơn 2.000 USD mỗi tháng
Nhưng khi dùng VPN (Mullvad), ngay cả lúc đã đăng nhập thì giao diện Chat vẫn thường xuyên ngắt kết nối hoặc timeout
Sẽ tốt hơn nếu người dùng trả phí có thể sử dụng ổn định bất kể có dùng VPN hay không
Có phàn nàn rằng Cloudflare khiến web gần như không thể dùng được chỉ vì trình duyệt hoặc IP bị coi là “đáng ngờ”
Có người nói rằng chỉ vì dùng Firefox mà rơi vào địa ngục captcha
VPN, trình duyệt thiên về quyền riêng tư, dải IP hiếm, v.v. khiến những người coi trọng quyền riêng tư lại là nhóm bị dính nhiều nhất
Trong khi đó bot thật sự lại dễ dàng vượt qua các bộ lọc này
Bản thân họ cũng dùng Firefox nhưng chỉ gặp captcha ở mức bình thường
Tôi đang tắt CGNAT nên không biết có phải đó là yếu tố tạo ra khác biệt hay không
Họ nói rằng ngân hàng đã xác minh danh tính rồi, nên thật khó hiểu khi trang web vẫn không phân biệt nổi người hay không phải người
Vì OpenAI cung cấp ChatGPT miễn phí cho người dùng chưa đăng nhập, nên có vẻ họ muốn bảo vệ để tránh việc này bị lạm dụng như một API miễn phí
Trên ứng dụng Android, kiểm tra Play Integrity có hoạt động, còn ứng dụng Claude thì chỉ yêu cầu đăng nhập chứ không có kiểu xác minh này
Chỉ nhập câu hỏi mà không có cookie hay tài khoản gì vẫn nhận được câu trả lời, nên họ thấy khá bất ngờ
Giá thuê bao rẻ hơn rất nhiều so với API, nên cần ngăn lạm dụng
Kiểm tra tải SPA ở mức này không phải rào cản lớn, và người nào nhận ra được thì thường cũng đã có kỹ thuật để vượt qua
Các công ty khác cũng đang tự xây dựng hệ thống chống bot riêng
Có người thấy thú vị ở chỗ ứng dụng React của ChatGPT phải render hoàn chỉnh thì một số thuộc tính nhất định mới tồn tại
Đây là cách phát hiện bot ở tầng ứng dụng, chứ không phải ở mức trình duyệt
Họ vốn nghĩ hầu hết các hệ thống phát hiện nâng cao đều hoạt động như vậy, nên tự hỏi phát hiện lần này có ý nghĩa gì đặc biệt hay không
Có ý kiến rằng tác giả nên giải thích rõ hơn vì sao vấn đề này lại đáng quan tâm
Rốt cuộc thì OpenAI chỉ muốn người dùng sử dụng ứng dụng React chính thức, và họ không rõ điều đó có gì là vấn đề
Xét từ góc độ kỹ thuật thì khá thú vị
Họ biết rằng Turnstile về cơ bản không có cấu hình riêng theo từng trang, nên thắc mắc OpenAI đã kết hợp dữ liệu Turnstile với API nội bộ của mình như thế nào
Có ý kiến nói họ không hiểu vì sao những người vận hành bot không đơn giản là chạy Windows 11 VM + Chrome
Nếu dùng memory deduplication thì có thể chạy đồng thời 50 VM, và theo giá AWS thì chỉ khoảng 1 cent cho mỗi 1.000 lần tải trang, tức là rất rẻ
Có đủ loại tùy chọn như xoay vòng IP, giả mạo vị trí, thiết lập ngôn ngữ, parser tích hợp, v.v., và chi phí chuyển đổi cũng thấp nên không có nhiều lý do để tự xây dựng
Đơn giản là nó đắt hơn nhiều so với các phương pháp sơ sài
Theo gợi ý đó, dùng container Linux thay vì Windows sẽ nhẹ và hiệu quả hơn nhiều
Có người chỉ trích đây là một bài báo vụng về như thể do ChatGPT viết
Có người từng dùng tiện ích mở rộng KeepChatGPT trong giai đoạn 2023~2024
Họ thấy cách nó hoạt động bằng cách giả làm người dùng mà không cần API khá thú vị
Sau đó họ ngừng dùng vì Gemini xuất hiện và lỗi xảy ra thường xuyên, nhưng vẫn thích tùy chọn chuyển bảng AI sang bên phải
Liên kết GitHub KeepChatGPT
Cách này không hề bị hệ thống chống bot của OpenAI chặn lại
Có câu hỏi rằng việc tích hợp giữa Cloudflare và ứng dụng có phải là tính năng tùy biến vượt quá Turnstile tiêu chuẩn hay chỉ dành riêng cho bản enterprise hay không