原來瀏覽器插件有這么多風險?
嫦美找到我時,整個人是崩潰的 —— “卡頌,我好像被監(jiān)視了”。
傍晚的星巴克,她的影子被吊燈拉得很長,顫抖著如同她此刻的內心。
“怎么回事?”我盡量讓聲音聽起來平靜些。
“最近認識個男生,是我MBA同學,對我很熱情,也很懂我”嫦美環(huán)顧四周,仿佛隨時會有什么東西從夜色中跳出來。
“緣分啊,這不很好嘛?”我笑著說。
“不是那種心有靈犀的懂,是那種「生活起居都被監(jiān)視的懂」”嫦美解釋道。不待我回應,又補充道:“這次約你出來,也是想讓你幫忙看看我電腦有沒有被植入啥監(jiān)聽木馬”。
說罷,從背包里取出MacBook Air遞給我。
“Mac一般安全性都蠻高的,你最近沒裝啥來路不明的應用吧?”一邊擺弄她的電腦,我一邊問道。
“我也不會裝應用,平時主要就上上網、刷刷劇”。
瀏覽完她的應用列表,我順手打開了瀏覽器,又習慣性打開插件列表。
這時,一個瀏覽器插件吸引了我的注意:
“這是啥?”
“奧,我們MBA的網課需要在這個平臺看。這個平臺很嚴,看課不能快進,也不能切換到其他頁面。這是那個男同學發(fā)我的,裝了后就能突破這些限制,還挺方便”說罷,嫦美皺了皺眉“和這個插件不會有關系吧?”
“不好說,等我看看插件源碼”。
事實證明,這個插件真的有問題......
本文參考文章Let's build a Chrome extension that steals everything[1]
瀏覽器插件能做什么?
瀏覽器插件為我們上網提供了極大便利,比如:
- GPT插件能幫我們一鍵總結網頁內容
- 翻譯插件能實時翻譯網頁內容
- 去廣告插件能去掉網頁牛皮癬,還我們清爽的頁面
實際上,瀏覽器插件除了能「分析并修改原始頁面」外,還能:
- 獲取我們的實時位置
- 讀取、修改我們復制粘貼的內容
- 讀取cookie、瀏覽歷史
- 屏幕截圖
- 記錄鍵盤輸入
- 等等
可以說,有心人只要利用得當,就能通過瀏覽器插件獲得我們上網的所有足跡。
這時,有人會說:“插件能做這些沒錯,但必須申請必要的權限,我不給他權限不就行了?”
事實真的這么簡單么?
安全約束夠么?
《Building Browser Extensions》一書作者「Matt Frisbie」為了演示瀏覽器插件的潛在安全問題,構造了一個「會申請全部49項權限」的chrome瀏覽器插件spy-extension[2]。
當你在瀏覽器安裝這個插件后,瀏覽器確實會提示你「插件申請的權限」:
不過,等等!明明申請了49項權限,這里為什么只顯示5項?原來,窗口顯示的內容行數有限,超出部分需要拖動滾動條才會顯示。
可是,又有幾個用戶會發(fā)現「在申請的5項權限下面,滾動條后面還隱藏了44項權限呢」?
一旦有了權限,想做什么就取決于插件作者的想象力了。可以被用來做壞事的WebExtensions API非常多,比如:
Service Worker
后臺運行的Service Worker可以監(jiān)聽發(fā)出的網絡請求,并在請求發(fā)送到網絡之前修改它們。
這意味著插件可以使用Service Worker發(fā)送數據到服務器,或者在用戶瀏覽網頁時攔截請求并發(fā)送額外的數據。
由于Service Worker運行于一個獨立的后臺進程中,所以打開調試工具的Network面板看不到插件發(fā)出的請求:
都有哪些有價值的數據可以收集呢?
用戶敏感數據
最簡單的,監(jiān)聽用戶鍵盤輸入:
[...document.querySelectorAll("input,textarea,[contenteditable]")].map((input) =>
input.addEventListener("input", _.debounce((e) => {
// 處理 用戶輸入
}, 1000))
);
除此之外:
- chrome.cookies.getAll({})會以數組的形式返回瀏覽器的所有cookie
- chrome.history.search({ text: "" })會以數組形式返回用戶的整個瀏覽歷史記錄
- chrome.tabs.captureVisibleTab()會靜默將用戶當前正在查看的頁面截圖,并以data URL的形式返回。
- chrome.webRequest可以讓插件監(jiān)控所有Tab的流量
上述API結合Service Worker傳輸數據,用戶在插件作者面前無異于裸奔。
更高階的玩法
據嫦美表示 —— 她那個MBA同學好像知道她住哪兒,這是怎么做到的呢?很有可能是通過「獲取地理位置」的插件功能。
一個網課插件獲取地理位置,這不是太奇怪了么?可是嫦美一點都沒發(fā)覺,這是怎么辦到的?
如果插件腳本獲取地理位置(通過navigator.permissions.query({ name: "geolocation" })),將詢問用戶授權。
但如果「被注入腳本的網站」已經獲得用戶的地理位置授權,插件不需要授權就能靜默使用對應功能。
舉個例子,如果百度地圖向你請求「獲取地理位置」的授權,這很合理,你也大概率會同意。
如果惡意插件可以向百度地圖注入腳本,當你訪問百度地圖時,他就不用再獲取授權就能訪問你的地理位置。
借尸還魂之法
以上所說的所有功能都局限在 —— 插件向已有網站注入腳本。那插件是否能不被察覺的直接打開惡意網站呢?
答案是 —— 可以,我愿稱其為「借尸還魂」之法。
很多朋友都會打開多個瀏覽器Tab,但常用的可能就是其中幾個,剩下的Tab會閑置很長時間。
而這些「閑置的Tab」就是最好的下手目標。
經常打開很多Tab
首先,插件通過以下代碼篩選出閑置的Tab:
const tabs = await chrome.tabs.query({
// 篩選用戶當前沒使用的Tab
active: false,
// 篩選用戶沒有pin的Tab,pin的Tab使用頻率通常比較高
pinned: false,
// 不使用有音頻的Tab
audible: false,
// 使用已經加載完畢的Tab
status: "complete",
});
// 篩選出閑置Tab
const [idleTab] = tabs.filter(/** ...省略其他篩選條件 **/)
只要惡意網站的標題、圖標(favicon)與閑置Tab一致,那么用惡意網站替換閑置Tab后,用戶也不會有任何察覺。
舉個例子,如果閑置Tab是React官網,那惡意網站只需要標題是React,圖標是React,即使閑置Tab跳轉到惡意網站,從Tab外觀上也無法區(qū)分。
下面的代碼構造了惡意網站的url,其中「與閑置Tab一致的標題、圖標」保存在url searchParams中:
// 將標題、圖標保存在searchParams中
const searchParams = new URLSearchParams({
returnUrl: idleTab.url,
faviconUrl: idleTab.favIconUrl || "",
title: idleTab.title || "",
});
const url = `${chrome.runtime.getURL(
"惡意網站.html"
)}?${searchParams.toString()}`;
惡意網站在url searchParams中取出標題、圖標數據,并替換:
// 修改標題
document.title = searchParams.get('title);
// 修改圖標
document.querySelector(`link[rel="icon"]`)
.setAttribute("href", searchParams.get('faviconUrl'));
最后,用惡意網站替換閑置Tab的網站:
await chrome.tabs.update(idleTab.id, {
url,
active: false,
});
惡意網站只需要在「做完壞事后」或「用戶重新點擊 閑置Tab 時」跳回原來的網站即可。代碼如下:
const searchParams = new URL(window.location.href).searchParams;
function useReturnUrl() {
// 跳回原來網站
window.location.href = searchParams.get('returnUrl');
}
if (document.visibilityState === "visible") {
useReturnUrl();
}
// 用戶訪問了閑置Tab
document.addEventListener("visibilitychange", () => useReturnUrl());
// ...開始做壞事
// 做完壞事,跳回原來網站
useReturnUrl();
從用戶的視角看,當他點擊閑置Tab時,網站重新加載。對于一個閑置的Tab來說,重新訪問時加載頁面是再正常不過的邏輯。
只是用戶不會知道,這并不是「網站重新加載」,而是「退回到前一個網站」。
后記
有人會說 —— 我只使用那些信得過的插件。
但今天信得過的插件,明天就一定信得過么?在暗網中,「用戶量大的免費瀏覽器插件」能賣不錯的價錢。
為什么會有人收購這類「沒有商業(yè)價值的免費插件」呢?一種可能是 —— 收購后向代碼中投毒,只要用戶升級插件就會中招。
所以,好用的插件不一定沒問題,今天沒問題的插件明天也不一定沒問題。
對于嫦美來說,技術上能做的只能是刪除插件、清除緩存、清除cookie,退出所有的賬號登錄并修改密碼。
但似乎更大的危險,來自現實世界......
參考資料
[1]Let's build a Chrome extension that steals everything:https://mattfrisbie.substack.com/p/spy-chrome-extension。
[2]spy-extension:https://github.com/classvsoftware/spy-extension。