4 điểm bởi GN⁺ 23 ngày trước | 1 bình luận | Chia sẻ qua WhatsApp
  • 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 OrchestratorProof 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
    1. Đọc token p từ yêu cầu
    2. Đọc turnstile.dx từ phản hồi
    3. XOR(base64decode(dx), p) → tạo bytecode bên ngoài
    4. Trích tham số cuối làm khóa từ lệnh 5 đối số phía sau blob 19KB
    5. 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)storeXOR(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

    • Thật thú vị khi OpenAI coi scraping là lạm dụng
    • Dạo này có cảm giác phải cần một trình duyệt cho phép mọi kiểu xác minh client để dùng các dịch vụ thiết yếu, và một trình duyệt khác để tránh bị theo dõi
      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
    • Không rõ có phải vấn đề liên quan hay không, nhưng trong các cuộc trò chuyện dài thì hiệu năng Chat UI rất tệ
      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
    • Một tài khoản mới chỉ để lại hai bình luận, nên cũng có người nghi ngờ không biết đó thật sự là người hay là bot bảo vệ OpenAI
      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ả
    • Thật vui khi được nghe phản hồi trực tiếp từ phía OpenAI
      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

    • Định nghĩa “đáng ngờ” của Cloudflare đang liên tục được mở rộng
      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
    • Có người gợi ý nên kiểm tra xem trong mạng có lưu lượng web lạ nào đang phát ra hay không
      Bản thân họ cũng dùng Firefox nhưng chỉ gặp captcha ở mức bình thường
    • Tôi dùng Firefox + Ublock Origin và gần như chưa từng thấy captcha
      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
    • Có người chia sẻ trải nghiệm vô lý khi phải giải 15 captcha liên tiếp ngay sau khi thanh toán
      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í

    • Có người thắc mắc liệu việc xác minh này có áp dụng bất kể có đăng nhập hay không
      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
    • Có người kể rằng họ từng dùng ChatGPT mà không cần đăng nhập
      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ờ
    • Loại bảo vệ này cũng nhằm bảo vệ mô hình sử dụng của thuê bao Pro
      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
    • Dùng GPT‑5.2 với giá 20 USD/tháng có tỷ lệ giá/hiệu năng quá tốt, nên có lẽ sớm muộn gì cũng sẽ có điều chỉnh giá
    • copilot.microsoft.com dường như cũng dùng cơ chế bảo vệ dựa trên Cloudflare tương tự
  • 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 đề

    • Vì vậy có người thấy bài viết đó giống một bài chất lượng thấp do AI viết
  • 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ẻ

    • Hiện đã có rất nhiều dịch vụ đóng gói sẵn cung cấp những tính năng này
      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
    • Trên thực tế, cách tiếp cận dựa trên VM như vậy có tác dụng răn đe vì làm giảm số lượng bot
      Đơn giản là nó đắt hơn nhiều so với các phương pháp sơ sài
    • Nếu xem các cộng đồng Reddit về scraping, có thể thấy các nhà phát triển bot rất khó chịu khi bị chặn truy cập bằng trình duyệt headless
      Theo gợi ý đó, dùng container Linux thay vì Windows sẽ nhẹ và hiệu quả hơn nhiều
    • Có người hỏi nếu ai biết cách dễ dàng để chạy Windows 11 VM có tăng tốc đồ họa tốt mà không cần GPU passthrough thì hãy chia sẻ
  • Có người chỉ trích đây là một bài báo vụng về như thể do ChatGPT viết

    • Họ đùa rằng: “Đặc trưng truyền thống của blog web là bản nháp tệ đến mức ngay cả mô hình ngôn ngữ cũng phải sửa lần hai
  • 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

    • Bản thân họ dùng một ứng dụng helper nhỏ gửi truy vấn tới ChatGPT bằng WinForms WebView rồi nhận phản hồi JSON
      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