從 0 開始入門 Chrome Ext 安全(一) -- 瞭解一個 Chrome Ext
作者: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.sendMessage
和
chrome.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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 從 0 開始入門 Chrome Ext 安全(番外篇) -- ZoomEye ToolsChromeOOM
- 從 0 開始瞭解 DockerDocker
- SpringBoot入門(一):從HelloWorld開始Spring Boot
- Chrome外掛開發入門Chrome
- 簡單瞭解EXT4檔案系統
- WebGL基礎(一): 從一個滑鼠畫點開始瞭解原生webGLWeb
- Chrome開發者工具Debug入門Chrome
- Chrome外掛入門Chrome
- 從0到70%:Chrome上位揭祕!Chrome
- Chrome外掛開發入門:如何實現一鍵上班賴皮Chrome
- 從0開始學習Webpack(一)Web
- Chrome開發者工具裡的一個隱藏技能:chrome://net-internalsChrome
- ext4 Ext.form.Panel 非ajax提交ORM
- # 編寫第一個Chrome ExtensionChrome
- [Ext JS] Sencha Cmd命令參考之一JS
- 從0開始弄一個面向OC資料庫(五)–多執行緒安全資料庫執行緒
- 【D3.js 入門系列一】從零開始繪製一個柱形圖JS
- Google Chrome除錯js入門GoChrome除錯JS
- 一文入門DNS?從訪問GitHub開始DNSGithub
- go語言如何入門?從一個簡單例子開始學起Go單例
- 一個 Chrome XSS Filter Bypass 的分析ChromeFilter
- 開發chrome外掛入門-天氣預報Chrome
- [譯] JavaScript 自動化爬蟲入門指北(Chrome + Puppeteer + Node JS):和 Headless Chrome 一起裝逼一起飛JavaScript爬蟲ChromeJS
- 從 0 開始手寫一個 Mybatis 框架,三步搞定!MyBatis框架
- 從 0 開始搭建一個技術部落格,私藏乾貨~
- 從0開始寫一個直播間的禮物系統
- 從0開始學VUE - 執行第一個VUE專案Vue
- 授予漁,從0開始搭建一個自己想要的網頁網頁
- 從零開始打造一個iOS圖片載入框架(一)iOS框架
- Chrome釋出最新版本,修復一個在野0dayChrome
- Ext.Date 方法
- AIX_EXT_VGAI
- 【轉】Ext JS xtypeJS
- Flutter 從一個demo開始Flutter
- webpack入門級 - 從0開始搭建單頁專案配置Web
- phaser3入門教程-從零開始開發一個打磚塊遊戲遊戲
- 從0開始用python寫一個命令列小遊戲(二)Python命令列遊戲
- 從0開始用python寫一個命令列小遊戲(十)Python命令列遊戲