從 0 開始入門 Chrome Ext 安全(一) -- 瞭解一個 Chrome Ext

酷酷的曉得哥發表於2019-11-26

作者:LoRexxar'@知道創宇404實驗室
時間:2019年11月21日

原文:

在2019年初,微軟正式選擇了Chromium作為預設瀏覽器,並放棄edge的發展。並在19年4月8日,Edge正式放出了基於Chromium開發的Edge Dev瀏覽器,並提供了相容Chrome Ext的配套外掛管理。再加上國內的大小國產瀏覽器大多都是基於Chromium開發的,Chrome的外掛體系越來越影響著廣大的人群。

在這種背景下,Chrome Ext的安全問題也應該受到應有的關注,《從0開始入門Chrome Ext安全》就會從最基礎的外掛開發開始,逐步研究外掛本身的惡意安全問題,惡意網頁如何利用外掛漏洞攻擊瀏覽器等各種視角下的安全問題。

第一部分我們就主要來聊聊關於Chrome Ext的一些基礎。

獲取一個外掛的程式碼

Chrome Ext的存在模式類似於在瀏覽器層新加了一層直譯器,在我們訪問網頁的時候,外掛會載入相應的html、js、css,並解釋執行。

所以Chrome Ext的程式碼也就是html、js、css這類,那我們如何獲取外掛的程式碼呢?

當我們訪問擴充套件程式的頁面可以獲得相應的外掛id

然後我們可以在 中下載相應的crx包。

把crx改名成zip之後解壓縮就可以了

manifest.json

在外掛的程式碼中,有一個重要的檔案是manifest.json,在manifest.json中包含了整個外掛的各種配置,在配置檔案中,我們可以找到一個外掛最重要的部分。

首先是比較重要的幾個欄位

  • browser_action
    • 這個欄位主要負責擴充套件圖示點選後的彈出內容,一般為popup.html
  • content_scripts
    • matches 代表scripts插入的時機,預設為document_idle,代表頁面空閒時
    • js 代表插入的scripts檔案路徑
    • run_at 定義了哪些頁面需要插入scripts
  • permissions
    • 這個欄位定義了外掛的許可權,其中包括從瀏覽器tab、歷史紀錄、cookie、頁面資料等多個維度的許可權定義
  • content_security_policy
    • 這個欄位定義了外掛頁面的CSP
    • 但這個欄位不影響content_scripts裡的指令碼
  • background
    • 這個欄位定義外掛的後臺頁面,這個頁面在預設設定下是在後臺持續執行的,只隨瀏覽器的開啟和關閉
    • persistent 定義了後臺頁面對應的路徑
    • page 定義了後臺的html頁面
    • scripts 當值為false時,background的頁面不會在後臺一直執行

在開始Chrome外掛的研究之前,除了manifest.json的配置以外,我們還需要了解一下圍繞chrome建立的外掛結構。

Chrome Ext的主要展現方式

browserAction - 瀏覽器右上角

瀏覽器的右上角點選觸發的就是mainfest.json中的 browser_action

 "browser_action": {
      "default_icon": "img/header.jpg",
      "default_title": "LoRexxar Tools",
      "default_popup": "popup.html"
    },

其中頁面內容來自popup.html

pageAction

pageAction和browserAction類似,只不過其中的區別是,pageAction是在滿足一定的條件下才會觸發的外掛,在不觸發的情況下會始終保持灰色。

contextMenus 右鍵選單

透過在chrome中呼叫chrome.contextMenus這個API,我們可以定義在瀏覽器中的右鍵選單。

當然,要控制這個api首先你必須申請控制contextMenus的許可權。

{"permissions": ["contextMenus"]}

一般來說,這個api會在background中被定義,因為background會一直在後臺載入。

chrome.contextMenus.create({
    title: "測試右鍵選單",
    onclick: function(){alert('您點選了右鍵選單!');}});

https://developer.chrome.com/extensions/contextMenus

override - 覆蓋頁面

chrome提供了override用來覆蓋chrome的一些特定頁面。其中包括歷史記錄、新標籤頁、書籤等...

"chrome_url_overrides":
{
    "newtab": "newtab.html",
    "history": "history.html",
    "bookmarks": "bookmarks.html"
}

比如Toby for Chrome就是一個覆蓋新標籤頁的外掛

devtools - 開發者工具

chrome允許外掛重構開發者工具,並且相應的操作。

外掛中關於devtools的生命週期和F12開啟的視窗時一致的,當F12關閉時,外掛也會自動結束。

而在devtools頁面中,外掛有權訪問一組特殊的API,這組API只有devtools頁面中可以訪問。

chrome.devtools.panels:皮膚相關;
chrome.devtools.inspectedWindow:獲取被審查視窗的有關資訊;
chrome.devtools.network:獲取有關網路請求的資訊;
{
    // 只能指向一個HTML檔案,不能是JS檔案
    "devtools_page": "devtools.html"
}

https://developer.chrome.com/extensions/devtools

option - 選項

option代表著外掛的設定頁面,當選中圖示之後右鍵選項可以進入這個頁面。

{
    "options_ui":
    {
        "page": "options.html",
        "chrome_style": true
    },
}

omnibox - 搜尋建議

在chrome中,如果你在位址列輸入非url時,會將內容自動傳到google搜尋上。

omnibox就是提供了對於這個功能的魔改,我們可以透過設定關鍵字觸發外掛,然後就可以在外掛的幫助下完成搜尋了。

{
    // 向位址列註冊一個關鍵字以提供搜尋建議,只能設定一個關鍵字
    "omnibox": { "keyword" : "go" },
}

這個功能透過 chrome.omnibox這個api來定義。

notifications - 提醒

notifications代表右下角彈出的提示框

chrome.notifications.create(null, {
    type: 'basic',
    iconUrl: 'img/header.jpg',
    title: 'test',
    message: 'i found you!'
});

許可權體系和api

在瞭解了各型別的外掛的形式之後,還有一個比較重要的就是Chrome外掛相關的許可權體系和api。

Chrome發展到這個時代,其相關的許可權體系劃分已經算是非常細緻了,具體的細節可以翻閱文件。

https://developer.chrome.com/extensions/declare_permissions

拋開Chrome外掛的多種表現形式不談,外掛的功能主要集中在js的程式碼裡,而js的部分主要可以劃分為5種injected script、content-script、popup js、background js和devtools js.

  • injected script 是直接插入到頁面中的js,和普通的js一致,不能訪問任何擴充套件API.
  • content-script 只能訪問extension、runtime等幾個有限的API,也可以訪問dom.
  • popup js 可以訪問大部分API,除了devtools,支援跨域訪問
  • background js 可以訪問大部分API,除了devtools,支援跨域訪問
  • devtools js 只能訪問devtools、extension、runtime等部分API,可以訪問dom
JS 是否能訪問DOM 是否能訪問JS 是否可以跨域
injected script 可以訪問 可以訪問 不可以
content script 可以訪問 不可以 不可以
popup js 不可直接訪問 不可以 可以
background js 不可直接訪問 不可以 可以
devtools js 可以訪問 可以訪問 不可以

同樣的,針對這多種js,我們也需要特殊的方式進行除錯

  • injected script: 直接F12就可以除錯
  • content-script:在F12中console選擇相應的域

  • popup js: 在外掛右鍵的列表中有審查彈出內容
  • background js: 需要在外掛管理頁面點選背景頁然後除錯

通訊方式

在前面介紹過各類js之後,我們提到一個重要的問題就是,在大部分的js中,都沒有給與訪問js的許可權,包括其中比較關鍵的content script.

那麼外掛怎麼和瀏覽器前臺以及相互之間進行通訊呢?

- injected-script content-script popup-js background-js
injected-script - window.postMessage - -
content-script window.postMessage - chrome.runtime.sendMessage chrome.runtime.connect chrome.runtime.sendMessage chrome.runtime.connect
popup-js - chrome.tabs.sendMessage chrome.tabs.connect - chrome.extension. getBackgroundPage()
background-js - chrome.tabs.sendMessage chrome.tabs.connect chrome.extension.getViews -
devtools-js chrome.devtools.inspectedWindow.eval - chrome.runtime.sendMessage chrome.runtime.sendMessage

popup 和 background

popup和background兩個域互相直接可以呼叫js並且訪問頁面的dom。

popup可以直接用 chrome.extension.getBackgroundPage()獲取background頁面的物件,而background可以直接用 chrome.extension.getViews({type:'popup'})獲取popup頁面的物件。

// background.jsfunction test(){
    alert('test');}// popup.jsvar bg = chrome.extension.getBackgroundPage();bg.test(); // 訪問bg的函式alert(bg.document.body.innerHTML); // 訪問bg的DOM

popup\background 和 content js

popup\background 和 content js之間溝通的方式主要依賴 chrome.tabs.sendMessagechrome.runtime.onMessage.addListener這種有關事件監聽的交流方式。

傳送方使用 chrome.tabs.sendMessage,接收方使用 chrome.runtime.onMessage.addListener監聽事件。

chrome.runtime.sendMessage({greeting: '傳送方!'}, function(response) {
    console.log('接受:' + response);
});

接收方

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse)
{
    console.log(request, sender, sendResponse);
    sendResponse('回覆:' + JSON.stringify(request));
});

injected script 和 content-script

由於injected script就相當於頁面內執行的js,所以它沒許可權訪問chrome物件,所以他們直接的溝通方式主要是利用 window.postMessage或者透過DOM事件來實現。

injected-script中:

window.postMessage({"test": 'test!'}, '*');

content script中:

window.addEventListener("message", function(e)
{
    console.log(e.data);
}, false);

popup\background 動態注入js

popup\background沒辦法直接訪問頁面DOM,但是可以透過 chrome.tabs.executeScript來執行指令碼,從而實現對頁面DOM的操作。

要注意這種操作要求必須有頁面許可權

 "permissions": [
        "tabs", "http://*/*", "https://*/*"
    ],

js

// 動態執行JS程式碼chrome.tabs.executeScript(tabId, {code: 'document.body.style.backgroundColor="red"'});// 動態執行JS檔案chrome.tabs.executeScript(tabId, {file: 'some-script.js'});

chrome.storage

chrome 外掛還有專門的儲存位置,其中包括chrome.storage和chrome.storage.sync兩種,其中的區別是:

  • chrome.storage 針對外掛全域性,在外掛各個位置儲存的資料都會同步。
  • chrome.storage.sync 根據賬戶自動同步,不同的電腦登陸同一個賬戶都會同步。

外掛想訪問這個api需要提前宣告storage許可權。

總結

這篇文章主要描述了關於Chrome ext外掛相關的許多入門知識,在談及Chrome ext的安全問題之前,我們可能需要先了解一些關於Chrome ext開發的問題。

在下一篇文章中,我們將會圍繞Chrome ext多個維度的安全問題進行探討,在現代瀏覽器體系中,Chrome ext到底可能會帶來什麼樣的安全問題。

re

本文由 Seebug Paper 釋出,如需轉載請註明來源。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69912109/viewspace-2665729/,如需轉載,請註明出處,否則將追究法律責任。

相關文章