浏览器的同源策略与跨域请求


=Start=

缘由:

本来之前对Web安全就不是太了解,后来工作之后也一直都没有往这方面去深入学习、发展,所以对细节越来越模糊了,最近想着在有时间的时候不断去补习有所欠缺或是比较感兴趣的知识点。苦练基本功!

正文:

参考解答:
1、什么是同源策略?

同源策略(Same Origin Policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

它的核心就在于它认为自任何站点装载的信赖内容是不安全的。当被浏览器半信半疑的脚本运行在沙箱时,它们应该只被允许访问来自同一站点的资源,而不是那些来自其它站点可能怀有恶意的资源。

所谓同源是指:域名、协议、端口相同。比如:

#URL是否同源备注
1http://store.company.com/dir2/other.htmlbase 
2http://store.company.com/dir/inner/another.htm| 
3https://store.company.com/secure.html协议不同
4http://store.company.com:81/dir/etc.html|端口不同
5http://news.company.com/dir/other.htmlhost不同

对于 about:blank和 javascript:这种特殊的URL,他们的源应当是继承自加载他们的页面的源,他们本身并没有『源』的概念。

2、浏览器为什么要设置同源策略?

同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?

很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

由此可见,”同源政策”是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。

3、浏览器同源策略的限制

除了 cookie 的访问受到同源策略的限制外,还有一些操作也同样受到同源策略的限制:

(1) 无法读取非同源网页的 Cookie 、sessionStorage 、localStorage 、IndexedDB

(2) 无法读写非同源网页的 DOM

(3) 无法向非同源地址发送 AJAX请求(可以发送,但浏览器会拒绝响应而报错)

虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。

4、跨域的一些方法整理
五种前端跨域方法

1、JSONP

JSONP(json with padding) ,利用了 <script> 标签能跨域的特性。需要前端和后端约定好一个函数名,当前端请求后端时,返回一段 JS。这段 JS 调用了之前约定好的回调函数,并将数据当作参数传入,完成数据的跨域传递。

这种方式有几个安全问题:

  • 一是接收请求的 api 页面是属于公共使用的那还好,如果是内部私用就会造成一个用户信息泄露的问题;
  • 二是如果 callback 参数的内容是一段 js 代码,当后端没有过滤或者过滤不严时,可能会出现 XSS 问题;三是有可能会出现 SOME 漏洞。

2、document.domain

这种方式有些局限性,只能在顶级域名相同的两个页面中跨域访问。通常情况下,在一个页面中内嵌一个不同域的 iframe,两个页面是无法相互访问的,所以多用于控制页面中内嵌的 iframe。然后再来说下 js 中的 document.domain 这个东西。这个东西会显示当前页面的域名。也可以设置,但有限制,只能设置成当前的域名或者顶级域名。如果设置为其他的域名则会报一个“参数无效”的错误。

3、window.name

关于 window.name 我们先来看这样一个场景,首先是 A 站:

window.name = 'A site data';
location.href = 'http://b.com';

设置完 window.name 后自动跳转到 B 站,此时我们在控制台里 alert 出 window.name ,发现还是我们在 A 站中设置的数据。可以看到如果在一个标签里跳转页面的话,我们的 window.name 是不会改变的。我们可以了利用这个特性进行跨域。顺便提一下,从页面内部打开的另一个页面会包含前一个页面的引用,这也是 target=”_blank” 漏洞的成因。

相同的技术也可以用在 iframe 的跨域数据传递中。

4、postMessage

postMessage 是 HTML5 时代新出现的 API。用于安全的进行跨域请求。从字面意思就可以想象,就是一个页面对另一个页面发消息来实现跨域通信。

5、browser SOP bug

虽然所有的浏览器都有同源策略,但是各家浏览器实现的方式也是各不相同。难免实现也会有漏洞。我们可以找出浏览器同源策略的漏洞来实现跨域访问。例如浏览器对 CSS(层叠样式表)的松散解析就会导致跨域bug的出现。

三种服务器跨域方法

1、反向代理服务器

由于服务器是可以跨域访问数据的。于是我们前端想要什么别的域的数据直接告诉后端服务器,让服务器帮我们去跨域读数据,获取到了再传给我们,这样前端也可以处理别的域内的数据了。也就是说,将其他域名的资源映射到你自己的域名之下,这样浏览器就认为他们是同源的。这就是反代服务器的原理,是不是非常简单。一般我们常常使用 nginx 来配置反向代理服务器。

2、CORS

暂略。

3、flash

了解太少,以后有机会再补充。

5、CORS的一些知识点

CORS(Cross-Origin Resource Sharing, 跨域资源共享)是HTML5的一个新特性,用于解决浏览器跨域网络资源访问,目前已经被所有浏览器支持,并被主流网站广泛部署使用。

随着Web应用的发展,Web开发者需要读取跨域网络资源内容(例如,电商网站想通过用户浏览器加载第三方快递网站的物流信息),开发人员提出了一些临时折衷方案来满足需求,例如JSONP,但是这些折衷方案带来了许多安全问题。

于是W3C 设计了 CORS 协议标准,用于替代 JSONP,实现更安全规范地支持跨域网络资源共享。从2009年开始,CORS协议就已经被各大浏览器(如 Chrome, Firefox等)支持,目前已经被主流网站广泛部署使用。

CORS 的基本原理是,第三方网站服务器生成访问控制策略,指导用户浏览器放宽 SOP 的限制,实现与指定的目标网站共享数据。具体工作流程可分为三步:

  1. 请求方脚本从用户浏览器发送跨域请求。浏览器会自动在每个跨域请求中添加Origin头,用于声明请求方的源。
  2. 资源服务器根据请求中Origin头返回访问控制策略(Access-Control-Allow-Origin响应头),并在其中声明允许读取响应内容的源。
  3. 浏览器检查资源服务器在Access-Control-Allow-Origin头中声明的源,是否与请求方的源相符,如果相符合,则允许请求方脚本读取响应内容,否则不允许。

在CORS协议中,请求方还可以指示浏览器在跨域请求中是否带credentials(包括Cookie,TLS客户端证书和代理验证信息)。如果跨域请求中带了credentials,那么浏览器会检查资源服务器返回的响应头中Access-Control-Allow-Credentials头是否设置为true,如果是,则允许请求方读取响应内容,否则,不允许。

关于CORS其它的细节,读者可以阅读 CORS标准,这里不再详述。

参考链接:

=END=


《 “浏览器的同源策略与跨域请求” 》 有 7 条评论

  1. 绕过浏览器SOP,跨站窃取信息:CORS配置安全漏洞报告及最佳部署实践
    https://github.com/chenjj/CORScanner
    `
    7条 CORS安全配置最佳实践:

    不要盲目反射 Origin头
    严格校验 Origin 头,避免出现权限泄露
    不要配置 Access-Control-Allow-Origin: null
    HTTPS 网站不要信任HTTP 域
    不要信任全部自身子域,减少攻击面
    不要配置 Origin:*和 Credentials: true
    增加 Vary: Origin 头
    `
    https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
    https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
    https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control

  2. 【全栈修炼】414- CORS和CSRF修炼宝典
    https://mp.weixin.qq.com/s/c6g-N3R_o1HAcHZGB84WHw
    `
    CORS :Cross Origin Resourse-Sharing 跨站资源共享

    CSRF :Cross-Site Request Forgery 跨站请求伪造

    XSS :Cross Site Scrit 跨站脚本攻击(为与 CSS 区别,所以在安全领域叫 XSS)
    `

    Cross-Origin Read Blocking (CORB)
    https://www.chromestatus.com/feature/5629709824032768
    https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md
    https://www.chromium.org/Home/chromium-security/corb-for-developers
    `
    Cross-Origin Read Blocking (CORB) is an algorithm that can identify and block dubious cross-origin resource loads in web browsers before they reach the web page. CORB reduces the risk of leaking sensitive data by keeping it further from cross-origin web pages. In most browsers, it keeps such data out of untrusted script execution contexts. In browsers with Site Isolation, it can keep such data out of untrusted renderer processes entirely, helping even against side channel attacks like Spectre.

    跨源读阻塞(CORB)是一种算法,它可以在由web浏览器发出的请求到达web服务器之前识别并阻止可疑的跨源资源加载。CORB通过使敏感数据远离交叉来源的web页面来降低泄漏的风险。在大多数浏览器中,它将这些数据放在不受信任的脚本执行上下文之外。在具有站点隔离的浏览器中,它可以将这些数据完全隔离在不可信的呈现进程之外,甚至有助于抵御Spectre之类的侧通道攻击。
    `

  3. 【原创】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
    https://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html

    Jsonp漏洞简析及自动化漏洞挖掘脚本编写
    https://mp.weixin.qq.com/s/SuEpF3RIZIv2CcIUok8SoQ

    jsonp的一些安全问题
    https://xz.aliyun.com/t/6539

    由浅入深理解JSONP并拓展
    https://www.k0rz3n.com/2018/06/05/%E7%94%B1%E6%B5%85%E5%85%A5%E6%B7%B1%E7%90%86%E8%A7%A3JSONP%E5%B9%B6%E6%8B%93%E5%B1%95/

    【挖洞姿势】Jsonp劫持
    http://www.fr1sh.com/?post=20

    JSONP Hunter in burpsuite.
    https://github.com/p1g3/JSONP-Hunter

    从 Ajax 聊一聊 Jsonp 点击劫持
    https://mp.weixin.qq.com/s/0rTTpt0GtBDgdjVl0dDl8Q?

    JSONP与CORS漏洞挖掘
    https://www.anquanke.com/post/id/97671

    JSONP注入实践
    http://www.mottoin.com/detail/903.html

  4. 腾讯一面:CORS为什么能保障安全?为什么只对复杂请求做预检?
    https://mp.weixin.qq.com/s/W38vyzlqRtUysjguHeqiNQ
    `
    提起CORS,大部分的文章都在写什么是简单请求、什么是复杂请求,复杂请求预检的流程又是怎样。

    但如果问你:

    1. CORS为什么要带上源,这是为了保障当前站点的安全还是目的服务器的安全?
    2. 为什么区分简单请求和复杂请求,只对复杂请求做预检?

    这篇文章会围绕CORS是如何保障安全的的,讲清这几个问题。读完可以对CORS知其然,并知其所以然。

    CORS把请求分成简单请求和复杂请求,划分的依据是“是否会产生副作用”。

    简单贴一下定义,同时满足下面这两个条件的是简单请求
    1. 请求方法是HEAD/GET/POST
    2. 请求体的文件类型只能是form-urlencoded、form-data、text/plain(这类文章很多,不再赘述,可以看阮一峰-跨域资源共享)

    对于简单请求,流程如下:

    1. 浏览器发起请求,并且自动加上请求的来源origin给服务器检查;
    2. 服务器返回数据,并返回检查结果,配置CORS响应头;
    3. 浏览器检查CORS响应头,如果包含了当前的源则放行,反之拦截;

    这里需要注意,浏览器是拦截响应,而不是拦截请求,跨域请求是发出去的,并且服务端做了响应,只是浏览器拦截了下来。

    对于复杂请求,整个流程如下:
    1. 浏览器发起预检请求,带上请求的来源origin,不包含请求体;
    2. 服务器返回检查结果,配置CORS头;
    3. 浏览器发起真正请求;
    4. 浏览器返回数据;

    浏览器会检查第2步中拿到的CORS头,如果没有包含当前的源,后续的第3、4步都不会进行,也就是不会发起真正请求。

    CORS给开发带来了便利,同时也带来了安全隐患——CSRF攻击。

    回到开头的两个问题,不难得出答案:
    1. 对于跨域请求带上请求来源,是为了防止CSRF攻击;浏览器的心智模型是:跨域请求都是不安全的,CORS的机制是为了保障请求目的服务器的安全;
    2. 依据是否对服务器有副作用,划分了简单请求和复杂请求(但由于历史原因,表单POST请求也被划分成了简单请求),预检机制会把不安全的复杂请求拦截下来,避免对服务器造成危害,而简单请求通常不会对服务器的资源作出修改,即使发出危害不大。
    `

回复 hi 取消回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注