本文的开始源于落地页项目中遇到的 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