网站可以检测您是否使用隐私浏览模式吗?

信息安全 网页浏览器 隐私
2021-09-01 09:01:04

大多数现代浏览器都支持“隐私浏览模式”(在 Chrome 中也称为“隐身模式”),在这种模式下,浏览器不会将有关您浏览的任何信息保存到磁盘。

在现代浏览器中,网站能否检测到正在访问该网站的用户是否启用了隐私浏览模式?

我做过的背景调查。 这是我能够找到的与此问题相关的内容。不幸的是,它并没有真正回答上面的问题。

  • 2010 年对隐私浏览模式的研究表明,网站可以通过使用 CSS 历史嗅探攻击来检测浏览器是否处于隐私浏览模式。(在隐私浏览模式下,网站不会添加到历史记录中,因此您可以使用历史嗅探来检查访问者是否处于隐私浏览模式。)不过,从那时起,现代浏览器已经加入了针对CSS 历史嗅探攻击的防御。

    因此,我不希望这种检测浏览器是否处于隐私浏览模式的方法会再成功。(我意识到对历史嗅探的防御并不完美,但它们对于这些目的可能已经足够了。)

  • 您正在访问的网站可能有一些方法可以了解您当前是否登录到其他网站(想想:Facebook)。如果用户当前登录到其他服务(如 Facebook),网站可能会合理地猜测用户当前没有使用隐私浏览模式——这不是一个确定的事情,但也许可以做出某种概率推断。但是,如果用户没有登录其他服务,那么我想我们只能说我们不知道是否在使用隐私浏览模式。我想,这可能会导致部分信息泄漏,但它听起来充其量是不可靠的——如果它甚至可以工作的话。这也有可能根本不起作用。

那么,任何人都可以提供有关网站是否可以测试其访问者是否使用隐私浏览模式的最新信息吗?

4个回答

请注意,这个答案是在 2011 年给出的。今天的答案是肯定的——截至 2020 年撰写本文时,已有广泛使用的可靠技术并且已经有一段时间了。有关更多最新信息,请参阅1 2以下的当前最佳答案之一。

我不确定您是否可以可靠地检测到隐私浏览,但我认为您可以应用一些启发式方法来很好地猜测用户正在使用各种隐私增强功能。正如我在对该问题的评论中所指出的,这是否足够好或适合您的应用程序取决于您希望能够对检测到私人浏览做出的反应。正如 Sonny Ordell 所提到的,我也不确定您是否可以将隐私浏览与各种隐私增强功能的临时使用区分开来(例如手动清除历史记录或 cookie)。

假设您操作一个 Web 应用程序,并且您想检测您的一个用户(有帐户)何时切换到隐私浏览。我指定用户有一个帐户,因为此策略依赖于跟踪各种行为数据。隐私浏览的各个方面是(至少在Firefox中):历史记录、表单/搜索条目、密码、下载、cookie、缓存、DOM 存储。我不确定如何探测下载,但我认为可以探测其他的。如果您对所有这些都进行了正面检测,则您的用户似乎更有可能是在进行私人浏览。

  • 在简单的情况下,您跟踪(IP, user-agent)每个用户。当您收到对匹配记录的无 cookie 请求时(IP, UA),您可能会推断出相应的用户是隐私浏览。如果出现以下情况,此方法将失败(未检测到):
  1. 他在隐私浏览期间使用 ProxySwitchy 或 TorButton 之类的东西来激活 Tor,从而更改 IP。
  2. 他切换到不同的浏览器(例如,通常使用 FF 并切换到 Chrome 以进行隐身模式)。
  3. 切换到隐私浏览不是立即的,他的 ISP 已经发布了一个新 IP(例如,周五他是 10.1.2.3,他周末没有使用您的应用程序,周一他是 10.1.4.5)。

正如Sonny Ordell 的回答中提到的,如果另一个人在隐私浏览模式下使用同一浏览器访问您网站上的单独帐户,您将得到检测 - 但这与“普通”用户只是切换的情况略有不同进入隐私浏览模式。

如果用户只是为您的网站清除了他的 cookie,或者使用辅助配置文件(例如,我保留了一些不同的 Firefox 配置文件和不同的插件集以进行某些测试和/或避免跟踪,那么您将得到误报,尽管我'会猜这是非常罕见的)。

  • 作为更复杂的检查,您可以使用EFF 的 panopticlick 之类的东西并维护浏览器指纹(或指纹集合),而不仅仅是每个用户的 UA。这在上述情况 2 中失败(例如,如果用户专门使用 FF 进行可识别浏览,而使用 Chrome 进行隐身浏览)。如果用户禁用了 javascript,指纹将更加通用(因此用处更少)。如果用户在不同的会话中选择性地启用 javascript(例如 NoScript 和临时允许的站点),指纹将会改变。

  • 您可以通过检测通过 Tor 出口节点的访问,并将其与指纹识别相结合,从而击败问题 1 (Tor)。这似乎只在少数情况下有用。

  • 不仅仅是用于上述检查的 cookie,而是 test localStorage如果它通常已启用,并且您的密钥不在此访问的存储中,并且指纹匹配,那么这可能是隐私浏览。显然,如果用户通常禁用存储,那么您将无法使用它。故障模式与上面描述的 cookie 类似。

  • 我没有测试或开发这个想法,但我想你可以用Cache-Control. (快速搜索发现这不是一个原始想法——该项目具有类似于概念验证的代码。)如果用户通过共享缓存代理,此策略将失败——同时页面提到 anonymizer.com . 至少,Firefox 在隐私浏览模式下不使用缓存。(有关基于缓存的跟踪的演示,请参阅此站点。)因此,您可以将其与上面提到的 UA/指纹结合使用:如果您的缓存跟踪器表明这是第一次访问,那么您可以猜测用户是隐私浏览。如果用户清理他的缓存,这将失败并出现误报;结合其他技术以获得更好的猜测。

  • 您可以为每个用户检测和跟踪浏览器是否自动填充某个表单元素。如果您检测到给定用户没有在该表单元素上自动填充,您可能会推断出隐私浏览。这很脆弱——也许用户没有使用他的“主”计算机,但你可以将它与上面提到的指纹结合起来以获得更可靠的猜测。

  • 侧通道定时攻击:检测并跟踪每个用户登录您的应用程序所需的典型时间。会有变化,但我猜你可以准确猜测是否有人在使用密码自动填充。如果用户通常使用密码自动填充(即通过登录页面快速转换),然后对于给定的访问(具有匹配的指纹)没有使用自动填充,则可以推断出隐私浏览。这又是脆弱的;结合其他技术以获得更好的猜测。您还需要检测和纠正给定页面加载时的网络延迟(例如,用户的网络在给定的一天可能只是很慢,而登录页面转换缓慢只是延迟而不是缺少自动填充)。您可能有点邪恶并自动注销用户(给他们一个虚假的错误消息,“请再试一次”

  • 将此与您在关于检测用户是否登录其他服务(例如 Facebook)的问题中提到的内容结合起来,您可以对您的猜测更有信心。

  • 如果你真的有动力,你可以玩 DNS 和跟踪页面加载时间的游戏。对 FF 3.6 和 Chrome 15 的快速测试似乎表明这两种浏览器都不会在隐私浏览模式下清除 DNS 缓存。并且浏览器完全无法控制本地系统的 DNS 缓存。如果您使用旁道 DNS 定时攻击来执行用户跟踪作为指纹识别的替代(或补充),您可能会得到更可靠的猜测。我不确定通过 DNS 时间进行的跟踪有多可靠。

在隐私浏览模式下检测“匿名”用户将更加困难,因为您没有机会积累有关他们“典型”行为的数据。而且,由于大多数功能仅在浏览器会话结束时才会启动,因此您真的不知道它们是否会再次出现。

话虽如此,这是一个检测匿名用户私人浏览的想法,如果你愿意作恶,并且你有一些资源,你知道用户愿意给你的网站第二次机会,你可以强制用户启用 javascript。跟踪指纹、设置持久性 cookie、localStorage、缓存——您可以做任何事情来跟踪用户。如果根据您的指纹是第一次访问,请通过 javascript(或 flash,或您知道的任何邪恶技巧)使浏览器崩溃/挂起。占用大量内存,或者陷入循环,或者采取任何措施让用户关闭浏览器。然后当他们返回时,您(从指纹)看到这是第二次访问。如果 cookie/storage/cache/etc 没有设置,那么你可以推断第一个会话是隐私浏览,我想你可能会推断出第二个会话可能也是私人浏览。如果用户不回来,或者你不能崩溃/说服他们杀死浏览器窗口,这显然会失败。作为奖励,如果您将它们发送到自定义 URL,并且它们处于非私有模式并恢复浏览会话,那么您可以猜测它们不是处于私有浏览模式(除非他们为 URL 添加了书签)。

上面的所有东西都充满了漏洞——有足够的空间容纳误报或误报。您可能永远不会知道我是在使用隐私浏览,还是在没有持久存储的 VM 中运行浏览器。(有什么不同?)

最糟糕的部分可能是,如果您确实得到了检测隐私浏览的可靠方法的答案,那么它似乎不太可能在很长一段时间内保持可行,因为浏览器要么“修复”它,要么用户找到解决方法来避免检测。

HTML 5 本地存储检查允许您现在(2019 年)可靠地检测隐私浏览模式。它通过尝试写入然后读取“本地存储”来工作。

看:

https://gist.github.com/jherax/a81c8c132d09cc354a0e2cb911841ff1

或者

https://github.com/jLynx/PrivateWindowCheckPoC

  ------ edit to add functional description ----

从上面的 jherax 链接:

...
    // **Firefox**
    if ('MozAppearance' in document.documentElement.style) {
      if (indexedDB === null) return yes();
      const db = **indexedDB.open**('test');
      db.onerror = yes;
      db.onsuccess = not;
      return void 0;
---

来自上面的 jLynx

...
        } else if(navigator.userAgent.includes("Firefox")){
            //Firefox
            var db = indexedDB.open("test");
            db.onerror = function(){resolve(true);};
            db.onsuccess =function(){resolve(false);};
---

在这两个示例中,无法打开持久性本地存储,用于 Firefox 的indexDB(由 HTML 5 定义)表示隐私浏览。其他浏览器使用不同的名称调用本地存储,例如localStorage,请看图。

您可以使用启发式方法做出可靠的猜测。例如,在 IE10 和 IE11(以及 Safari、IIRC)中,尝试使用 IndexedDB 作为浏览器处于 InPrivate 模式的强烈提示时会引发异常。

同样,当浏览器处于 InPrivate/Incognito 时,Adobe 的 DRM 系统(显然由 HBOGO 使用)会显示错误代码,因为不允许在私有模式下创建所需的“许可证工件”。https://forums.adobe.com/thread/1189199

我看到有一个赏金,因为你想要一个更精确和最新的答案,但事实是其他人已经给出了正确的答案。尽管我不是 JS 开发人员,而且我也不知道这些东西是如何工作的,但我可以给你更多细节。

简短的回答是:他们使用 JavaScript 来实现某种启发式方法,主要检查某些功能是否可用。

看看bostonglobe.com例如。在隐私模式下点击一篇文章,您会看到提示:“您处于隐私模式等”。如果禁用 JavaScript,则不会出现该通知,这意味着它是在 JS 中完成的。如果你去纽约时报也是如此,它只是 JS。但他们究竟是如何做到的呢?bostonglobe.com我发现一个名为JS文件的代码meter.js源。如果您在该代码中搜索,detectPrivateMode您将看到它使用的功能。它被缩小了,所以阅读起来很痛苦。然而,在浏览器的开发工具中美化源代码会给出以下代码:

detectPrivateMode: function (t) {
  var e;
  if (window.webkitRequestFileSystem) window.webkitRequestFileSystem(window.TEMPORARY, 1, function () {
    e = !1
  }, function (t) {
    console.log(t),
    e = !0
  });
   else if (window.indexedDB && /Firefox/.test(window.navigator.userAgent)) {
    var i;
    try {
      i = window.indexedDB.open('test')
    } catch (t) {
      e = !0
    }
    void 0 === e && n(function () {
      return 'done' === i.readyState
    }, function (t) {
      t || (e = !i.result)
    })
  } else if (r(window.navigator.userAgent)) {
    e = !1;
    try {
      window.indexedDB || (e = !0)
    } catch (t) {
      e = !0
    }
  } else if (window.localStorage && /Safari/.test(window.navigator.userAgent)) {
    if (window.safariIncognito) e = !0;
     else {
      try {
        window.openDatabase(null, null, null, null)
      } catch (t) {
        e = !0
      }
      try {
        window.localStorage.setItem('test', 1)
      } catch (t) {
        e = !0
      }
    }
    void 0 === e && (e = !1, window.localStorage.removeItem('test'))
  }
  n(function () {
    return void 0 !== e
  }, function (n) {
    t(e)
  })
}

例如,您可以看到他们正在尝试使用window.webkitRequestFileSystem,在 Firefox 中他们会尝试window.indexedDB.open('test'),在 Safarywindow.openDatabase, 等等。所有这些功能似乎都依赖于它们在私人模式(隐身模式)下表现不同的事实。大多数代码似乎使用与本地存储相关的函数,这显然与正常模式下的行为不同。有几个 try-catch 块,因此其中大多数功能甚至可能在私有模式下都不可用。如果你用谷歌搜索这些功能中的任何一个(也可能在搜索中添加“私人”或“隐身”),你会发现很多讨论检测私人模式的可能方法的结果,最后你会发现代码看起来与我引用的非常相似。您会在 StackExchange 以及 GitHub 上的代码片段上找到几个问题。例如,StackExchange 上的这个答案有一些有趣的信息:https ://stackoverflow.com/a/41322183

在《纽约时报》上,如果你点击一篇文章,打开 HTML 源代码,然后搜索webkitRequestFileSystem,你会发现类似的代码。

如您所见,代码和它们使用的启发式方法可能存在一些差异,但每个网站都可能通过依赖相同的一小部分函数来检测私有模式。