解決方案
2018 年時,追蹤網站訪客看似是 JavaScript 的問題:指令碼在頁面載入或點擊時發出信標,而一旦指令碼被封鎖、停用或過濾,整條管道便告中斷。開發者 jbtronics 的概念驗證 Crooked Style Sheets 顯示,頁面可以完全不靠 JavaScript,只使用瀏覽器自身的 CSS 引擎來追蹤。
顯而易見的做法全都依賴指令碼或像素:回報伺服器的追蹤片段、圖片標籤、第三方分析 SDK。每一種都是指令碼封鎖器與廣告過濾器專門攔截的可見請求類別,而且在指令碼從未執行的頁面上,它們一個都不會觸發。
訣竅在於瀏覽器何時抓取 CSS 的 url() 資源:只有在選擇器相符時才抓取。因此,連結的 :active 樣式搭配 content: url(track.php?action=link2_clicked),會讓瀏覽器正好在該連結被點擊時請求該 URL。同樣的原理涵蓋了滑鼠懸停、勾選方塊、透過 :valid 比對樣式的文字、透過 @supports 偵測瀏覽器,以及透過 @font-face 回退在缺少 Calibri 時載入,來偵測已安裝的字型。每個請求都會命中一個 PHP 頁面,該頁面記錄時間戳與編碼於其 URL 中的動作。
由於這些請求是普通的 CSS 驅動資源載入,它們不帶有任何可供封鎖器辨識的指令碼呼叫,而且樣式表在 JavaScript 關閉時仍會生效。2018 年 1 月的 Hacker News 貼文獲得 532 分與 175 則留言,而該儲存庫到 2026 年已成長至約 3.3k 顆星與 132 次分支。它所引發的防禦措施包括 CSS Exfil Protection 擴充功能,而作者主張穩健的修正方式是讓瀏覽器在頁面載入時、而非按需抓取 CSS 所引用的外部內容,他承認這項變更會犧牲效能。
達成了什麼
將瀏覽器對 CSS 資源的延遲抓取當作事件信標:只有在點擊、懸停或字型缺失時才相符的選擇器會觸發請求,伺服器便可記錄
為何有效
瀏覽器決定何時抓取 CSS 的 url() 內容,因此相符的選擇器會產生網路請求,而沒有可供廣告封鎖器鎖定的 JavaScript 呼叫。
這些請求看起來像普通的圖片或字型載入,在日誌與多數封鎖工具中與合法資源無從區分。
依狀態而定的選擇器將意義編碼於 URL 本身:資源路徑即為事件名稱,伺服器只記錄抵達時間戳。
CSS 在停用指令碼的頁面上仍會生效,填補了讓「無 JavaScript」看似保有隱私的缺口。
可應用之處
宣告式格式仍會執行條件式工作:任何依狀態而定的資源載入都是可觀測的訊號,因此防禦措施必須將源自 CSS 的請求視為值得限制的行為
後續發展
該儲存庫於 2018 年 1 月 16 日登上 Hacker News,獲得 532 分與 175 則留言;到 2026 年爬取時,它顯示約 3.3k 顆星與 132 次分支。這項示範至少催生了一項防禦措施,即其自身 README 所連結的 CSS Exfil Protection 擴充功能,而作者的說明文章主張,持久的修正方式是讓瀏覽器在頁面載入時、而非選擇器相符時載入 CSS 所引用的外部內容,他指出這項變更會犧牲效能。原始示範網站後來下線,留下儲存庫中的程式碼範例作為該技術的可用紀錄。
追溯依據
參考來源
- CrookedStyleSheets - Webpage tracking only using CSS (and no JS) GitHub · github.com
- Crooked Style Sheeding - Webpage tracking using only CSS Hacker News · news.ycombinator.com ·