原文連接:Bypassing anti-incognito detection in Google Chromehtml
瀏覽器的隱身窗口能夠幫助用戶避免 cookie 被竊取、防止被跟蹤記錄瀏覽行爲。這篇文章中的一些內容可能與其餘系列的瀏覽器類似或不一樣,但我只關注基於 Chromium 的瀏覽器,更具體地說是谷歌的 Chrome 瀏覽器。git
在 Chrome 74 以前,有一個漏洞,不少網站利用這個漏洞來檢測用戶是否在使用 Chrome 的隱身模式訪問網站。網站只需嘗試使用 FileSystem API,該 API 用於存儲臨時或持久文件。該 API 在隱身模式下被禁用,但在非隱身模式下存在,從而產生一個差別,能夠用來檢測用戶是否正在使用隱身模式瀏覽網站。web
在谷歌上隨便搜索一下無痕窗口,就會獲得不少結果,其中一個是 Stackoverflow 問題,被採納的回答是:chrome
var 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"));
}
複製代碼
谷歌在 Chrome 74 中推出了一個新選項(經過#enable- filesystemin -incognito標誌訪問),阻止了這種檢測。他們的解決方案是在隱身模式下使用 RAM 建立一個虛擬文件系統。該保護能夠屏蔽上述檢測方法,並在隨後的穩定版本中默認啓用。瀏覽器
結果代表,上面那種保護是不夠的,仍然有可能檢測到隱身模式,從而使目前的保護無效。最近,我在擺弄 Quota Management API
時另闢蹊徑,使得即便啓用了這種保護,也能夠檢測隱身模式。這個 API 管理分配給瀏覽器上的應用程序和網站的臨時和持久存儲的配額。使用如下摘自 Jeff Posnick 文章的代碼片斷,能夠查詢臨時存儲的配額:安全
if ('storage' in navigator && 'estimate' in navigator.storage) {
navigator.storage.estimate().then(({usage, quota}) => {
console.log(`Using ${usage} out of ${quota} bytes.`);
});
}
複製代碼
網站/應用程序有兩種可用的存儲方式,臨時存儲和持久存儲,臨時存儲能夠在不請求任何配額的狀況下使用,而且由瀏覽器上運行的全部網站共享。cookie
關於臨時存儲及其配額,我經過閱讀 Chromium 源代碼、文章和 bug 報告收集了一些有趣的觀點:(Ref1、Ref2、Ref3)網站
對於全部應用程序/網站,臨時存儲的默認配額是可用磁盤的 50%,該空間做爲全部應用程序/網站的共享池ui
應用程序/網站能夠經過調用 quota API 的 queryUsageAndQuota() 方法查詢它們的配額,而不須要任何權限google
隱身窗口的配額是設備內存
的一小部分(10%),上限爲 120MB
非隱身窗口的配額只是設備存儲
的一小部分
下表列出了不一樣磁盤大小設備的最小可用臨時存儲配額,該配額是根據瀏覽器試圖在設備中始終保持空閒時來計算的。
如上圖所示,隱身模式和非隱身模式的臨時存儲配額的關鍵不一樣之處在於,在隱身模式下,臨時存儲配額固定爲 120MB,而非隱身窗口則不是這樣。從上表能夠看出,在非隱身模式下,設備存儲小於2.4GB 時臨時存儲配額纔會小於 120MB。可是,就全部實際用途而言,能夠安全地假設當前使用的大多數設備都有超過 2.4GB 的存儲空間,即在非隱身模式下,臨時存儲配額必定大於 120MB。
利用這些信息,我想出了一個檢測隱身模式的簡單規則。若是臨時存儲配額 <= 120MB,那麼能夠確定這是一個隱身窗口。
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')
}
複製代碼
檢測出用戶使用隱身模式以後能夠作些什麼呢?歡迎評論...