解法
在2018年,追踪网站访问者看起来就是个JavaScript问题:脚本在页面加载或点击时发送信标,如果脚本被拦截、禁用或过滤,整个通道就断了。Crooked Style Sheets,一个由开发者jbtronics做的概念验证,证明了不用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年这个仓库大概有3300个星和132个fork。随之而来的防御包括CSS Exfil Protection扩展,作者认为真正的修复是让浏览器在页面加载时就获取CSS引用的外部内容,而不是等选择器匹配,他承认这个改动会牺牲性能。
What it achieved
把浏览器对CSS资源的懒加载当成事件信标:只在点击、悬停或字体缺失时匹配的选择器,会触发服务器能记录的请求
为什么有效
浏览器决定何时去取CSS url()的内容,所以匹配的选择器会产生网络请求,其中没有广告拦截器能盯上的JavaScript调用。
这些请求看起来像普通的图片或字体加载,在日志和多数拦截工具里跟合法资源难分彼此。
依赖状态的选择器把含义编进URL本身:资源路径写明事件,服务器只需要记录到达时间。
CSS在禁用脚本的页面上照样生效,填补了让无JavaScript看似隐私的空白。
可以借鉴什么
声明式格式照样执行条件工作:任何依赖状态的资源加载都是可观察的信号,所以防御方要把CSS发起的请求也当成需要限制的行为。
后续
这个仓库在2018年1月16日登上Hacker News,拿到532分和175条评论;到2026年抓取时显示大概3.3k个星和132个fork。这个演示至少催生了一个防御,就是它自己README里链接的CSS Exfil Protection扩展,作者在说明文章里主张,持久的修复是让浏览器在页面加载时就取CSS引用的外部内容,而不是等选择器匹配,不过他承认这个改动会牺牲性能。原演示网站后来下线了,只剩仓库里的代码示例作为这种技术的活记录。
从这里,追溯依据
参考来源
- CrookedStyleSheets - Webpage tracking only using CSS (and no JS) github.com
- Crooked Style Sheeding - Webpage tracking using only CSS news.ycombinator.com