本文的開始源於落地頁項目中遇到的 Chrome 控制檯 warn 提示,擔憂影響頁面渲染,特此弄個究竟。提示以下,javascript
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://www.example.com/example.html with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.
複製代碼
除非特殊說明,不然本文中的瀏覽器均指 Chrome Browser。html
本文將從如下幾個方面對 CORB 進行探討,java
CORB 是一種判斷是否要在跨站資源數據到達頁面以前阻斷其到達當前站點進程中的算法,下降了敏感數據暴露的風險。node
當請求發生 CORB 時,瀏覽器控制檯會打印以下警告內容,git
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://www.example.com/example.html with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details
複製代碼
在 chrome 66
或這個版本以前,提示信息有細微不一樣,程序員
Blocked current origin from receiving cross-site document at https://www.example.com/example.html with MIME type text/html
複製代碼
當請求的響應結果自己就出錯或爲空時,早期版本 Chrome 依舊會出現上述提示,但 Chrome 69 以後的版本再也不出現上述提示。下文實驗一和實驗二驗證了該描述。github
The response body is replaced with an empty body. // 響應數據置爲空
The response headers are removed. // 移除響應請求頭
複製代碼
CORB 啓動時,雖然響應結果會被置空,可是請求的服務仍然成功,`status: 200`。好比:使用 `img` 標籤上報頁面監控數據,儘管響應結果爲空,但請求依舊發送成功,服務器亦正常響應。下文實驗一已驗證。 web
簡單來講,就是出現了一些網絡安全漏洞,爲防止漏洞肆虐,便出現了站點隔離(Site Isolation),CORB 則是其中的一種實現策略。算法
當惡意代碼和正常站點存在於同一個進程時,惡意代碼即可以訪問進程內的內存,進行一系列訪問攻擊,此時,惡意代碼竊取數據的惟一難點在於不知道敏感數據的具體存儲位置,但經過 CPU 預執行 和 SCA 能夠一步步 試探 出來。詳細瞭解可參看: zhuanlan.zhihu.com/p/32784852chrome
if(condition)
do_sth();
複製代碼
CPU 執行速度大於內存讀取速度,爲了提高 CPU 使用率,在從內存中讀取 condition
完成以前,CPU 就已經開始執行下文內容。即無論 if
條件是否返回 true
,CPU 都會提早執行裏面的語句do_sth()
。 CPU 預執行是芯片製造者決定的,爲了提高 CPU 使用速度和效率而建的,預執行紅利不是輕易就能放棄的,所以,目前或短時間來看基本沒可能改變。
在某些狀況下,沒有實現 Site Isolution 的普通瀏覽器會出現一個進程裏面同時運行多個站點的代碼,這就讓惡意站點有隙可乘。好比惡意站點 a.dd.com
在本身的代碼中嵌入 <iframe src="https://v.qq.com" frameborder="0"></iframe>
,這時,普通瀏覽器就會把帶有惡意站點 a.dd.com
的惡意代碼 和 v.qq.com
放在同一個內存中運行。
簡單來講,就是利用程序運行時,系統產生的一些物理特徵(如:時延,能耗,電磁,錯誤消息,頻率等)進行推測型攻擊。看起來有點難以想象,但早在 1956 年,英國已經利用 SCA 獲取了埃及駐倫敦的加密機。
緩衝時延(Cache Timing)旁路是經過內存訪問時間的不一樣來產生的旁路。假設訪問一個變量,這個變量在內存中,這須要上百個時鐘週期才能完成,但若是變量訪問過一次,這個變量被加載到緩衝(Cache)中了,下次再訪問,可能幾個時鐘週期就能夠完成了,可根據這種訪問速度竊取特定數據。Spectre 和 Meltdown 漏洞即是利用了這種特性。
漏洞三大關鍵點是 CPU 預執行、SCA 和 共享進程。預防就得從這三個方面着手。先看 SCA,算法運行時間的變化本質就是源於數據處理,根據時間變化推測運算操做和數據存儲位置,所以 SCA 可預防性極低。再看 CPU 預執行,性能至少提升 10%,一片可觀的紅利,芯片廠商如何捨得放棄。如此,只能針對共享進程下手了,Site Isolation 即是剝離共享進程的一項技術,採用獨立站點獨立進程的方式實現,下降漏洞的威脅。
站點隔離保證了不一樣站點頁面始終被放入不一樣的進程,每一個進程運行在一個有限制的沙箱環境中,在該環境中可能會阻止進程接收其它站點返回的某些特殊類型敏感信息,惡意站點再也不和正常站點共享進程,這就讓惡意站點竊取其它站點的信息變得更加困難。從 Chrome 67 開始,已默認啓用 Site Isolation。
經驗證,Site Isolation
關於進程獨立的原則是 只要一級域名同樣,站點實例就共享一個進程,不管子域名是否同樣。若是使用 iframe 嵌入了一級域名不同的跨域站點,則會生成一個新的進程維護該跨域站點運行,這一點同前文介紹的普通瀏覽器共享進程不一樣。更詳細的內容參看 www.yaoyanhuo.com/blog/site_i…
在同源策略下,Site Isolation 已經很好地隔離了站點,只是還有跨域標籤這樣的東西存在,敏感數據依舊會暴露,依舊會進駐惡意站點內存空間。 有這樣一個場景,用戶登陸某站點 some.qq.com
後,又訪問了 bad.dd.com
惡意站點,惡意站點有以下代碼,<script src="some.qq.com/login">
,跨域請求了原站點的登陸請求,此時,普通瀏覽器會正常返回登陸後的敏感信息,且敏感信息會進駐 bad.dd.com
內存空間。好不容易站點隔離把各個站點信息分開了,這由於跨域又在一塊兒了。咋整?CORB 來了。CORB 會在敏感信息到達 web apge 以前,將其攔截掉,如此,敏感信息既不會暴露於瀏覽器,也不會進駐內存空間,獲得了很好的保護。
當跨域請求回來的數據 MIME type 同跨域標籤應有的 MIME 類型不匹配時,瀏覽器會啓動 CORB 保護數據不被泄漏,被保護的數據類型只有 html
xml
和 json
。很明顯 <script>
和 <img>
等跨域標籤應有的 MIME type 和 html
、xml
、json
不同。
MIME type 同 CORB 有着至關緊密的關係,能夠說 CORB 的產生直接依附 MIME 類型。所以,閱讀本文前,有必要先理解一下什麼是 MIME type。
MIME 是一個互聯網標準,擴展了電子郵件標準,使其能夠支持更多的消息類型。常見 MIME
類型如:text/html
text/plain
image/png
application/javascript
,用於標識返回消息屬於哪種文檔類型。寫法爲 type/subtype
。 在 HTTP 請求的響應頭中,以 Content-Type: application/javascript; charset=UTF-8
的形式出現,MIME type
是 Content-Type
值的一部分。以下圖,
內容嗅探技術是指 當響應頭沒有指明 MIME type
或 瀏覽器認爲指定類型有誤時,瀏覽器會對內容資源進行檢查並執行,來猜想內容的正確MIME
類型。嗅探技術的實現細節,不一樣的瀏覽器在不一樣的場景下有不一樣的方式,本文不作詳述。詳細內容參見:www.keycdn.com/support/wha…
MIME sniffing
呢?服務器在響應首部添加 X-Content-Type-Options: nosniff
,用來告訴瀏覽器必定要相信 Content-Type
中指定的 MIME
類型,不要再使用內容嗅探技術探測響應內容類型。該方法僅對 <script>
和 <style>
有效。
官方解釋:developer.mozilla.org/en-US/docs/…
這多是本文最須要關心的內容了,到底什麼狀況下會出現 CORB 。在知足跨域標籤(如:<script>
,<img>
)請求的響應內容的 MIME type
是 HTML MIME type
、 XML MIME type
、JSON MIME type
和 text/plain
時,如下三個條件任何一個知足,就享受 CORB 保護。(image/svg+xml
不在內,屬圖片類型)
X-Content-Type-Options: nosniff
206 Partial Content
(developer.mozilla.org/zh-CN/docs/…這種嗅探用於防止某些內容因被錯誤標記 MIME 類型 而被 CORB 阻斷不能正常響應返回,且該嗅探基於 Content-Type
進行,好比類型是 text/json
,便只會對內容進行 json 類型檢查,而不會進行 xml 或 html 的檢查。
HTML MIME type
、 XML MIME type
、JSON MIME type
的出現能理解,爲何 text/plain
類型也會在保護範圍內?由於 當 Content-Type
缺失的時候,響應內容 MIME type
有可能就是 text/plain
;且據可靠數據顯示, HTML, JSON, or XML 有時候也會被標記爲 text/palin
。如,
data.txt
{
"ret_code": 0,
"msg": "請求成功!",
"data": [1, 2, 3, 4, 5]
}
複製代碼
server.js
app.get('/file', function getState(req,res,next){
// res.type('json')
res.sendfile(`${__dirname}/public/data.txt`)
})
複製代碼
如上代碼,啓動 server.js ,Chrome 瀏覽器訪問 /file
時服務返回 data.txt
內容,儘管響應頭是 Content-Type: text/plain; charset=UTF-8
,響應內容依舊能被識別爲 json
。由此, text/plain
會做爲 json
的標記也是一種常見現象。若是跨域訪問 /file
就會出現 CORB,驗證結果以下圖,
不少時候 script
文件被會打上 html
xml
json
這些 MIME 類型,若是 Chrome 瀏覽器直接 block,將相應內容置空,當前域下的網站便會 由於缺乏 js 執行內容而不能正常運行。爲避免這種狀況出現,Chrome 瀏覽器在決定是否保護響應內容前,會先判斷 script 的響應內容是不是受保護的 MIME 類型(html
xml
json
)。若是檢測結果是,則啓動 CORB,若是沒法檢測會直接返回,不啓用 CORB。
對於跨域請求 js 資源,若是已經存在 nosniff 的狀況下,還把 js 資源設置成了其它類型(如:json),那麼一定觸發 CORB 保護機制,沒法返回 js 資源內容,若是此時本域站點恰好須要這個 js 資源,就 GG 了。至關於 錯誤的 MIME type 加上 X-Content-Type-Options: nosniff
會觸發 CORB ,即便資源真正的類型同跨域標籤一致。
Content-Type
;X-Content-Type-Options: nosniff
禁止 MIME sniffing
,如此,可讓瀏覽器不進行內容 MIME 類型嗅探,從而更簡單快速地保護資源或響應返回。控制檯出現 CORB 提示時,不用擔憂,通常不會對頁面產生本質性的影響,能夠直接忽略。
雖然該部份內容屬於驗證類,但想了解一項知識點,僅僅簡單地閱讀是不夠的,實際操做試驗後才能得到更深的印象和理解。
Chrome 版本: Chrome 73。
Node 服務代碼 index.js
,
const express = require('express')
const path = require('path')
const app = express()
const port = process.argv[2] || 3002
app.get('/', function (req, res) {
res.send('<p>hello world!</p>')
})
app.get('/data', function (req, res) {
console.log('請求正常,只是瀏覽器將響應數據置空')
res.json({greeting: 'hello chrome!'})
})
app.listen(port, () => console.log(`app is listening at localhost:${port}`))
複製代碼
配置 host
127.0.0.1 a.dd.com
127.0.0.1 c.dd.com
127.0.0.1 test.pp.com
複製代碼
test.pp.com
中使用 img
標籤跨域請求 c.dd.com
的數據,數據 MIME 類型爲 jsonnpm init
和 npm install
安裝服務依賴包node index.js
啓動服務test.pp.com:3002
並打開 開發者工具Elements
中插入 <img src="http://c.dd.com:3002/data"/>
(選中 body 元素,再按 F2 便可進入 html 編輯模式)console
便可見,CORB 提示。app.get('/data')
方法返回的數據 {greeting: 'hello chrome!'}
,即 將服務自己返回的數據自己置空,CORB 提示消失,但依舊看不到請求頭 和 響應結果。實驗結果:1. 使用 `img` 跨域請求 json 類型的數據確實會出現 CORB;2. 當服務自己返回數據爲空時,CORB 提示會消失,但其行爲依然保持。
test.pp.com
中使用 script
跨域請求 c.dd.com
的數據,數據 MIME 類型爲 json{greeting: 'hello chrome!'}
,瀏覽器中訪問 test.pp.com 並 打開開發者工具。console
欄中執行下方代碼,便可插入 js 標籤併發送跨域請求。s = document.createElement('script')
s.src = 'http://c.dd.com:3002/data'
document.head.appendChild(s)
複製代碼
效果如圖,
同 img
表現一致,出現了 CORB 提示。清除{greeting: 'hello chrome!'}
,將服務返回數據置空,效果同 img
方式表現一致,CROB 提示消失。其它行爲也同 img
。
實驗結果:同 `img` 行爲效果如出一轍。
看了瀏覽器中 請求的響應 狀況,如今看看,兩次實驗的 請求執行 狀況,
能夠看到儘管產生了 CORB 保護,讓響應結果變爲空,也隱藏了請求頭,但服務請求自己始終正常接收請求並進行處理。由此,看到 CORB 後,通常能夠直接忽略該提示。
若是跨域請求 http://a.dd.com:3002/data
自己發生錯誤,則徹底無需 CORB 的保護,自己就已經不能正常返回了。所以,更不須要 CORB 的提示和行爲。
test.pp.com
中跨域請求 c.dd.com
服務的 server.js 文件本實驗旨在驗證 在某站點跨域請求 js 文件,而該 js 文件被設置了不一樣的 MIME 類型 和 nosniff
時,Chrome 是否會出現 CORB 。
第一步,server.js 文件 MIME 類型爲默認,不設置 nosniff
。c.dd.com
服務代碼 index.js 中添加以下代碼,
代碼片斷一,
app.get('/file', function getState(req,res,next){
res.sendfile(`${__dirname}/public/js/server.js`)
})
複製代碼
打開 Chrome test.pp.com
的開發者工具,並在開發者工具中執行以下代碼,跨域請求 server.js
代碼片斷二,
s = document.createElement('script')
s.src = 'http://c.dd.com:3002/file'
document.head.appendChild(s)
複製代碼
運行結果以下圖,
如圖所示:真實請求頭被隱藏,Provisional headers are shown
;響應頭可見;響應結果可見。
第二步,設置 MIME 類型爲 json
,即 Content-Type: application/json; charset=utf-8
,不設置 nosniff
。修改 index.js /file
部分代碼以下,
代碼片斷三,
app.get('/file', function getState(req,res,next){
res.type('json')
res.sendfile(`${__dirname}/public/js/server.js`)
})
複製代碼
再次執行本實驗 代碼片斷二,發現運行結果同第一步(即默認 MIME 類型)徹底同樣:真實請求頭被隱藏,Provisional headers are shown;響應頭可見;響應結果可見。
第三步,設置 MIME 類型爲 json,即 Content-Type: application/json; charset=utf-8
,並添加 'X-Content-Type-Options': 'nosniff'
響應頭。(若是不理解該響應頭的含義,請再次閱讀文頂內容嗅探相關描述) 兩個響應頭加在一塊兒的意思是,明明本身是 js ,卻告訴瀏覽器 MIME 類型是 json,還非不讓瀏覽器使用嗅探技術修正 MIME 類型。 修改 index.js /file
部分代碼以下。
代碼片斷四,
app.get('/file', function getState(req,res,next){
res.type('json')
res.set({
'X-Content-Type-Options': 'nosniff'
})
res.sendfile(`${__dirname}/public/js/server.js`)
})
複製代碼
再次執行本實驗 代碼片斷二,運行結果以下圖,
如圖所示: 跨域請求 js 文件時,若是沒有設置 nosniff,甭管 MIME 類型設置了什麼,都只是請求頭不顯示,響應頭和響應結果正常顯示。若是設置了 nosniff 且 MIME 類型不是 js,則會觸發 CORB 保護,跨域 js 沒法正常加載。
所以,若是做爲跨域站點 c.dd.com
和 本域站點 test.pp.com
合做時,若是爲了 減小 MIME 類型嗅探時間 加上了 nosniff
請求頭,同時,需務必保證設置的 MIME 類型同 js 文件一致!不然 本域站點 沒法拿到 跨域站點 的 js 資源數據!
----------------- 關於 CORB , Chrome 表現和行爲驗證結束 -------------------
原文地址:www.yaoyanhuo.com/blog/corb
做者博客主頁:www.yaoyanhuo.com