原文鏈接:http://www.brokenbrowser.com/workers-sop-bypass-importscripts-and-basehref/
原文標題:Workers SOP Bypass importScripts and baseHref
原作者:@magicmac2000
譯:Holic (知道創宇404安全實驗室)
前言
關于HTML web worker的科普:
web worker 是運行在后臺的 JavaScript,不會影響頁面的性能。 當在 HTML 頁面中執行腳本時,頁面的狀態是不可響應的,直到腳本已完成。
worker線程中的代碼具有獨立的執行環境,有興趣的同學可以去看相關文檔。
正文
正如所知,所有的瀏覽器在試圖訪問不同源上的資源時會加強一些限制。當然我們可以播放或渲染來自不同域的音樂和圖像,然而由于存在同源策略,我們并不能夠讀取這些資源的具體內容。比如我們可以在canvas上繪制一幅圖像,但不能使用 getImageData 方法讀取到它的具體像素信息,除非該被加載的資源和加載主體是在相同的域下的。
該規則同樣適用于腳本。我們可以隨意加載外部不同域下的腳本,但是如果那些腳本存在錯誤,我們不能獲取到任何有關的細節,因為錯誤本身可能會泄漏信息。換句話說,瀏覽器不惜一切代價防止資源的信息泄漏問題,即使采用禁止顯示錯誤細節的方法。
假設我們在 cracking.com.ar 上渲染了來自 brokenbrowser.com 上的腳本,如下所示:
---- Main page on cracking.com.ar ----
<script src="http://brokenbrowser.com/errorscript.js"></script>
---- Script errorscript.js hosted in brokenbrower.com ----
this_is_an_error();
瀏覽器在執行一個不存在的函數“this_is_an_error()"的時候會拋出一個異常,然而這個腳本是來自不同的源,主線程中不會顯示任何相關的細節信息。實際上主頁僅僅獲取到簡單的"Script error"信息,省略了通常會附帶著的重要錯誤信息:錯誤描述,URL和行號等。主頁獲取到的僅僅是錯誤存在這一簡單信息而已。
瀏覽器這一行為是正確的,在加載可能泄露重要信息的站點的腳本或者其他文件時(比如ID,搜索記錄等)保護了終端用戶。
Script requested from a different origin:
Description: Script error
URL:
Line: 0
另一方面,如果我們把errorscript.js放在和主頁相同的域下,我們會開心地看到更多的信息。注意下述不同之處:
Script requested from the same origin:
Description: 'this_is_an_error' is undefined
URL: http://www.cracking.com.ar/errorscript.js
Line: 1
如果想了解更多關于同源策略(SOP)的工作原理,參考該鏈接
。但出于研究漏洞的目的,我們對這一小部分比較感興趣:

既然我們在相同的正常頁面下,那就通過Worker繞過限制吧。
通常情況下,我們不能再不同的域下面創建worker。實際上一系列嘗試都會惹怒瀏覽器,然后馬上拋出安全錯誤問題。那我們就試著在 cracking.com.ar 上創建一個 bing.com 的Worker,看看將會發生什么。

看到了什么?我們甚至沒法創建Worker!
如果改變我們自己的 document.baseURI,在創建Worker之前使它指向 bing.com 的話,將會發生什么呢?

Wow! 看來我們的幸運日到了?非也。如果我們在歷史記錄,地址和base object上面做點手腳,我們會看到很多有意思的東西。運氣不是必要因素,只要堅持不懈就會有所收獲,但其間也會產生許多意想不到的波折,要做好心理準備。( We don’t need luck but just persistence shaking these objects and tons of fruit will fall (watch your head!).)。無論如何,我們趕快構造PoC,看看是不是能從bing.com 獲取到泄漏信息。
var base = document.createElement("base");
base.href = "http://www.bing.com";
document.head.appendChild(base);
var worker = new Worker('http://www.bing.com/sa/8_1_2_5126428/HpbHeaderPopup.js');
worker.onerror = function(err)
{
alert("URL: "+ err.filename +
"\n\nLine: " + err.lineno +
"\n\nError: " + err.message);
}

Oh,我知道你現在在想些什么,bug獵手。你一定在想”僅僅泄漏成員的名稱“不算什么大事,對嗎?但這并不太對,因為很多站點是根據用戶返回內容的,而且如果我們能泄漏足夠多的數據,我們最終可能猜到關于她的成噸信息。另外,如果我們找到這個源下讀取內容的js文件(像XMLHttpRequest),我們最后可以隨意使用它并且獲取更多的材料。在任何情況下,泄漏的”undefined sj_ic“錯誤信息對我們來說是不夠的,我們想要更多的信息。太棒了!
下面我們來試一下其他繞過這個錯誤的方法。這是我們不能改變baseURI,但是可以大膽地使用Worker內的importScripts 方法。這時導入的腳本會在我們的上下文(源)執行,錯誤信息依然會泄漏,但是我們將能夠創建函數或者變量來在讓 bing 的腳本跑的更遠一點。
例如,在導入腳本之前,我們先創建一個類似能夠泄漏 “sj_ic” 錯誤信息的函數。換句話說,由于 ”sj_ic“ 沒有定義,bing 再也不會拋出這個錯誤。作為獎勵,我們會通過主線程獲取到的參數,允許我們通過這個函數獲取到一點更多的自由信息,可是先別興奮(一顆賽艇),這是在我們的上下文源上運行的。另言之,實際上我們能讀取那個函數的參數并不是個安全bug,錯誤信息的泄漏才是漏洞所在。
// Main
var worker = new Worker('workerimporterror.js');
worker.onmessage = function(event)
{
alert("Text coming from Worker on bing.com:\n\n" + event.data);
}
worker.onerror = function(err)
{
alert("URL: "+ err.filename +
"\n\nLine: " + err.lineno +
"\n\nError: " + err.message);
}
//---- workerimporterror.js ----
function sj_ic(n)
{
self.postMessage(n);
}
importScripts("http://www.bing.com/sa/8_1_2_5126428/HpbHeaderPopup.js");
我們的sj_ic函數被外部腳本調用,通過self.postMessage我們在主線程獲取到了相關數據。

然后便是新泄漏的錯誤信息。”新“是因為現在我們創建了一個叫”sj_ic“的函數,就看不到之前的錯誤信息了。正如所見,錯誤信息現在是”_H is undefined“

當然攻擊者會持續提供外部腳本,直到她獲取到了想要的信息。但我們只是個娛樂的 bug-hunter,點到為止。?
譯者注
參考后面的測試鏈接可以發現,Masato Kinugawa的測試鏈接中,postMessage使用了arguments.callee.caller作為參數,在Edge瀏覽器上可以通過arguments.callee.caller獲取到全文如下(測試版本Edge 25) 。
原作者:

Masato Kinugawa提供的:

參考測試鏈接
在 Edge/IE 上測試成功
來自@Masato Kinugawa的測試鏈接:
https://vulnerabledoma.in/edge_workerleak/

本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/57/
暫無評論