精华内容
下载资源
问答
  • 浏览器指纹
    2021-12-24 15:49:46

    浏览器指纹

    场景一:在网站上浏览某个商品,了解了相关的商品信息,但并没有下单购买,甚至没有进行登录操作。过两天用同台电脑访问其他网站的时候却发现很多同类商品的广告。

    场景二:在某博客中你有多个小号(水军),这些小号的存在就是为了刷某个帖子的热度或者进行舆论引导,又或者纯粹进行流量交易,即便你在切换账号的时候清空了cookie、本地缓存,重开路由器甚至使用vpn来进行操作,你觉得自己足够小心,并尽可能提高水军的真实性,但是管理人员可能还是知道这是同一个人在操作,从而被打击。

    什么是浏览器指纹

    “浏览器指纹识别”是一种通过浏览器对网站可见的配置和设置信息来跟踪网络浏览器的方法,而不是传统的跟踪方法,例如 IP 地址和唯一的 cookie。

    浏览器指纹识别既难以检测又极难阻止。就像我们人手上的指纹一样,具有个体辨识度,只不过现阶段浏览器指纹辨别的是浏览器。

    当您加载网页时,您将自动将有关浏览器的某些信息广播到您正在访问的网站 - 以及嵌入该网站的任何跟踪器(例如那些提供广告的跟踪器)。您正在访问的站点可能会选择使用 JavaScript、Flash 和其他方法来分析您的浏览器(就像 Cover Your Tracks 一样)。它可能会查找您安装的字体类型、您设置的语言、您安装的附加组件以及其他因素。然后,该站点可能会创建一种您的个人资料,与与您的浏览器相关的这种特征模式相关联,而不是与特定的跟踪 cookie 相关联。

    如果您的浏览器是独一无二的,那么即使没有设置跟踪 cookie,在线跟踪器也有可能识别出您的身份。虽然跟踪器不会知道您的姓名,但他们可以收集您访问的网站的深度个人档案。

    删除 cookie 无济于事,因为正在分析的是浏览器配置的特征

    背景

    浏览器指纹追踪技术到目前已经进入2.5代。

    • 第一代是状态化的,主要集中在用户的cookie和evercookie上,需要用户登录才可以得到有效的信息。
    • 第二代才有了浏览器指纹的概念,通过不断增加浏览器的特征值从而让用户更具有区分度,例如(UA、浏览器插件信息)
    • 第三代是已经将目光放在人身上了,通过收集用户的行为、习惯来为用户建立特征值甚至模型,可以实现真正的追踪技术,这部分目前实现比较复杂,依然在探索中。

    目前处于2.5代是因为现在需要解决的问题是如何解决跨浏览器识别指纹的问题上

    指纹采集

    信息熵(entropy)是接收的每条消息中包含的信息的平均量,熵越高,则能传输越多的信息,熵越低,则意味着传输的信息越少

    查看自己的浏览器指纹ID和基本信息

    查看自己的HTTP头部信息

    查看自己浏览器的基本信息

    https://link.zhihu.com/?target=https%3A//panopticlick.eff.org/about

    特征值:

    • 每个浏览器的用户代理字符串
    • 浏览器发送的HTTP ACCEPT标头
    • 屏幕分辨率和色彩深度
    • 系统设置为时区
    • 浏览器中安装的浏览器扩展/插件,例如Quicktime,Flash,Java或Acrobat,以及这些插件的版本
    • 计算机上安装的字体,由Flash或Java报告。
    • 浏览器是否执行JavaScript脚本
    • 浏览器是否能种下各种cookie和“超级cookie(super cookies)”
    • 通过Canvas指纹生成的图像的哈希
    • WebGL指纹生成的图像的哈希
    • 是否浏览器设置为“Do Not Track”
    • 系统平台(例如Win32,Linux x86)
    • 系统语言(例如,cn,en-US)
    • 浏览器是否支持触摸屏

    特征值的信息熵计算方式

    浏览器指纹可以分为:

    • 普通指纹:任何浏览器都具有的特征标识,比如硬件类型(Apple)、操作系统(Mac OS)、用户代理(User agent)、系统字体、语言、屏幕分辨率、浏览器插件 (Flash, Silverlight, Java, etc)、浏览器扩展、浏览器设置 (Do-Not-Track, etc)、时区差(Browser GMT Offset)等众多信息,这些指纹信息“类似”人类的身高、年龄等,有很大的冲突概率,只能作为辅助识别
    • 高级指纹:
      • Canvas指纹
      • Audio Context指纹
      • 硬件指纹
      • 综合指纹
      • WebGL 指纹

    WebRTC

    WebRTC(网页实时通信,Web Real Time Communication),是可以让浏览器有音视频实时通信的能力,它提供了三个主要的API来让JS可以实时获取和交换音视频数据,MediaStream、RTCPeerConnection和RTCDataChannel。当然如果要使用WebRTC获得通信能力,用户的真实ip就得暴露出来(NAT穿透),所以RTCPeerConnection就提供了这样的API,直接使用JS就可以拿到用户的IP地址。

    Canvas指纹

    Canvas是HTML5中的动态绘图标签,也可以用它生成图片或者处理图片。即便使用Canvas绘制相同的元素,但是由于系统的差别,字体渲染引擎不同,对抗锯齿、次像素渲染等算法也不同,canvas将同样的文字转成图片

    function getCanvasFingerprint () {
        var canvas = document.getElementById("anchor-uuid");
        var context = canvas.getContext("2d");
        context.font = "18pt Arial";
        context.textBaseline = "top";
        context.fillText("Hello, user.", 2, 2);
        return canvas.toDataURL("image/jpeg");
    }
    

    canvas指纹测试

    AudioContext指纹

    AudioContext指纹和Canvas类似也是基于硬件设备或者软件的差别,来产生不同的音频输出,然后计算得到不同的hash来作为标志,当然这里的音频并没有直接在浏览器中播放出来,只需要拿到播放前的处理数据就行

    音频指纹测试

    硬件指纹

    硬件指纹主要通过检测硬件模块获取信息,作为对基于软件的指纹的补充,主要的硬件模块有:GPU’s clock frequency、Camera、Speakers/Microphone、Motion sensors、GPS、Battery等

    综合指纹

    测试地址

    Web世界的指纹碰撞不可避免,将上述所有的基本指纹和多种高级指纹综合利用,进行分析、计算哈希值作为综合指纹,可以大大降低碰撞率,极大提高客户端唯一性识别的准确性

    webGL指纹

    WebGL(Web图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。WebGL 通过引入一个与 OpenGL ES 2.0 非常一致的 API 来做到这一点,该 API 可以在 HTML5 元素中使用。这种一致性使 API 可以利用用户设备提供的硬件图形加速。网站可以利用 WebGL 来识别设备指纹,一般可以用两种方式来做到指纹生产:

    • WebGL 报告——完整的 WebGL 浏览器报告表是可获取、可被检测的。在一些情况下,它会被转换成为哈希值以便更快地进行分析。
    • WebGL 图像 ——渲染和转换为哈希值的隐藏 3D 图像。由于最终结果取决于进行计算的硬件设备,因此此方法会为设备及其驱动程序的不同组合生成唯一值。这种方式为不同的设备组合和驱动程序生成了唯一值。

    可以通过 Browserleaks test 检测网站来查看网站可以通过该 API 获取哪些信息。

    产生WebGL指纹原理是首先需要用着色器(shaders)绘制一个梯度对象,并将这个图片转换为Base64字符串。然后枚举WebGL所有的拓展和功能,并将他们添加到Base64字符串上,从而产生一个巨大的字符串,这个字符串在每台设备上可能是非常独特的。

    如何防范

    没有足够专业的知识或者非常频繁更换浏览器信息的话,几乎100%可以通过浏览器指纹定位到一个用户,当然这也不见得全是坏事。

    • 泄露的隐私非常片面,只能说泄露了用户部分浏览网页时的行为。
    • 价值不够,用户行为并未将实际的账户或者具体的人对应起来,产生的价值有限。
    • 有益利用,利用浏览器指纹可以隔离部分黑产用户,防止刷票或者部分恶意行为。

    Do Not Track

    在http头部可以声明这样一个标志“DNT”意味“Do Not Track”,如果值为1表示为不要追踪我的网页行为,0则为可以追踪。即便没有cookie也可以通过这个标志符告诉服务器我不想被追踪到,不要记录我的行为。

    不好的消息是大多数网站目前并没有遵守这个约定,完全忽略了“Do Not Track”这个信号。

    EFF提供了这样一个工具Privacy Badger,它是一个浏览器插件形式的广告拦截器,对于那些遵守这个约定的公司会在这个广告拦截器的白名单上,允许显示广告,从而激励更多的公司遵守“Do Not Track”,以便完全展示广告。

    个人觉得这一个方向很不错的做法,如果用户使用这个工具,网站在拿用户行为之前会抉择两边的利益,从而减轻用户对于隐私泄露的风险。

    Privacy Badger

    Tor Browser

    浏览器的特征越多,越容易被追踪到,所以有效的方法是尽量将特征值进行大众化,例如目前市面最广泛的搭配是Window 10 + Chrome,那么你将UA改为这个组合就是一个有效的方法,同时尽量避免网站获取信息熵非常高的特征值,例如canvas指纹。

    or 浏览器在这上面做了很多工作,以防止它们被用来跟踪Tor用户,为了响应Panopticlick和其他指纹识别实验,Tor浏览器现在包含一些补丁程序,以防止字体指纹(通过限制网站可以使用的字体)和Canvas指纹(通过检测对HTML5 Canvas对象的读取并要求用户批准)来防止,例如上面获取Canvas指纹的代码,在Tor上会弹出如下警告
    同时还可以将Tor浏览器配置为主动阻止JavaScript。

    禁用JS

    比较粗暴的方法,直接禁止网站使用JavaScript可以非常有效地防御浏览器指纹追踪,但是这样会导致页面较大部分地功能不可用。但是,即便禁止了JS但是还可以通过CSS来采取浏览器的信息。如:

    @media(device-width: 1080px) {
      body {
        background: url("https://example.org/1080.png");
      }
    }
    

    隐身模式

    隐私浏览和隐身模式只有一个目的。这些模式旨在防止您访问过的站点的痕迹被存储在您的机器上。这并不是为了阻止远程站点或跟踪器在您访问服务器上的站点时识别和存储。

    如果使用 Firefox,使用隐私浏览将提供一些针对跟踪器的保护。任何包含在断开连接跟踪保护列表中的跟踪器都将被阻止。这免受已知跟踪器的侵害。使用您的浏览器攻击您的已知指纹识别器和密码挖掘器也被阻止。但是,这不会阻止新的指纹识别器或跟踪器识别您的浏览器并密切关注它。为了获得这种额外的保护级别,您的浏览器需要有一个指纹,它是:

    1. 如此普遍以至于跟踪器无法将您与人群区分开来(如在Tor 浏览器中),或者
    2. 随机化,以便跟踪器无法从一个时刻到下一个时刻告诉您是您(如 勇敢的浏览器)。

    Google 的 Chrome 浏览器在隐身模式下不提供针对跟踪器或指纹器的保护

    如何防止被生成“用户指纹”

    混淆Canvas指纹

    想混淆 Canvas 指纹,只需要在 toDataURL 得到的结果上做手脚就可以。

    toDataURL() 将整个canvas的内容导出,我们需要将 Canvas 中的部分内容修改,这个时候可以通过 getImageData() 复制画布上指定矩形的像素数据,然后通过 **putImageData()**将图像数据放回,然后再使用 toDataURL() 导出的图片就有了差异。

    CanvasRenderingContext2D.getImageData() 返回一个ImageData对象,用来描述 Canvas 区域隐含的像素数据。这个区域通过矩形表示,起始点为(sx, sy)、宽为sw、高为sh。

    ImageData 接口描述了元素的一个隐含像素数据的区域,可以由 ImageData() 方法构造,或者由canvas 在一起的 CanvasRenderingContext2D 对象的创建方法:createImageData() 和 getImageData()。

    ImageData 对象存储着canvas对象真实的像素数据,它包含几个只读属性:

    • width 图片宽度,单位像素
    • height 图片高度,单位像素
    • data

    Uint8ClampedArray 类型的一位数组,包含着 RGBA 的整型数据,范围在 0~255。它可以视作初始像素数据,每个像素用 4 个 1 bytes 值(按照 red、green、blue、alpha 的顺序),每个颜色值用0~255 中的数字代表。每个部分被分配到一个数组内的连续索引,左上角第一个像素的红色部分,位于数组索引的第 0 位。像素从左到右从上到下被处理,遍历整个数组。

    Unit8ClampedArray 包含 高度宽度4 bytes数据,索引值从 0 ~ (wh4)-1 。

    读取图片中位于第 50 行,200 列的像素的蓝色部分

    const blueComponent = imageData[50*(imageData.width * 4) + 200*4 + 2]
    

    实现混淆Canvas指纹的方法

    const toBlob = HTMLCanvasElement.prototype.toBlob;
    const toDataURL = HTMLCanvasElement.prototype.toDataURL;
    HTMLCanvasElement.prototype.manipulate = function() {
      const {width, height} = this;
      // 拿到在进行toDataURL或者toBlob前的canvas所生成的CanvasRenderingContext2D
      const context = this.getContext('2d'); 
      const shift = {
        'r': Math.floor(Math.random() * 10) - 5,
        'g': Math.floor(Math.random() * 10) - 5,
        'b': Math.floor(Math.random() * 10) - 5
      };
      const matt = context.getImageData(0, 0, width, height);
      // 对getImageData生成的imageData(像素源数据)中的每一个像素的r、g、b部分的值进行进行随机改变从而生成唯一的图像。
      for (let i = 0; i < height; i += Math.max(1, parseInt(height / 10))) {
        for (let j = 0; j < width; j += Math.max(1, parseInt(width / 10))) {
          const n = ((i * (width * 4)) + (j * 4));
          matt.data[n + 0] = matt.data[n + 0] + shift.r; // 加上随机扰动
          matt.data[n + 1] = matt.data[n + 1] + shift.g;
          matt.data[n + 2] = matt.data[n + 2] + shift.b;
        }
      }
      context.putImageData(matt, 0, 0); // 重新放回去
    // 修改prototype.toBlob
    Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
      value: function() {
        if (script.dataset.active === 'true') {
          try {
            this.manipulate(); // 在每次toBlob前,先混淆下ImageData
          }
          catch(e) {
            console.warn('manipulation failed', e);
          }
        }
        return toBlob.apply(this, arguments);
      }
    });
    // 修改prototype. toDataURL
    Object.defineProperty(HTMLCanvasElement.prototype, 'toDataURL', {
      value: function() {
        if (script.dataset.active === 'true') {
          try {
            this.manipulate(); // 在每次toDataURL前,先混淆下ImageData
          }
          catch(e) {
            console.warn('manipulation failed', e);
          }
        }
        return toDataURL.apply(this, arguments);
      }
    });
    

    混淆其他指纹

    与混淆canvas指纹思路一致,都是更改被获取对象的原型的方法。

    比如混淆时区,就是更改 Date.prototype.getTimezoneOffset 的返回值。

    混淆分辨率则是更改documentElement.clientHeight documentElement.clientWidth

    混淆 WebGL 则要更改 WebGLbufferData getParameter方法等等

    参考

    更多相关内容
  • fybridjs是一个开源浏览器指纹(或指纹)库。 指纹可用于识别用户的浏览器,并可用于欺诈检测和向用户提供更个性化的服务(例如,有针对性的广告)。 传统的浏览器识别方法主要依赖于客户端标识符,例如浏览器和 ...
  • 浏览器指纹Demo 知乎文章: 在线演示地址: 你应该知道的事 Chrome一直在阻止网页技术捕获用户的指纹,这是出于对于用户隐私与安全性的考虑,所以现在可用的技术可能在未来的某个版本中就不可用了。但是浏览器指纹...
  • Node.js应用程序获取浏览器指纹。 依存关系 快速,简单,极简的Web框架 该模块尝试通过检查浏览器的标头和连接信息来唯一标识浏览器。 为什么这个? 该脚本用作内部端点,可为请求该脚本的客户端提供“浏览器指纹...
  • 阻止浏览器指纹识别尝试。 油腻的叉子: : GitHub: : Firefox浏览器附加组件: : 什么是浏览器指纹 可以通过浏览器的屏幕分辨率,颜色深度,已安装的插件,受支持的mime类型,时区偏移等来识别浏览器,并且...
  • d on't˚F英格P RINT M E DFPM是用于检测浏览器指纹的浏览器扩展。 您可以从安装它。 在过去的几年中,浏览器指纹已经得到了广泛的关注。 EFF和其他公司已经发布了工具( ),证明了这是可能的,但令人沮丧的是,...
  • C# cefsharp 多账号同时登陆,设置cookie隔离,修改部分浏览器指纹,源码仅供学习交流,后续可以加自动加购和不惧反爬虫等操作
  • FingerprintJS是一个浏览器指纹库,用于查询浏览器属性并从中计算散列的访问者标识符。 与cookie和本地存储不同,即使在清除浏览器数据时,指纹在隐身/私有模式下也保持不变。 。 快速开始 从CDN安装 < script ...
  • 如何使用候鸟浏览器修改浏览器指纹
  • 简单指纹简单的浏览器指纹库演示: : 正在安装npm install simple-fingerprintyarn add simple-fingerprint用法使用简单计算稳定的浏览器指纹: import { computeFingerprint } from "simple-fingerprint" ;...
  • 浏览器指纹解读

    千次阅读 2022-06-07 14:26:18
    浏览器指纹很重要,在数据采集、搜索引擎、埋点分析、网站测试等方面都有体现。指纹通常是指服务端的为了做识别而收集的客户端设备信息。即使没有cookie,指纹也可用于识别个人用户或设备...

    科普文,简单解读浏览器指纹相关内容,如有描述不周望谅解。


    浏览器指纹

    浏览器指纹很重要,在数据采集、搜索引擎、埋点分析、网站测试等方面都有体现。

    指纹通常是指服务端的为了做识别而收集的客户端设备信息。即使没有cookie,指纹也可用于识别个人用户或设备。

    比如常用于记录的指纹 Header、Cookie、IP、DNS、UserAgent,Font(字体列表),Language,localStorage、Plugin(插件),Canvas(渲染绘图),WebGL(3D渲染图形),Web Vendor(硬件厂商信息),Timezone(时区),WebRTC(web通信API),ScreenResolution(分辨率),Platform(系统),Audio(音频设置和硬件特征指纹),以及enumerateDevices(其他媒体设备)、CPU、GPU信息等等。

    在这里插入图片描述

    像用户代理、HTML元素属性、Dom对象操作等都属于基本指纹。
    像图形渲染、音频指纹、硬件指纹这些属于高级指纹,生成或者模拟都有一定难度。
    像浏览记录、访问频率等属于行为指纹,常用于恶意访问的判定,具体判定规则需要测试。

    当你浏览页面时,网站可以根据你的浏览器指纹进行跟踪,此外还有一些网站会根据指纹信息生成设备ID然后发送行为日志。
    所以在你访问了一个网站后,它虽然没有cookie,但是有一个唯一的指纹,所以无论是推送广告还是行为检测都非常容易。

    在线查看浏览器指纹:

    • https://www.deviceinfo.me/ (非常详细的设备信息)
    • https://www.yalala.com/ (单一特征的指纹)
    • http://uniquemachine.org/ (特征合一的指纹)
    • https://pixelscan.net/ (像素扫描信息)
    • https://ja3er.com/ (ja3 SSL指纹)
    • https://iphey.com/#loc-text (以IP为主的数字身份)
    • http://dnscookie.com/ (NDS cookie指纹)
    • https://amiunique.org/fp
    • https://firstpartysimulator.net/kcarter?

    chromedriver指纹

    提一下chromedriver驱动,不论是selenium或者puppeteer或者playwright,基于chromedriver封装的自动化工具库都很容易被网站监测,所以如何应对指纹检测对使用者来说非常重要。

    比如特征参数 webdriver,启动参数no-first-run、window-size、log-level、start-maximized、no-sandbox等,用户特征 user_data_dir、language,以及一些html类型Webelement等。

    设置 webdriver为flase:

    broser.execute_cdp_cmd(
         "Page.addScriptToEvaluateOnNewDocument",
         {
             "source": """
                 Object.defineProperty(window, 'navigator', {
                     value: new Proxy(navigator, {
                             has: (target, key) => (key === 'webdriver' ? false : key in target),
                             get: (target, key) =>
                                     key === 'webdriver' ?
                                     false :
                                     typeof target[key] === 'function' ?
                                     target[key].bind(target) :
                                     target[key]
                             })
                 });
    
         """
         },
    )
    

    具体方法可以参考 undetected-chromedriver 开源库,源码中给出了丰富的解决方法。


    隐藏指纹的插件

    Canvas Fingerprint Defender 隐藏canvas,不适用于最新chrome。

    AudioContext Fingerprint Defender-AudioContext 伪造指纹。

    Chameleon by sereneblue 修改UA、分辨率、语言等。

    一些插件已经不适用于新版google的 manifest_version 要求, 那我们也可以手动去禁用一些指纹,比如Canvas 、WebGL,或者直接禁用JavaScript,但是会影响网站正常运行。

    甚至于禁用JavaScript后,一些网站还会根据页面的CSS样式表来获取信息。


    修改指纹的浏览器

    所以有时候可以使用指纹浏览器来进行调试。

    巨象浏览器
    AdsPower浏览器
    阿拉鱼指纹浏览器
    hubstudio指纹浏览器
    洋葱浏览器


    反爬指纹的生成

    目前常见的反爬指纹有

    • 基于某种算法的请求指纹(如:TLS-Ja3、报文指纹)
    • 基于某种算法生成的环境指纹 (如:fingerprint2)
    • 基于服务器预设文件执行结果返回的接口调用信息(如:日志)
    • 基于浏览器对服务器不同参数的动画渲染提取出浏览器的帧数信息

    这些指纹都可生成值用于校验,无论是在验证请求或者是数据解密。不过指纹用于检验时一般是和其他信息结合起来使用的,所以一些站点​只通过堆号已经无法有效采集了。

    在这里插入图片描述

    比如https://fingerprintjs.com/demo/的示例。

    其算法与浏览器信息生成和设备关联的唯一标识符,用于访问识别,具体方法可阅读官方文档。
    在这里插入图片描述


    canvas指纹

    在线查看:https://browserleaks.com/canvas

    Canvas 是一种 HTML5 API,相当于一个画布,用于通过 JavaScript 脚本在网页上绘制图形和动画。

    因为Canvas 在不同操作系统不同浏览器上所产生的图片内容基本不同,所以其可用作浏览器指纹识别中的特征,用于标识身份。

    但是需要注意 canvas 指纹并不具备唯一性,所以常和其他指纹结合起来计算唯一身份ID。

    在这里插入图片描述
    在这里插入图片描述

    那在Js中如何获取Canvas 指纹呢,通常是基于Canvas 绘制特定内容的图片,然后使用 canvas.toDataURL()方法返回该图片内容的base64编码字符串,这一点在我们补环境时也经常遇到。

    那么在补的时候呢,看它的调用方法和返回结果,然后取出base64值放到toDataURL()中。

    document = {
    	createElement: function createElement(x) {
    		return canvas
    	}
    };
    
    canvas = {
    	toDataURL: function toDataURL() {
    		return "data:image/png;base64,i.....ggg=="
    	},
    	getContext: function getContext(x) {
            if (x === "xxx") {
                return 
            } else {
                return CanvasContext 
            }
    	}
    };
    
    CanvasContext = {
    	arc: function arc() {},
    	stroke: function stroke() {},
    	fillText: function fillText() {},
    	toString: function() {
            return "[object]"
        }
    };
    
    canvas[Symbol.toStringTag] = "HTMLCanvasElement";
    

    音频指纹

    浏览器音频指纹AudioContext 测试地址 :https://audiofingerprint.openwpm.com/

    AudioContext 指纹是计算机音频堆栈本身的属性,AudioContext接口表示由链接在一起的音频模块构建的音频处理图,音频上下文控制它包含的节点的创建和音频处理或解码的执行。

    在FingerprintJS2有获取音频指纹的代码。

    在这里插入图片描述

    音频指纹会受到硬件影响,因为音频信号的处理上不同,不同机器下或不同浏览器产生的音频输出存在差异。

    比如用google浏览器和微信内置浏览器进行对比,缓冲区值的总和是不同的,这就导致生成的hash值也不同。

    在这里插入图片描述

    但需要注意的是,同机器下AudioContext 的属性似乎是相同的,所以当发现有此类检测时,可以尝试修改一些音频属性。


    工具站

    我在工具站中加了fingerprint2,可以来看看你的浏览器环境。

    cnlans.com/lx/tools

    展开全文
  • 来源 |http://www.fly63.com/article/detial/10479什么是浏览器指纹浏览器指纹”是一种通过浏览器对网站可见的配置和设置信息来跟踪Web浏览器的方法...

    来源 | http://www.fly63.com/article/detial/10479

    什么是浏览器指纹

    “浏览器指纹”是一种通过浏览器对网站可见的配置和设置信息来跟踪Web浏览器的方法,浏览器指纹就像我们人手上的指纹一样,具有个体辨识度,只不过现阶段浏览器指纹辨别的是浏览器。

    人手上的指纹之所以具有唯一性,是因为每个指纹具有独特的纹路、这个纹路由凹凸的皮肤所形成。

    每个人指纹纹路的差异造就了其独一无二的特征。

    那么浏览器指纹也是同理,获取浏览器具有辨识度的信息,进行一些计算得出一个值,那么这个值就是浏览器指纹。

    辨识度的信息可以是UA、时区、地理位置或者是你使用的语言等等,你所选取的信息决定了浏览器指纹的准确性。

    对于网站而言,拿到浏览器指纹并没有实际价值,真正有价值的是这个浏览器指纹对应的用户信息。

    作为网站站长,收集用户浏览器指纹并记录用户的操作,是一个有价值的行为,特别是针对没有用户身份的场景。

    例如在一个内容分发网站上,用户A喜欢浏览二次元的内容,通过浏览器指纹记录这个兴趣,那么下次用户不需要登录即可向A用户推送二次元的信息。

    在个人PC如此普及的当下,这也是一种内容分发的方式。

    对于用户而言,建立个人上网行为与浏览器指纹之间的联系或多或少都有侵犯用户隐私的意味,特别是将你的浏览器指纹和真实的用户信息相关联起来的时候。

    所幸的是这种方式对于用户的隐私侵犯比较有限、滥用用户行为也会透支用户对网站的好感。

    浏览器指纹背景

    浏览器指纹追踪技术到目前已经进入2.5代。

    第一代是状态化的,主要集中在用户的cookie和evercookie上,需要用户登录才可以得到有效的信息。

    第二代才有了浏览器指纹的概念,通过不断增加浏览器的特征值从而让用户更具有区分度,例如(UA、浏览器插件信息)

    第三代是已经将目光放在人身上了,通过收集用户的行为、习惯来为用户建立特征值甚至模型,可以实现真正的追踪技术,这部分目前实现比较复杂,依然在探索中。

    目前处于2.5代是因为现在需要解决的问题是如何解决跨浏览器识别指纹的问题上,稍后会介绍下这方面所取得的成果。

    指纹采集

    信息熵(entropy)是接收的每条消息中包含的信息的平均量,信息熵越高,则能传输越多的信息,信息熵越低,则意味着传输的信息越少。

    浏览器指纹是由许多浏览器的特征信息综合起来的,其中特征值的信息熵也不尽相同。因此,指纹也分为基本指纹和高级指纹。

    基本指纹

    基本指纹就是容易被发现和修改的部分,如 http 的 header。

    {  "headers": {        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",         "Accept-Encoding": "gzip, deflate, br",         "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",         "Host": "httpbin.org",         "Sec-Fetch-Mode": "navigate",         "Sec-Fetch-Site": "none",         "Sec-Fetch-User": "?1",         "Upgrade-Insecure-Requests": "1",         "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"  }}
    

    除了 http 中拿到的指纹,还可以通过其他方式来获得浏览器的特征信息,例如:

    每个浏览器的UA
    浏览器发送的 HTTP ACCEPT 标头
    浏览器中安装的浏览器扩展/插件,例如 Quicktime,Flash,Java 或 Acrobat,以及这些插件的版本
    计算机上安装的字体。
    浏览器是否执行 JavaScript 脚本
    浏览器是否能种下各种 cookie 和 “super cookies”
    是否浏览器设置为“Do Not Track”
    系统平台(例如 Win32、Linux x86)
    系统语言(例如 cn、en-US)
    浏览器是否支持触摸屏

    拿到这些值后可以进行一些运算,得到浏览器指纹具体的信息熵以及浏览器的 uuid。

    这些信息就类似人类的体重、身高、肤色一样,有很大的重复概率,只能作为辅助识别,所以我们需要更精确的指纹来判断唯一性。

    高级指纹

    普通指纹是不够区分独特的个人,这时就需要高级指纹,将范围进一步缩小,甚至生成一个独一无二的跨浏览器身份。

    用于生产指纹的各个信息,有权重大小之分,信息熵大的将拥有较大的权重。


    如何完整修改浏览器指纹?

    接下来教大家如何修改浏览器指纹,例如修改navigator全部参数:

    (function() {    'use strict';
        function fakeActiveVRDisplays() { return "Not Spoofed"; }    function fakeAppCodeName() {      return "Mozilla";    }    function fakeAppName() {      return "Netscape";    }
        function fakeAppVersion() {        return "5.0 (Windows)";    }    function fakeBattery() { return "Not Spoofed"; }    function fakeConnection() { return "Not Spoofed"; }    function fakeGeoLocation() { return "Not Spoofed"; }    function fakeHardwareConcurrency() {      return 1;    }    function fakeJavaEnabled() {      return false;    }    function fakeLanguage() {        // NOTE: TOR Browser uses American English        return "en-US";    }    function fakeLanguages() {        // NOTE: TOR Browser uses American English        return "en-US,en";    }    function fakeMimeTypes() { return "Not Spoofed"; }    function fakeOnLine() {      return true;    }    function fakeOscpu() {      return "Windows NT 6.1";    }    function fakePermissions() { return "Not Spoofed"; }    function fakePlatform() {      return "Win32";    }    function fakePlugins() {        return window.navigator.plugins;    }    function fakeProduct() {      return "Gecko";    }    function fakeServiceWorker() { return "Not Spoofed"; }    function fakeStorage() { return "Not Spoofed"; }    function fakeUserAgent() {      // NOTE: Current TOR User Agent as of 19 July 2017        // NOTE: This will need constant updating.        // NOTE: As TOR changes firefox versions each update,        // NOTE: Shape Shifter will need to keep up.        return "Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0";    }    function fakeBuildID() {      return "20100101";    }
    const fakeActiveVRDisplaysValue       = fakeActiveVRDisplays();    const fakeAppCodeNameValue            = fakeAppCodeName();    const fakeAppNameValue                = fakeAppName();    const fakeAppVersionValue             = fakeAppVersion();    const fakeBatteryValue                = fakeBattery();    const fakeConnectionValue             = fakeConnection();    const fakeGeoLocationValue            = fakeGeoLocation();    const fakeHardwareConcurrencyValue    = fakeHardwareConcurrency();    const fakeJavaEnabledValue            = fakeJavaEnabled();    const fakeLanguageValue               = fakeLanguage();    const fakeLanguagesValue              = fakeLanguages();    const fakeMimeTypesValue              = fakeMimeTypes();    const fakeOnLineValue                 = fakeOnLine();    const fakeOscpuValue                  = fakeOscpu();    const fakePermissionsValue            = fakePermissions();    const fakePlatformValue               = fakePlatform();    const fakePluginsValue                = fakePlugins();    const fakeProductValue                = fakeProduct();    const fakeServiceWorkerValue          = fakeServiceWorker();    const fakeStorageValue                = fakeStorage();    const fakeUserAgentValue              = fakeUserAgent();    const fakeBuildIDValue                = fakeBuildID();
        Object.defineProperties(window.navigator, {        /*        activeVRDisplays: {            configurable: true,            enumerable: true,            get: function getActiveVRDisplays() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.activeVRDisplays");                return fakeActiveVRDisplaysValue;            }        },        */
            appCodeName: {            configurable: true,            enumerable: true,            get: function getAppCodeName() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.appCodeName");
                    return fakeAppCodeNameValue;            }        },        appName: {            configurable: true,            enumerable: true,            get: function getAppName() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.appName");
                    return fakeAppNameValue;            }        },        appVersion: {            configurable: true,            enumerable: true,            get: function getAppVersion() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.appVersion");
                    return fakeAppVersionValue;            }        },
            // TODO: This is getBattery() now        /*        battery: {            configurable: true,            enumerable: true,            get: function getBattery() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.battery");                return fakeBatteryValue;            }        },        connection: {            configurable: true,            enumerable: true,            get: function getConnection() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.connection");                return fakeConnectionValue;            }        },        geolocation: {            configurable: true,            enumerable: true,            get: function getGeoLocation() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.geolocation");                return fakeGeoLocationValue;            }        },        */
            hardwareConcurrency: {            configurable: true,            enumerable: true,            get: function getHardwareConcurrency() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.hardwareConcurrency");
                    return fakeHardwareConcurrencyValue;            }        },
            /*        javaEnabled: {            configurable: true,            enumerable: true,            value: function getJavaEnabled() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.javaEnabled");                return fakeJavaEnabledValue;            }        },        */
            language: {            configurable: true,            enumerable: true,            get: function getLanguage() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.language");
                    return fakeLanguageValue;            }        },        languages: {            configurable: true,            enumerable: true,            get: function getLanguages() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.languages");
                    return fakeLanguagesValue;            }        },
            /*        mimeTypes: {            configurable: true,            enumerable: true,            get: function getMimeTypes() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.mimeTypes");                return fakeMimeTypesValue;            }        },        */
            onLine: {            configurable: true,            enumerable: true,            get: function getOnLine() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.onLine");
                    return fakeOnLineValue;            }        },        oscpu: {            configurable: true,            enumerable: true,            get: function getOscpu() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.oscpu");
                    return fakeOscpuValue;            }        },
            /*        permissions: {            configurable: true,            enumerable: true,            get: function getPermissions() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.permissions");                return fakePermissionsValue;            }        },        */
            platform: {            configurable: true,            enumerable: true,            get: function getPlatform() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.platform");
                    return fakePlatformValue;            }        },
            /*        plugins: {            configurable: true,            enumerable: true,            get: function getPlugins() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.plugins");                return fakePluginsValue;            }        },        */
            product: {            configurable: true,            enumerable: true,            get: function getProduct() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.product");
                    return fakeProductValue;            }        },
            /*        serviceWorker: {            configurable: true,            enumerable: true,            get: function getServiceWorker() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.serviceWorker");                return fakeServiceWorkerValue;            }        },        storage: {            configurable: true,            enumerable: true,            get: function getStorage() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.storage");                return fakeStorageValue;            }        },        */
            userAgent: {            configurable: true,            enumerable: true,            get: function getUserAgent() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.userAgent");
                    return fakeUserAgentValue;            }        },        buildID: {            configurable: true,            enumerable: true,            get: function getBuildID() {                console.log("[ALERT] " + window.location.hostname + " accessed property Navigator.buildID");
                    return fakeBuildIDValue;            }        }    });})();
    

    另外关于浏览器硬件指纹,包括canvas,webgl,fonts,audio等。

    Canvas 指纹

    Canvas 是 HTML5 中的动态绘图标签,也可以用它生成图片或者处理图片。即便使用 Canvas 绘制相同的元素,但是由于系统的差别,字体渲染引擎不同,对抗锯齿、次像素渲染等算法也不同,Canvas 将同样的文字转成图片,得到的结果也是不同的。

    实现代码大致为:在画布上渲染一些文字,再用 toDataURL 转换出来,即便开启了隐私模式一样可以拿到相同的值。

    function getCanvasFingerprint () {        var canvas = document.createElement('canvas');        var context = canvas.getContext("2d");        context.font = "18pt Arial";        context.textBaseline = "top";        context.fillText("Hello, user.", 2, 2);        return canvas.toDataURL("image/jpeg");}getCanvasFingerprint()
    

    流程很简单,渲染文字,toDataURL 是将整个 Canvas 的内容导出,得到值。

    WebGL 指纹

    WebGL(Web图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。

    WebGL 通过引入一个与 OpenGL ES 2.0 非常一致的 API 来做到这一点,该 API 可以在 HTML5 元素中使用。

    这种一致性使 API 可以利用用户设备提供的硬件图形加速。网站可以利用 WebGL 来识别设备指纹,一般可以用两种方式来做到指纹生产:

    WebGL 报告——完整的 WebGL 浏览器报告表是可获取、可被检测的。在一些情况下,它会被转换成为哈希值以便更快地进行分析。

    WebGL 图像 ——渲染和转换为哈希值的隐藏 3D 图像。由于最终结果取决于进行计算的硬件设备,因此此方法会为设备及其驱动程序的不同组合生成唯一值。

    这种方式为不同的设备组合和驱动程序生成了唯一值。

    可以通过 Browserleaks test 检测网站来查看网站可以通过该 API 获取哪些信息。

    产生WebGL指纹原理是首先需要用着色器(shaders)绘制一个梯度对象,并将这个图片转换为Base64字符串。

    然后枚举WebGL所有的拓展和功能,并将他们添加到Base64字符串上,从而产生一个巨大的字符串,这个字符串在每台设备上可能是非常独特的。

    例如fingerprint2js库的 WebGL 指纹生产方式:

    // 部分代码 gl = getWebglCanvas()    if (!gl) { return null }    var result = []    var vShaderTemplate = 'attribute vec2 attrVertex;varying vec2 varyinTexCoordinate;uniform vec2 uniformOffset;void main(){varyinTexCoordinate=attrVertex+uniformOffset;gl_Position=vec4(attrVertex,0,1);}'var fShaderTemplate = 'precision mediump float;varying vec2 varyinTexCoordinate;void main() {gl_FragColor=vec4(varyinTexCoordinate,0,1);}'var vertexPosBuffer = gl.createBuffer()    gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer)    var vertices = new Float32Array([-0.2, -0.9, 0, 0.4, -0.26, 0, 0, 0.732134444, 0])// 创建并初始化了Buffer对象的数据存储区。gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW) vertexPosBuffer.itemSize = 3vertexPosBuffer.numItems = 3// 创建和初始化一个WebGLProgram对象。var program = gl.createProgram()// 创建着色器对象var vshader = gl.createShader(gl.VERTEX_SHADER)// 下两行配置着色器 gl.shaderSource(vshader, vShaderTemplate)  // 设置着色器代码  gl.compileShader(vshader) // 编译一个着色器,以便被WebGLProgram对象所使用
    var fshader = gl.createShader(gl.FRAGMENT_SHADER)   gl.shaderSource(fshader, fShaderTemplate)    gl.compileShader(fshader)    // 添加预先定义好的顶点着色器和片段着色器  gl.attachShader(program, vshader)gl.attachShader(program, fshader) // 链接WebGLProgram对象   gl.linkProgram(program)// 定义好的WebGLProgram对象添加到当前的渲染状态  gl.useProgram(program)    program.vertexPosAttrib = gl.getAttribLocation(program, 'attrVertex')    program.offsetUniform = gl.getUniformLocation(program, 'uniformOffset')                           gl.enableVertexAttribArray(program.vertexPosArray)    gl.vertexAttribPointer(program.vertexPosAttrib, vertexPosBuffer.itemSize, gl.FLOAT, !1, 0, 0)    gl.uniform2f(program.offsetUniform, 1, 1)// 从向量数组中绘制图元  gl.drawArrays(gl.TRIANGLE_STRIP, 0, vertexPosBuffer.numItems)    try {            result.push(gl.canvas.toDataURL())    } catch (e) {            /* .toDataURL may be absent or broken (blocked by extension) */}
    

    防御浏览器指纹追踪

    这是一个比较暴力的方法,直接禁止网站使用JavaScript可以非常有效地防御浏览器指纹追踪,但是这样会导致页面较大部分地功能不可用。

    而且非常不幸的是,即便禁止了js但是还可以通过css来采取浏览器的信息,例如:

    @media(device-width: 1080px) {  body {    background: url("https://example.org/1080.png");  }}
    

    总结

    对于浏览器指纹,攻与防在不断的转换,目前浏览器指纹也不能绝对的标识一台主机,如果用户切换显卡或者双系统,虚拟机这些因素,那么目前的浏览器指纹就无法唯一标识了。

    未来随着新的HTML5技术不断更新,新的浏览器技术会提供更多的API,以及通过侧信道技术,在浏览器指纹会有新的突破。

    学习更多技能

    请点击下方公众号

    展开全文
  • 在如今,做安全防御已经不仅仅是被动的等着攻击者攻击,作为防御⽅,有越来越多的⽅法去反击攻击者,甚⾄给攻击者⼀些威胁...设备指纹技术是⼀种⻓久有效的追踪技术,即使攻击者挂再多 vpn,也能够准确识别攻击者身份。
  • 一文理解浏览器指纹

    2022-05-01 19:16:25
    我们今天就来深入了解下浏览器指纹浏览器指纹是什么? 浏览器指纹可以通过浏览器对网站可见的配置、设置信息,来跟踪 Web 浏览器,它就像我们人手上的指纹一样,具有个体辨识度,只不过现阶段浏览器指纹辨别...

    我们今天就来深入了解下浏览器指纹。

    浏览器指纹是什么?

    浏览器指纹可以是UA,失去,地理位置或者使用的语言等,网站可以通过浏览器指纹获取到对应的使用者用户信息,能识别用户和记录用户的操作,进行个性化推荐。

    现有的浏览器指纹技术,由于目前跨浏览器识别指纹的问题尚未解决,可认为发展到 处于2.5 代:

    • 第一代是状态化的,主要集中在用户的 cookie 和 evercookie 上,需要用户登录才可以得到有效的信息。

    • 第二代才有了浏览器指纹的概念,通过不断增加浏览器的特征值从而让用户更具有区分度,例如 UA、浏览器插件信息等

    • 第三代是已经将目光放在人身上了,通过收集用户的行为、习惯来为用户建立特征值甚至模型,可以实现真正的追踪技术。但是目前实现比较复杂,依然在探索中。

    采集与分析指纹

    浏览器指纹也分为基本指纹和高级指纹,由许多浏览器的特征信息综合起来的,不同特征值的信息熵有异。

    信息熵(entropy)是接收的每条消息中包含的信息的平均量,信息熵越高,则能传输越多的信息,信息熵越低,则意味着传输的信息越少。

    基本指纹就是容易被发现和修改的部分,比如:

    • 每个浏览器的UA

    • 浏览器发送的 HTTP ACCEPT 标头

    • 浏览器中安装的浏览器扩展/插件,例如 Quicktime,Flash,Java 或 Acrobat,以及这些插件的版本

    • 计算机上安装的字体。

    • 浏览器是否执行 JavaScript 脚本

    • 浏览器是否能种下各种 cookie 和 “super cookies”

    • 是否浏览器设置为“Do Not Track”

    • 系统平台(例如 Win32、Linux x86)

    • 系统语言(例如 cn、en-US)

    • 浏览器是否支持触摸屏

    •  http 的 header

    {  
      "headers": {    
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",     
        "Accept-Encoding": "gzip, deflate, br",     
        "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",     
        "Host": "httpbin.org",     
        "Sec-Fetch-Mode": "navigate",     
        "Sec-Fetch-Site": "none",     
        "Sec-Fetch-User": "?1",     
        "Upgrade-Insecure-Requests": "1",     
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"
      }}

    经过运算,得到浏览器指纹具体的信息熵以及浏览器的 uuid,由于基本指纹的重复率较高,只能作为辅助识别,所以人们需要更精确的高级指纹来判断唯一性。甚至生成一个独一无二的跨浏览器身份。

    参考论文《Cross-Browser Fingerprinting via OS and Hardware Level Features》,像时区、屏幕分辨率和色深、Canvas、webGL 的信息熵在跨浏览器指纹上的权重是比较大的:

     

     

    接下来我们来详细看这些高级指纹都包含了些什么信息。

    Canvas 指纹

    Canvas 是 HTML5 中的动态绘图标签,也可以用它生成图片或者处理图片。即便使用 Canvas 绘制相同的元素,但是由于系统的差别,字体渲染引擎不同,对抗锯齿、次像素渲染等算法也不同,Canvas 将同样的文字转成图片,得到的结果也是不同的。

    通过在网站上执行 Canvas 渲染代码,在画布上渲染一些文字,再用 toDataURL 转换出来,如此针对不同浏览器,Canvas 结果不尽相同:

    function getCanvasFingerprint () {    
        const canvas = document.createElement('canvas');    
        const context = canvas.getContext("2d");    
        context.font = "18pt Arial";    
        context.textBaseline = "top";    
        context.fillText("Hello, user.", 2, 2);    
        return canvas.toDataURL("image/jpeg");
    }
    getCanvasFingerprint();

    WebGL 指纹

    WebGL(Web图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。WebGL 通过引入一个与 OpenGL ES 2.0 非常一致的 API 来做到这一点,该 API 可以在 HTML5 元素中使用。这种一致性使 API 可以利用用户设备提供的硬件图形加速。

    网站可以利用 WebGL 来识别设备指纹,一般可以用两种方式来做到指纹生产:

    • WebGL 报告——完整的 WebGL 浏览器报告表是可获取、可被检测的。在一些情况下,它会被转换成为哈希值以便更快地进行分析。
    • WebGL 图像 ——渲染和转换为哈希值的隐藏 3D 图像。由于最终结果取决于进行计算的硬件设备,因此此方法会为设备及其驱动程序的不同组合生成唯一值。这种方式为不同的设备组合和驱动程序生成了唯一值。

    可以通过 Browserleaks test 检测网站来查看网站可以通过该 API 获取哪些信息。

    产生WebGL指纹原理是首先需要用着色器(shaders)绘制一个梯度对象,并将这个图片转换为Base64字符串。然后枚举 WebGL 所有的拓展和功能,并将他们添加到Base64字符串上,从而产生一个巨大的字符串,这个字符串在每台设备上可能是非常独特的。比如 fingerprintjs库的 WebGL 指纹生产。

    如何防止被网站采集“浏览器指纹”

    浏览器指纹可能涉及到隐私泄露,如果不想被网站获取,是需要一些方法来阻止网站的。

    通过浏览器的扩展插件(Canvas Blocker、WebGL Fingerprint Defender、Fingerprint Spoofing等),在网页加载前执行一段 JS 代码,更改、重写 JS 的各个函数来阻止网站获取各种信息,或返回一个假的数据,以此来保护我们的隐私信息,其中重新JS函数 :

    • 混淆时区,就是更改 Date.prototype.getTimezoneOffset 的返回值。
    • 混淆分辨率则是更改documentElement.clientHeight documentElement.clientWidth
    • 混淆 WebGL 则要更改 WebGLbufferData getParameter方法等等。
    • 混淆Canvas 指纹则需要更改 toDataURL 方法,比如 先使用 toDataURL() 将整个canvas的内容导出,通过 getImageData() 复制画布上指定矩形的像素数据并修改然后通过 putImageData() 将图像数据放回,然后再使用 toDataURL() 导出的图片,完成混淆
    展开全文
  • 如何防止浏览器指纹 毫无疑问;浏览器指纹可用于唯一标识您并在线跟踪您。现在请阅读有关如何防止浏览器指纹识别的文章。 某些人认为,为防止进行任何跟踪尝试,他们要做的就是通过代理服务器路由其Web请求,并...
  • 指纹修改工具,适合火狐,谷歌浏览器
  • 什么是浏览器指纹浏览器指纹”是一种通过浏览器对网站可见的配置和设置信息来跟踪Web浏览器的方法,浏览器指纹就像我们人手上的指纹一样,具有个体辨识度,只不过现阶段浏览器指纹辨别的是浏览器。 人手上的...
  • 什么是浏览器指纹  浏览器指纹可以通过浏览器对网站可见的配置、设置信息,来跟踪Web浏览器,它就像我们人手上的指纹一样,具有个体辨识度,只不过现阶段浏览器指纹辨别的是浏览器。  浏览器指纹辨识的信息...
  • 指纹追踪技术(指纹浏览器)的前世今生: 1).第一代 第一代指纹追踪是cookie这类的服务端在客户端设置...浏览器之后,第二代技术中很重要的 canvas 指纹、浏览器插件指纹都变了,所以很难把浏览器指纹归并到同一设备
  • 防印Antiprint是Chrome和Firefox的扩展程序,可使您的浏览器在您访问的网站上显得不那么独特。 在实现这一壮举方面,此扩展既不完整也不正确。 要提出改进方法的建议,请打开一个问题。覆盖区域User-Agent和...
  • 在本篇文章中,我们将概述浏览器指纹识别的基础知识,如何使用它来跟踪互联网用户以及可以采取哪些措施来减少发送的详细信息被识别的可能性。
  • 浏览器指纹追踪类似人的外貌和指纹,Web客户端(这里主要指浏览器)也有多种“外貌”信息和“指纹”信息,将这些信息综合分析计算后,可对客户端进行唯一性识别,进而锁定、追踪、了解网民行为和隐私数据。
  • 浏览器指纹追踪 现实世界可通过体貌特征、身份证件、生物特征(如指纹信息)等手段对用户进行唯一性识别。Web 世界主要通过 Cookies 技术、浏览器指纹、WebRTC 等技术进行识别。 典型追踪技术 —Cookie 追踪 ...
  • 今天讲⼀些让您按捺不住和欲求不满的反浏览器追踪技术,揭开你是如果被互联网巨头监控的。 场景一:在⽹站上浏览了某个商品,了解了相关的商品信息,但并没有下单购买,甚⾄没有进⾏登录操作,过两天⽤同台电脑访问...
  • 浏览器指纹的生成

    千次阅读 2021-09-07 17:08:27
    浏览器指纹”是一种通过浏览器对网站可见的配置和设置信息来跟踪Web浏览器的方法,浏览器指纹就像我们人手上的指纹一样,具有个体辨识度,只不过现阶段浏览器指纹辨别的是浏览器。 查看浏览器指纹信息:...
  • Laravel监视 Laravel Surveillance是一个软件包,用于监视恶意用户,IP地址和匿名浏览器指纹,编写监视日志并阻止恶意用户访问该应用程序。 请在使用此软件包之前阅读下面的重要信息该软件包收集和处理可能是个人...
  • 浏览器指纹识别是一种识别您的身份并收集有关您在线旅行数据的方法。在本文中,我将告诉您浏览器指纹识别的工作原理以及如何防止它。 浏览器指纹识别是一种非常准确的识别独特浏览器和跟踪在线活动的方法。 幸运...
  • 采集浏览器指纹

    千次阅读 2021-12-15 15:11:01
    确定这些信息的过程叫做采集指纹。 一、使用HTTP首部 每一个Http请求和响应中都包含HTTP首部,它随同每一个Web请求发送的信息,详细描述了浏览器支持的特性、请求的URL以及主机名和其他信息。这些首部

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,828
精华内容 7,531
关键字:

浏览器指纹

友情链接: led100.rar