Canvas Fingerprinting vượt ra ngoài cơ bản: Vì sao hai trình duyệt Chrome giống hệt lại render ra pixel khác nhau
Hai thiết bị cùng Chrome, OS và GPU vẫn render ra pixel canvas khác nhau. Vì sao pipeline render không mang tính tất định, vì sao chèn nhiễu để bảo vệ quyền riêng tư lại phản tác dụng, và canvas nằm ở đâu trong stack phát hiện hiện đại.
Canvas fingerprinting đã được dùng trong production từ năm 2012. Ý tưởng khá đơn giản: yêu cầu trình duyệt render nội dung 2D, đọc lại các pixel, rồi băm (hash) chúng. Các thiết bị khác nhau tạo ra pixel hơi khác nhau cho cùng một tập lệnh, và những khác biệt đó đủ ổn định để định danh một thiết bị qua nhiều phiên.
Đó là điều ai cũng biết. Điều ít được hiểu hơn là vì sao kỹ thuật này hoạt động — vì sao các cấu hình phần mềm giống hệt nhau trên phần cứng giống hệt nhau vẫn tạo ra đầu ra pixel khác nhau. Câu trả lời nằm ở giao điểm giữa driver GPU, việc render font và số học dấu phẩy động.
Pipeline render không mang tính tất định
Khi JavaScript gọi context.fillText("Cwm fjord bank glyphs vext quiz", 4, 45), Chrome không tự render pixel. Nó tạo ra các lệnh cho Skia — thư viện đồ họa 2D — và Skia đến lượt mình phát các lệnh vẽ tới một backend tăng tốc bằng GPU (thường là ANGLE trên Windows, Metal trên macOS, hoặc software fallback trong container).
Ở mỗi bước, những khác biệt nhỏ trong cách triển khai tích lũy lại:
-
Hệ thống font của Skia chọn một họ font (font family). Nếu không có Arial cài sẵn, nó sẽ fallback — và font fallback thay đổi tùy theo các font được cài trên hệ thống.
-
Font được chọn sẽ được render ở kích thước yêu cầu bằng FreeType (trên Linux), DirectWrite (trên Windows) hoặc Core Text (trên macOS). Mỗi thư viện có thuật toán hinting khác nhau.
-
Định vị subpixel được áp dụng. Đây là nơi các font giống hệt nhau bắt đầu tạo ra pixel khác nhau — thuật toán làm tròn vị trí về các offset pixel phân số, và quy tắc làm tròn khác nhau giữa các nền tảng.
-
Văn bản đã được raster hóa được composite lên canvas. Việc pha trộn (blending) được thực hiện bằng shader GPU trên các hệ thống tăng tốc phần cứng, và bằng mã CPU ở chế độ fallback.
Mỗi bước trong số này có thể tạo ra khác biệt một hoặc hai giá trị pixel. Riêng lẻ thì không nhìn thấy được. Gộp lại thì độc nhất.
Phiên bản driver GPU chi phối fingerprint
Hai máy Windows 11 với chip Intel UHD Graphics 620 có thể tạo ra đầu ra canvas khác nhau nếu driver GPU của chúng khác nhau. Intel phát hành bản cập nhật driver nhiều lần mỗi năm, và mỗi bản cập nhật có thể thay đổi việc lọc subpixel, hiệu chỉnh gamma và khử răng cưa (anti-aliasing) văn bản.
Điều này có nghĩa là độ ổn định của canvas fingerprint bị giới hạn bởi tần suất cập nhật driver. Một người dùng nâng cấp driver đồ họa — thường một cách âm thầm, qua Windows Update — sẽ thấy canvas fingerprint của mình thay đổi.
Các hệ thống phát hiện xử lý điều này bằng cách coi canvas fingerprint là một trong nhiều tín hiệu, chứ không phải định danh độc lập. Khi nó thay đổi nhưng các tín hiệu khác vẫn ổn định (TLS fingerprint, WebGL renderer, múi giờ, các font đã cài), thì khách truy cập vẫn được nhận diện.
Render emoji là một mỏ vàng
Yếu tố dễ định danh nhất của một canvas fingerprint thường không phải là văn bản hay hình khối, mà là emoji. Việc render emoji phụ thuộc vào font emoji được cài kèm OS — Segoe UI Emoji trên Windows, Apple Color Emoji trên macOS, Noto Color Emoji trên Android.
Ngay cả trong cùng một OS, việc render emoji cũng thay đổi giữa các phiên bản. Cách Windows 10 render một emoji cầu vồng khác với Windows 11. Khuôn mặt cười toe toét (grinning face) của iOS 16 có khử răng cưa khác với iOS 17.
Các script canvas fingerprinting hiện đại render riêng những chuỗi emoji, bao gồm cả những bổ sung mới vào Unicode. Một khách truy cập tự nhận là chạy Safari trên iPhone nhưng không thể render một emoji được thêm vào ở iOS 17 thì đang chạy một iOS cũ hơn — hoặc nói dối về nền tảng.
Các framework tự động hóa tạo ra fingerprint đặc trưng
Chrome headless, chạy trong một container Docker không có GPU, dùng SwiftShader để render. SwiftShader tạo ra đầu ra canvas nhất quán nội bộ nhưng khác biệt với bất kỳ Chrome tăng tốc phần cứng nào.
Chữ ký này dễ nhận ra: khử răng cưa sạch bất thường, các giá trị màu cụ thể ở vùng gradient, và các cạnh văn bản không khớp với bất kỳ driver GPU nào đã biết. Một canvas fingerprint khớp với SwiftShader trong Chrome 124 trên container Linux gần như chắc chắn là tự động hóa — không người dùng thật nào chạy trình duyệt theo cách này.
Puppeteer-extra-stealth cố gắng giả mạo đầu ra canvas bằng cách chặn toDataURL() và trả về dữ liệu đã sửa đổi. Nhưng việc sửa đổi này thường tự nó tạo ra những dấu vết riêng — các mẫu nhiễu lặp lại qua nhiều phiên, và nghịch lý thay điều đó khiến nỗ lực chống fingerprinting còn dễ bị phát hiện hơn là không làm gì cả.
Vì sao chèn nhiễu không hiệu quả
Các trình duyệt tập trung vào quyền riêng tư như Brave chèn nhiễu vào đầu ra canvas để ngăn theo dõi. Ý tưởng là thêm những biến thiên ngẫu nhiên nhỏ vào giá trị pixel để cùng một thiết bị tạo ra fingerprint khác nhau mỗi phiên.
Trên thực tế, việc chèn nhiễu có ba vấn đề:
1. Bản thân nhiễu là một fingerprint. Một khách truy cập có đầu ra canvas thay đổi ở mỗi lần tải, nhưng các tín hiệu khác vẫn giống hệt, thì dễ nhận diện là một trình duyệt chèn nhiễu. Bản thân điều đó đã mang tính định danh.
2. Thuật toán nhiễu ổn định. Cách triển khai của Brave tạo ra các mẫu nhiễu cụ thể không khớp với biến thiên tự nhiên của việc render GPU. Các hệ thống phát hiện có thể nhận ra đầu ra canvas nào trông có vẻ đã chèn nhiễu so với trông tự nhiên.
3. Các hệ thống tinh vi kết hợp nhiều mẫu. Nhiều lần render trên cùng một trang, hoặc qua nhiều phiên, có thể được lấy trung bình. Nếu nhiễu nhỏ, giá trị trung bình sẽ hội tụ về fingerprint tất định nền tảng.
Canvas fingerprinting nắm bắt những gì
Ngoài đầu ra hình ảnh hiển nhiên, canvas fingerprinting có thể trích xuất một số thuộc tính thiết bị như tác dụng phụ:
Thời gian render — canvas mất bao lâu để render cho thấy năng lực GPU. Một desktop 4K với GPU rời render nhanh hơn một laptop tầm trung.
Text metrics — measureText() trả về độ rộng pixel chính xác vốn thay đổi theo việc render font. Độ rộng văn bản có thể dùng làm fingerprint ngay cả khi không render.
Hỗ trợ composite operation — một số trình duyệt hoặc cấu hình GPU hỗ trợ các chế độ composite mở rộng. Kiểm tra sự hỗ trợ này bộc lộ ranh giới năng lực.
Hiệu ứng filter — các filter kiểu CSS áp dụng lên canvas tạo ra đầu ra khác nhau giữa các GPU, đặc biệt là filter làm mờ (blur) và đổ bóng (drop-shadow).
Canvas fingerprinting nằm ở đâu trong stack phát hiện
Đứng riêng lẻ, canvas fingerprinting không phải là một định danh vững chắc. Driver thay đổi. Người dùng chuyển trình duyệt. Việc chèn nhiễu phổ biến trong nhóm người dùng quan tâm quyền riêng tư.
Sức mạnh thực sự của nó là làm phép kiểm tra chéo. Khi một phiên tự nhận là người dùng quay lại dựa trên cookie hoặc đăng nhập tài khoản, canvas fingerprint đóng vai trò tín hiệu thứ hai — khớp với fingerprint lịch sử thì xác nhận tuyên bố đó, không khớp thì cảnh báo chiếm đoạt tài khoản hoặc chiếm quyền phiên (session hijacking).
Đối với phát hiện bot, canvas fingerprinting nổi trội ở việc bắt tự động hóa trong container. Người dùng thật có GPU thật. GPU thật tạo ra chữ ký render dễ nhận ra. Bất kỳ thứ gì render giống SwiftShader, hoặc giống một canvas bị giả mạo vụng về, đều nằm trong nhóm gần như chắc chắn là bot.
Kỹ thuật của năm 2012 vẫn hoạt động vào năm 2026 vì cùng một lý do: việc render mang tính tất định theo từng môi trường nhưng gần như không thể giả mạo hoàn toàn. Mọi nỗ lực che giấu đều để lại dấu vết của chính nỗ lực đó.