瀏覽器隱身模式下的你,仍然沒有任何隱私

你以爲你瀏覽器開了隱身模式,你就真的 "隱身" 了嗎?No!No!No!今天帶你從前端的視角來看了解瀏覽器的隱身模式

本文從科普和技術視角對瀏覽器隱身模式進行介紹,全文脈絡如下,讀者可根據興趣選擇對應章節閱讀。

腦圖

認識隱私模式

隱私模式隱藏了什麼

現代網絡瀏覽器,大多數都增加了隱私瀏覽模式來瀏覽網頁,旨在保護用戶隱私。Chrome 稱之爲隱身模式;Opera、Safari 和 Firefox 中一般稱爲隱私瀏覽。這些模式以深色主題和蒙面人物圖標爲特徵,可以給用戶一種匿名瀏覽的印象。芝加哥大學和漢諾威萊布尼茨大學的研究人員發現,人們對隱私瀏覽或隱身模式存在很多誤解,許多用戶認爲隱私瀏覽可以保護他們免受惡意軟件、廣告、跟蹤腳本和互聯網服務提供商 (ISP) 的監控。

其實,隱私瀏覽旨在避免在計算機上保留瀏覽會話的痕跡。因此,當你打開隱私窗口時,主瀏覽窗口中的 cookie、瀏覽歷史不會被保留。當你關閉隱私瀏覽窗口時,你的瀏覽歷史記錄、保存的密碼以及你在該窗口的文本字段中鍵入的內容(用戶名、電話號碼等)都將被擦除。這意味着使用你的計算機並啓動瀏覽器的下一個人將無法找出你在私人瀏覽會話期間訪問了哪些網站,即便是你自己,當下次使用這些網站未登錄帳戶時,你也將以新用戶的身份出現。

隱私瀏覽是一種非常有用且方便的工具,可用於快速瀏覽會話,不會在你的計算機上留下痕跡。它將保護你的隱私免受使用你計算機的其他人的侵害,並減少你在訪問網站時透露的一些有關你自己的信息。但是隱私瀏覽不會讓你匿名,也不會保護你免受監視和大型技術窺探。

說到泄露隱私,很多人認爲只要自己不登錄、不使用 cookie,使用瀏覽器的無痕模式,自己的數據信息就是安全的、自己瀏覽了什麼就只有自己知道了,那麼,我們不妨直接看看瀏覽器官方自己的定義吧。

無痕模式(Incognito mode)是 Chrome 瀏覽器的一種設置,在 Chrome 瀏覽器裏,它是這樣描述的:

incognito_mode

簡單來說,Chrome 無痕模式只是幫你刪除了你存在本地的搜索和瀏覽記錄,只是看起來 “無痕” 而已。要在 Chrome 中以隱身模式打開頁面,請單擊右上角的三點圖標,從出現的下拉菜單中選擇打開新的無痕窗口,或按 Ctrl+Shift+N。一個帶有深色主題的新窗口彈出,並顯示一條通知:“您已進入無痕模式”, 細則解釋了隱身模式的優缺點。默認情況下,第三方 cookie(用於跨不同站點跟蹤你)被禁用。

至於如何開啓隱身模式,相信大多數人都是知道的,如果不知道,或者不知道某一款特定的瀏覽器如何開啓隱身模式,可以參考下面這個鏈接。

How do I set my browser to Incognito or private mode?[1]

在實踐中,即使在隱私模式下,網站仍然可以通過關聯其他信息來發現你的身份,例如你的 IP 地址、設備類型和瀏覽習慣(一天中的時間、訪問的頁面等),隱私瀏覽不會隱藏任何數據。Facebook 和 Google 等大型科技公司擁有大量關於用戶的信息,通過連接這些點,即使你尚未登錄帳戶,它們也可以識別你的身份。

瀏覽器隱身模式真的可以隱身嗎?

通過前面的介紹,想必你的答案是確定的:不能。

我們可以通過一個展示隱私瀏覽跟蹤的示例網站 —— Nothing Private[2] 來證明這一點。這個網站的測試方式是讓你先提交一個你的標識信息,之後讓你使用瀏覽器的無痕模式訪問網站,猜猜網站會不會認出你。

這裏,我先填入了 “獨釣寒江雪”,很明顯的,當我提交信息時,瀏覽器除了發送了我填寫的 “獨釣寒江雪”,還有一個finger字段。

nothingprivate1

當我使用無痕模式再次打開這個網站時,瀏覽器又攜帶了相同的finger字段去服務器查詢相關信息,於是,我被識別出來了。

nothingprivate2

綜上:瀏覽器無痕模式並不能保護你的數據信息不被網站的服務器所獲取。準確的說,無痕模式就是掩耳盜鈴而已。有興趣的話,您不妨親自去 Nothing Private[3] 體驗一下,關於它的原理,後續章節會繼續介紹。

隱私模式不能幹什麼

隱私模式使用現狀

2017 年,DuckDuckGo[4] 對 5,710 名美國人進行了瀏覽器隱私模式調查,以瞭解人們對隱私模式的認識以及他們如何使用這一常見的隱私功能,完整報告可參考:A Study on Private Browsing: Consumer Usage, Knowledge, and Thoughts[5]。

簡單總結如下:

參考資料:Is Private Browsing Really Private?[6]

從技術視角看隱身模式

用戶訪問網站的過程

一般情況下,用戶訪問網站的過程如下圖所示:

browsing_process1

當一位用戶瀏覽網頁時,一般會進行以下操作:

可以看到整個過程一般而言有 3 種數據是保存在用戶的電腦上的,那就是瀏覽記錄、臨時文件與 Cookie 和表單填寫的內容。而有 1 或 2 種的數據被保留在了網站那邊,就是 IP 地址和用戶填寫的註冊信息。

現在非常多的公司和學校建立了專有的網絡環境,對外只顯示 1 個 IP,數據返回的時候再發送到相應的內網 IP 上。僱主和學校有心想看的話還是能夠知道內網的某個人瀏覽了什麼。對於 HTTP 網站鏈接,僱主和學校能夠完整的瞭解用戶瀏覽了哪些網站,用戶看了哪些內容,停留了多久,針對哪些網站進行了點擊跳轉等等;對於 HTTPS 網站鏈接,由於證書的存在和相應的驗證機制,一般而言 HTTPS 解密(中間人攻擊)很難發動,所以只能夠了解到用戶瀏覽了哪些網站而已。同時不恰當的網絡環境也會將自己的瀏覽記錄暴露在他人的視野中,比如免費公用的 Wi-Fi。

browsing_process2

瀏覽器隱身模式檢測的博弈

在 Chrome 76 之前,存在一個漏洞,許多網站利用該漏洞來檢測用戶是否在 Chrome 的隱身模式下訪問網站。這些網站只需要嘗試使用 FileSystem API 用於存儲臨時或永久文件的 。此 API 在隱身模式下被禁用,但在非隱身模式下存在,因此產生了差異,該差異被利用來檢測用戶是否正在使用隱身模式瀏覽網站並阻止這些用戶查看網站的內容。

const fs = window.RequestFileSystem || window.webkitRequestFileSystem;
if (!fs) {
  console.log('check failed?');
} else {
  fs(
    window.TEMPORARY,
    100,
    console.log.bind(console, 'not in incognito mode'),
    console.log.bind(console, 'incognito mode')
  );
}
複製代碼

後來谷歌修復了一個漏洞,不幸的是,他們的修復導致了另外兩種方法,仍然可以用來檢測訪問者何時進行私密瀏覽。

if ('storage' in navigator && 'estimate' in navigator.storage) {
  const { usage, quota } = await navigator.storage.estimate();
  console.log(`Using ${usage} out of ${quota} bytes.`);

  if (quota < 120000000) {
    console.log('Incognito');
  } else {
    console.log('Not Incognito');
  }
} else {
  console.log('Can not detect');
}
複製代碼

timings

Chrome 開發人員看到了這兩點:在 2018 年 3 月的設計文檔中,他們確定了基於時間和文件系統大小檢測隱私模式的風險,並進行了替代實現:只將元數據保存在內存中,並加密磁盤上的文件。這將解決網站使用時間來區分內存和磁盤存儲的風險,並消除基於文件系統大小和文件系統類型(臨時與持久)的差異。

然而,這樣的解決方案有其自身的權衡。雖然它可以抵禦隱私模式檢測,但它會留下元數據:即使數據本身無法解密,它的存在也提供了隱身使用的證據。

如果我們考慮隱身模式的威脅模型,其主要目的是保護同一設備的其他用戶的隱私,而不是您訪問的網站的隱私,這種權衡可能是不值得的。

隱私模式下如何標識用戶

設備唯一標識與瀏覽器指紋

我們都知道,瀏覽器隱身模式可以讓別人無法知道你都訪問了什麼網站和做了什麼操作,在隱身模式下,打開的網頁和加載的文件不會記錄到你的瀏覽歷史記錄以及加載歷史記錄中。在你關閉打開的全部隱身窗口後,系統會刪除所有新 Cookie。但是,做爲程序猿的我們,如果有類似以下場景:

公衆號

這對我們來說,無疑是一個巨大的困擾,我們或許都知道設備唯一標識的概念,但在瀏覽器端,在隱身模式下,在無需用戶額外授權時,我們該如何拿到設備唯一標識呢?

在開發場景下,唯一的標識一個設備是一個基本功能,可以擁有很多應用場景,比如軟件授權(如何保證你的軟件在授權後才能在特定機器上使用)、軟件 License,設備標識,設備身份識別等。

如果說要獲取設備唯一標識,也許你會想到類似 IMEI、Android ID、MAC 地址等思路,但是 Android 10 中官方文檔 [9] 中有以下兩個表述:

一個電腦可能存在多個網卡,多個 MAC 地址,MAC 地址另外一個更加致命的弱點是,MAC 地址很容易手動更改。

至於 Android ID,則不具有真正的唯一性,ROOT、刷機、恢復出廠設置、不同簽名的應用等都會導致獲取的 Android ID 發生改變,並且不同廠商定製的系統的 BUG 會導致不同的設備可能會產生相同的 Android ID。

其他一些獲取設備唯一標識的方法,這篇文章有比較全面的論述:

獲取設備唯一標識(Unique Identifier):Windows 系統 [10]

廣告商是如何追蹤我們?日常使用手機該怎樣保護隱私 [11] 這篇文章有一張圖則是一個更好的彙總:

identifying

而如果回到我們前端場景下,以上這些方法又多了很多侷限性,比如有的需要特許權限,有的需要依賴於原生開發的配合,那麼,有沒有一種只需要前端參與,也可以獲得不錯的準確率的唯一標識方案呢?—— 此時就到了瀏覽器指紋登場的時候了。

FingerPrint 即我們常說的指紋識別,使用手指和拇指前端的紋理按下的紋印來鑑定身份。指紋是鑑別身份的一種可靠的方法,具有唯一性,因爲每個人的每個指頭上的紋理排列各不相同而且不因發育或年齡而改變。而瀏覽器指紋是指僅通過瀏覽器的各種信息,如 CPU 核心數、顯卡信息、系統字體、屏幕分辨率、瀏覽器插件等組合成的一個字符串,就能近乎絕對定位一個用戶,就算使用瀏覽器的隱私窗口模式,也無法避免。

這是一個被動的識別方式。也就是說,理論上你訪問了某一個網站,那麼這個網站就能識別到你,雖然不知道你是誰,但你有一個唯一的指紋,將來無論是廣告投放、精準推送、安全防範,還是其他一些關於隱私的事情,都非常方便。

瀏覽器指紋的技術點與分類

更多關於高級指紋的細節和原理,可以通過探討瀏覽器指紋 [13] 這篇文章進行了解。

BrowserLeaks

長期以來,人們一直認爲 IP 地址和 Cookie 是用於在線跟蹤人員的唯一可靠數字指紋。但過了一段時間,當現代網絡技術允許感興趣的組織在他們不知情且無法避免的情況下使用新方法來識別和跟蹤用戶時,事情就失控了。

BrowserLeaks[14] 就是關於瀏覽隱私和網絡瀏覽器指紋的。在這裏,你將找到一個 Web 技術安全測試工具庫,這些工具將向你展示哪些類型的個人身份數據可能會被泄露,以及如何保護自己免受此類泄露。這個網站提供了包括 IP 地址、地理位置、Canvas、WebGL、WebRTC、字體等多種類型指紋的查看及其基本原理概述。

fingerPrint

如果你對其中的技術原理很感興趣,可以進入 BrowserLeaks[15],點擊對應卡片標題進行查看和了解,比如 HTML5 Canvas Fingerprinting[16] 頁面,會給出你的 Canvas 指紋及其唯一性率等信息。

fingerPrintCanvas

Nothing Private 的識別原理

前面的章節「瀏覽器隱身模式真的可以隱身嗎?」中介紹了 Nothing Private[17] 這個站點的測試結果,我們也看到,在提交信息和校驗的時候,請求會攜帶一個finger字段,這個字段就可以被認爲是 “瀏覽器指紋”。

查看 GitHub 上 Nothing Private 的源碼 [18] 可以發現,Nothing Private 實現 “瀏覽器指紋” 的核心邏輯如下:

fingerprint1

顯而易見,Nothing Private 使用 ClientJS[19](用純 JavaScript 編寫的設備信息和數字指紋)的瀏覽器指紋識別功能來獲取你的 Web 瀏覽器的指紋,核心方法在於getFingerprint。當你提交表單時,此指紋與你填寫的標識一起保存在使用 PHP 作爲後端的 MySQL 數據庫中。下次你訪問該網站時,你的瀏覽器指紋將與數據庫中的列匹配,並返回你填寫的標識。

ClientJS 當前用於生成指紋的數據點包括:

user agent, screen print, color depth, current resolution, available resolution, device XDPI, device YDPI, plugin list,
font list, local storage, session storage, timezone, language, system language, cookies, canvas print
複製代碼

我們還是瀏覽一下 ClientJS 的 getFingerprint 基本邏輯 [20]:

fingerprint2

我們發現,getFingerprint會獲取 UA、cookie、本地存儲、canvas 指紋等信息,再經過Murmur Hash 算法加密,最終返回一個可以唯一標識瀏覽器設備的 “瀏覽器指紋”。

MurmurHash 是一種非加密型哈希函數,適用於一般的哈希檢索操作。由 Austin Appleby 在 2008 年發明, 並出現了多個變種,都已經發布到了公有領域 (public domain)。與其它流行的哈希函數相比,對於規律性較強的 key,MurmurHash 的隨機分佈特徵表現更良好。

ClientJS 官網地址 [21]

FingerprintJS

FingerprintJS 是一個快速的瀏覽器指紋庫,純 JavaScript 實現,沒有任何依賴。默認情況下,使用 Murmur Hash 算法返回一個 32 位整數,Hash 函數可以很容易地更換。同時,他也很輕量:開啓 gzipped 後只有 843 bytes,匿名識別網絡瀏覽器的準確率高達 94%

FingerprintJS 的使用也比較簡單:

import FingerprintJS from '@fingerprintjs/fingerprintjs';

// 應用啓動時初始化:Initialize an agent at application startup.
const fpPromise = FingerprintJS.load();

(async () ={
  // Get the visitor identifier when you need it.
  const fp = await fpPromise;
  const result = await fp.get();

  // This is the visitor identifier:
  const visitorId = result.visitorId;
  console.log(visitorId);
})();
複製代碼

更多關於 fingerprintJS 的信息,可以參考:

上面這些方法,能獲得九成以上意義的唯一瀏覽器指紋,也許並不能完全真的唯一,因爲比如重寫相關 canvas 方法、使用類似貓頭鷹瀏覽器 [25] 等特殊瀏覽器還是會使得相關方法失效,但是技術手段更多時候只是一個通用意義上的解決方案,增加破解的壁壘和成本,我認爲支持常用場景下的開發是足夠的了。

有了唯一的瀏覽器指紋,我們就可以在類似統計 UV、點贊、投票的時候,帶上相關指紋,自然就可以在極大程度上辨別用戶是否存在刷票、刷訪問量的行爲了,不過,瀏覽器指紋技術終歸是把雙刃劍,在解決以上問題的同時,難免會給用戶帶來更多的信息泄漏困擾。

實現 Canvas Fingerprinting

**Canvas Fingerprinting(Canvas 指紋)基於 Canvas 繪製特定內容的圖片,使用 canvas.toDataURL()方法返回該圖片內容的 base64 編碼字符串。對於 PNG 文件格式,以塊 (chunk) 劃分,最後一塊是一段 32 位的 CRC 校驗,提取這段 CRC 校驗碼便可以用於用戶的唯一標識。**Canvas 利用 HTML5 canvas API 和 JavaScript 來動態生成你想要的圖像。和其它跟蹤技術一樣,這種方法已被成千上萬的網站採用了,包括我們熟知的廣告領域。

下面是 Canvas 指紋的一個簡單實現,原理其實比較簡單,不理解的地方可以參考註釋:

// PHP 中,bin2hex() 函數把 ASCII 字符的字符串轉換爲十六進制值。字符串可通過使用 pack() 函數再轉換回去
// 下面是PHP 的 bin2hex 的 JavaScript 實現
function bin2hex(s) {
  let n,
    o = '';
  s += '';
  for (let i = 0, l = s.length; i < l; i++) {
    n = s.charCodeAt(i).toString(16);
    o += n.length < 2 ? '0' + n : n;
  }

  return o;
}

// 獲取指紋UUID
function getUUID(domain) {
  // 創建 <canvas> 元素
  let canvas = document.createElement('canvas');
  // getContext() 方法可返回一個對象,該對象提供了用於在畫布上繪圖的方法和屬性
  let ctx = canvas.getContext('2d');
  // 設置在繪製文本時使用的當前文本基線
  ctx.textBaseline = 'top';
  // 設置文本內容的當前字體屬性
  ctx.font = "14px 'Arial'";
  // 設置用於填充繪畫的顏色、漸變或模式
  ctx.fillStyle = '#f60';
  // 繪製"被填充"的矩形
  ctx.fillRect(125, 1, 62, 20);
  ctx.fillStyle = '#069';
  // 在畫布上繪製"被填充的"文本
  ctx.fillText(domain, 2, 15);
  ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
  ctx.fillText(domain, 4, 17);

  // toDataURL返回一個包含圖片展示的 data URI
  let b64 = canvas.toDataURL().replace('data:image/png;base64,''');
  // atob() 方法用於解碼使用 base-64 編碼的字符串;base-64 編碼使用方法是 btoa(),這倆都是window全局方法
  let crc = bin2hex(atob(b64).slice(-16, -12));
  return crc;
}

// 調用時,你可以傳入任何你想傳的字符串,並不侷限於傳遞domain,這裏只是爲了便於區分站點
console.log(getUUID('https://www.baidu.com/'));
複製代碼

PHP bin2hex() 函數 [26]

測試結果表明,同一瀏覽器訪問該域時生成的 CRC 校驗碼總是不變。可以簡單理解爲同樣的 HTML Canvas 元素繪製操作,在不同的操作系統不同的瀏覽器上,產生的圖片內容其實是不完全相同的。出現這種情況可能是有幾個原因:

如何更好的保護個人隱私

我們應該在何時使用私密 / 隱身模式?

隱身模式就是能夠在多人共用電腦的時候保護自己的瀏覽記錄不被其他公用的人看到,以及保護自己的賬戶不被惡意登錄。此外隱私模式還能保護我們不被惡意廣告所困擾。

如何防止被生成 “瀏覽器指紋”?

上一大節我們探討了網站如何使用各種技術來生成 “瀏覽器指紋” 來標識唯一用戶,那麼下面我們來說說,如何避免被網站 “生成” 唯一用戶指紋。

常用的手段是,通過瀏覽器的擴展插件,阻止網站獲取各種信息,或者返回個假的數據,這種方式是在網頁加載前就執行一段 JS 代碼,更改、重寫、HOOK 了 js 的各個函數來實現的,因爲 JS 的靈活性給這種方式提供了可能。但是這種方式始終是表層的,使用 JS 修改是能防止大部分網站生成唯一指紋,但是是有手段可以檢測出來是否 “作弊” 的。

更好的手段是從瀏覽器底層做處理,從瀏覽器底層修改 API 使得這些在 js 層獲取的信息並不唯一,不管如何組合都不能生成一個唯一的代表用戶的指紋。比如:貓頭鷹瀏覽器 [27]。

貓頭鷹瀏覽器是基於 chromium 代碼修改編譯的瀏覽器,從底層對各種 API 做了修改,可以交給用戶自定義返回各種數據,比如 Canvas、Webgl、AudioContext、WebRTC、字體、UserAgent、屏幕分辨率、CPU 核心數、內存大小、插件信息、語言等信息,這樣就可以完全避免被 “生成” 唯一用戶指紋了。因爲在線公司、廣告商和開發人員喜歡跟蹤你的在線活動和操作,以便爲你提供有針對性的廣告,通常,大家認爲這是侵犯用戶隱私的。

如何免受廣告跟蹤器的監視和跟蹤

禁用第三方 Cookie。Chrome 2020 年推了一個叫做 SameSite Cookie 的東西,目的是爲了減少第三方 Cookie 的發送,但網站所有者仍然有能力關掉它(SameSite=None),可參考下圖。而 Chrome 的終極目標,是要在 2022 年完全消滅第三方 Cookie,像 Safari 和 Brave 已經做的那樣,SameSite Cookie 就是第一步。

禁用 JavaScript 腳本,蒽,這個在現今,估計還是算了。在現在前後端分離的開發模式下,大多數網站在禁用 JavaScript 後,將什麼也沒有,得,煩惱沒有了,網站內容也沒有了,一了百了~

要隱藏你的互聯網流量以免受監控和跟蹤,你可以使用虛擬專用網絡 (VPN)。你的 ISP 會知道你正在使用 VPN,但它無法確定你正在訪問哪些網站。VPN 服務通過遠程服務器路由流量,因此看起來你是從另一個位置或多個位置進行瀏覽。不過,VPN 提供商可以跟蹤你上網的位置,因此最好找一家你可以信任的公司來刪除或鎖定你的瀏覽活動。VPN 不會阻止來自廣告商的第三方 cookie,但這些 cookie 將無法準確識別你的位置,從而使廣告跟蹤器難以或不可能有效。

友情提示:VPN 是中立性的技術,使用由相關單位構建並且登記備案的 VPN 不屬於違法行爲,而私自搭建的則屬於違法行爲(即使用非法 VPN 是違法的);如果只是使用 VPN 連接國際網絡進行必要的工作、查閱必要信息,是不屬於違法行爲的;如果使用 VPN 在國際互聯網製作、複製、查閱和傳播違法信息的,則需要依法追究違法責任。

Tor 瀏覽器可以真正掩蓋你的在線活動。TorBrowser 是一款匿名訪問網絡的的軟件,用戶通過 Tor 可以在因特網上進行匿名交流。爲了實現匿名目的,Tor 把分散在全球的計算機連起來形成一個加密迴路。當你通過 Tor 網絡訪問互聯網時,你的網絡數據會通過多臺電腦迂迴發送,就像洋蔥包裹其核心那樣掩飾你的網絡活動,使得跟蹤流量變得困難,你訪問的網站真的不知道你在哪裏,只知道你的請求路由通過的最後一個服務器的大致位置;信息傳輸在每一步都被加密,無從得知你所處位置和信息傳輸目的地。因此 Tor Browser 也被稱爲洋蔥瀏覽器,Tor 瀏覽器在關閉時會刪除所有 cookie,但是即使 Tor 代理也不會阻止第三方廣告商在你的瀏覽器中注入 cookie。

本文爲公衆號【前端巔峯】

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/sbKej3IOF43wFfuCHKVOxg