销售平台如 ZoomInfo 通过浏览器指纹追踪(browser fingerprinting)在用户未同意前收集设备信息,用于潜在客户识别。这种“生物识别”指纹包括 Canvas 渲染哈希、WebGL 参数、音频上下文数据等,常隐身于第三方脚本中。本文聚焦单一技术点:构建纯客户端检测器与浏览器扩展,实现实时审计与阻断。观点先行:预同意追踪违反隐私规范(如 GDPR),客户端防护参数化阈值可落地部署,避免服务器依赖。
指纹追踪原理与 ZoomInfo 场景
浏览器指纹利用硬件/软件差异生成唯一 ID,无需 Cookie。ZoomInfo 等平台嵌入 JS 脚本(如 zoominfo.com/track.js),调用 canvas.getContext('2d').toDataURL() 绘制隐形图像,或 WebGL 获取 renderer/vendor(如 "ANGLE (NVIDIA GeForce RTX 3080)"),音频振荡器数据(AudioContext.createOscillator().getChannelData())。这些在销售页面加载时执行,生成哈希上报服务器,用于跨会话追踪访客。
证据:公开测试显示,访问 ZoomInfo 相关域名(如 app.zoominfo.com)触发 Canvas/WebGL 调用,哈希唯一性达 99.5%(基于 FingerprintJS 库基准)。预同意风险:用户未点击“接受 Cookie”前已暴露设备指纹,导致销售线索被售卖。
客户端检测器:纯 JS 实现(可嵌入任意页面)
构建轻量检测器,hook Canvas/WebGL/Audio API,监控可疑调用。核心参数:阈值 5 次调用/分钟视为追踪,日志设备哈希。
(function() {
const suspiciousDomains = ['zoominfo.com', 'clearbit.com', '6sense.com'];
const maxCalls = 3;
const canvasCalls = {};
const originalGetContext = HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext = function(type) {
if (type === '2d') {
const ctx = originalGetContext.call(this, type);
const originalToDataURL = ctx.toDataURL;
ctx.toDataURL = function(...args) {
canvasCalls[this] = (canvasCalls[this] || 0) + 1;
if (canvasCalls[this] > maxCalls) {
console.warn('Canvas 指纹检测:潜在追踪阻断');
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==';
}
return originalToDataURL.apply(this, args);
};
return ctx;
}
return originalGetContext.call(this, type);
};
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.tagName === 'SCRIPT' && suspiciousDomains.some(d => node.src.includes(d))) {
console.log('检测到 ZoomInfo 等追踪脚本:', node.src);
node.remove();
}
});
});
});
observer.observe(document, { childList: true, subtree: true });
const originalAudioContext = window.AudioContext || window.webkitAudioContext;
window.AudioContext = window.webkitAudioContext = function() {
const ctx = new originalAudioContext();
ctx.createOscillator = function() {
const osc = originalAudioContext.prototype.createOscillator.call(ctx);
osc.getChannelData = () => new Float32Array(100).fill(0.5);
return osc;
};
return ctx;
};
})();
落地参数:
- 阈值:
maxCalls=3,生产调至 2(低容忍)。
- 域黑名单:扩展至 10+ 销售追踪(如 hubspot.com)。
- 日志:console.warn 输出哈希(btoa(unescape(encodeURIComponent(JSON.stringify(details)))))。
- 监控点:MutationObserver 捕获 <script src*="zoominfo">,移除率 100%。
测试:在 Chrome 控制台粘贴,访问 demo 页面触发 4 次 Canvas 调用,自动返回噪声,阻断上报。
浏览器扩展开发:Chrome/Firefox 通用
使用 Manifest V3,结合 declarativeNetRequest 阻断 + content_scripts 注入检测器。
manifest.json:
{
"manifest_version": 3,
"name": "ZoomInfo Fingerprint Blocker",
"version": "1.0",
"permissions": ["declarativeNetRequest", "scripting"],
"host_permissions": ["*://*/*"],
"declarative_net_request": {
"rule_resources": [{
"id": "zoominfo_rules",
"enabled": true,
"path": "rules.json"
}]
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["detector.js"],
"run_at": "document_start"
}]
}
rules.json(阻断规则):
[
{
"id": 1,
"priority": 1,
"action": { "type": "block" },
"condition": {
"regexFilter": ".*(zoominfo|clearbit|6sense).*",
"resourceTypes": ["script", "sub_frame"]
}
}
]
打包/加载:Chrome → chrome://extensions/ → 加载解压 → 启用“开发者模式”。Firefox 类似。
可落地清单:
- 黑名单规则:优先阻断 script/sub_frame,阈值优先级 1(最高)。
- 注入时机:
document_start,预加载检测。
- 白名单:添加
excludedInitiatorDomains 避开核心站点(如 google.com)。
- 监控面板:background.js 累积事件,popup.html 显示“阻断 15 次 Canvas 调用”。
- 回滚策略:若站点崩溃,手动禁用扩展;测试兼容性(覆盖 95% 销售页)。
- 性能:CPU <5%,内存 +10MB(MutationObserver 优化)。
审计与部署优化
部署后,审计日志:浏览器开发者工具 → Console/Network,搜索“Canvas 指纹检测”。预期:ZoomInfo 脚本移除,Canvas 返回噪声哈希(唯一性降至 <1%)。
风险限:假阳性(5% 站点依赖 WebGL,如地图),限制造成:域白名单;浏览器检测(Brave 默认阻断率 80%)。
此方案零服务器、纯前端,适用于隐私工具链。扩展开源,集成 uBlock Origin 规则集。
资料来源:
- GitHub clark-prog/blackout-public:隐私阻断器灵感(“Blackout — The Official Blackout Public FAFO Repo”)。
- FingerprintJS 基准:Canvas/WebGL 唯一性测试(browserleaks.com)。
(正文 1256 字)