对于同源策略和CSP一直是只知皮毛,没有进行一次深入的分析,偶然看到安全维基上的web安全职位面试题,面试前几题基本就是同源和CSP的一些问题,针对这些问题,笔者基本是讲不清的。。所以还是来好好学习一波吧~
面试题链接:传送门
一、同源策略
Domain
解释一下同源策略
同源策略,那些东西是同源可以获取到的
如果子域名和顶级域名不同源,在哪里可以设置叫他们同源
如何设置可以跨域请求数据?jsonp是做什么的?
这是面试题上的题目,下面我们借着这些题目来认识什么是同源策略?
所谓同源是指域名(主机名或者IP地址)、端口、协议相同。不同的客户端脚本(JavaScript、ActionScript)在没明确授权的情况下,不能读取对方的资源。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
不同源的例子:
1. 域名(主机名或者IP地址)不同
http://news.company.com/index.html与http://www.company.com/index.html不同源,域名不同,news子域与www子域不同。
http://company.com/index.html与http://www.company.com/index.html 不同源,域名不同,顶级域与www子域不是一个概念。
2. 端口不同
http://www.company.com:8080/index.html与
http://www.company.com/index.html不同源,端口不同,8080与默认的80端口不同。
3. 协议不同
https://www.company.com/index.html与
http://www.company.com/index.html 不同源,协议不同,https与http是不同协议。
同源的例子:
http://www.company.com/a/c/index.html与
http://www.company.com/b/d/index.html 属于同源,域名,端口,协议均相同。
|
综上所述,是否同源也就看三个参数:域名、端口、协议。
但是IE上对于同源策略有两个特例
1
2
3
4
5
|
1. 授权范围(Trust Zones)
两个相互之间高度互信的域名,如公司域名(corporate domains),不遵守同源策略的限制。
2. 端口
IE并没有将端口号加入到同源策略的组成部分之中,因此,https://www.company.com:8080/index.html 与
http://www.company.com/index.html 属于同源并且不受任何限制。
|
下面来演示一下同源策略的应用!
那么我们可以知道了什么是同源策略,并且通过上面的讲述,我们可以知道同源策略下利用javascript仅可以操作自己web下的应用,即只可以操作自己域下的东西。
那么下面继续看,两个域名不同源,如何设置让它们同源?
由于自己也是一知半解,通过百度得到了一个比较可靠的答案,那就是在在WEB服务器或者服务端脚本中设置ACCESS-CONTROL-ALLOW-ORIGIN头部,通过设置这个http头部,那么浏览器就会跳过同源限制,最终返回不同域的内容。
1
2
|
1.如果设置 Access–Control–Allow–Origin:*,则允许所有域名的脚本访问该资源。
2.Access–Control–Allow–Origin:http://www.aerchi.com,允许特定的域名访问。
|
那么针对上面问题,我们只需要修改特定域名即可~完美解决问题!
下面是针对跨域请求数据方面的,继续研究ing。。
一般情况下跨域请求有两个办法,一个是jsonp,一个是cors。(全是陌生词汇。。)
那么这里先讲jsonp!
JSONP也是开发中常见到的内容,在jquery中就有封装,通过ajax请求多带上一个jsonp的参数即可。JSONP也能够实现跨域访问资源,但是它的实现原理其实跟ajax没有多少关系,它是通过动态插入<script>标签来实现跨域资源访问的,因为根据前面内容我们已经知道,嵌入跨域资源浏览器是允许的。
那么这里又提到ajax请求,这里感觉必须先重点讲解下什么是ajax请求!
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。所谓异步,在这里简单地解释就是:向服务器发送请求的时候,我们不必等待结果,而是可以同时做其他的事情,等到有了结果我们可以再来处理这个事。
直白地说,就是没用AJAX的网页,你点一个按钮就要刷新一下页面,尽管新页面上只有一行字和当前页面不一样,但你还是要无聊地等待页面刷新。用了AJAX之后,你点击,然后页面上的一行字就变化了,页面本身不用刷。AJAX只是一种技术,不是某种具体的东西。不同的浏览器有自己实现AJAX的组件。
对ajax的一些基本情况了解之后,我们回到我们的jsonp来~
JSONP(JSON with Padding)是一个简单高效的跨域方式,HTML中的script标签可以加载并执行其他域的JavaScript,于是我们可以通过script标记来动态加载其他域的资源。例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA需要的数据,然后在pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。JSONP在此基础上加入了回调函数,pageB加载完之后会执行pageA中定义的函数,所需要的数据会以参数的形式传递给该函数。
下面给出一个案例
http://localhost:8080/test.html
1
2
3
4
5
6
|
<script src=“http://localhost:8081/test_data.js” type=“text/javascript”></script>
<script>
function test_handler(data) {
console.log(data);
}
</script>
|
可以看到调用了8081端口的js脚本,实现了跨域请求
http://localhost:8081/test_data.js
1
|
test_handler(‘{“data”: “something”}’);
|
为了动态实现JSONP请求,可以使用Javascript动态插入<script>标签
1
2
3
4
5
6
7
|
<script type=“text/javascript”>
// this shows dynamic script insertion
var script = document.createElement(‘script’);
script.setAttribute(‘src’, url);
// load the script
document.getElementsByTagName(‘head’)[0].appendChild(script);
</script>
|
JSONP协议封装了上述步骤,jQuery中统一实现在Ajax中(其中data type为JSONP):
http://localhost:8080/test?callback=test_handler
为了支持JSONP协议,服务器端必须提供特别的支持,另外JSONP只支持GET请求。
下面来探究什么是CROS(Cross-origin resource sharing)
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
CORS请求分为两种,一个是简单请求,一个是非简单请求
只要同时满足以下两大条件,就属于简单请求。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept–Language
Content–Language
Last–Event–ID
Content–Type:只限于三个值application/x–www–form–urlencoded、multipart/form–data、text/plain
|
凡是不同时满足上面两个条件,就属于非简单请求。浏览器对这两种请求的处理,是不一样的。
1.简单请求
对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。
1
2
3
4
5
6
|
GET /cors HTTP/1.1
Origin: http://foreversong.cn
Host: api.alice.com
Accept–Language: en–US
Connection: keep–alive
User–Agent: Mozilla/5.0
|
上面的头信息中,Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。
2.非简单请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
“预检”请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。
除了Origin字段,”预检”请求的头信息包括两个特殊字段。
(1)Access-Control-Request-Method
该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。
(2)Access-Control-Request-Headers
该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。
服务器收到”预检”请求以后,检查了Origin,、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。
CORS与JSONP的使用目的相同,但是比JSONP更强大。
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
二、CSP
CSP是什么?如何设置CSP?
这是sec-wiki上的问题,看似很简单,但是水是真的深!
CSP指的是内容安全策略,为了缓解很大一部分潜在的跨站脚本问题,浏览器的扩展程序系统引入了内容安全策略(CSP)的一般概念。这将引入一些相当严格的策略,会使扩展程序在默认情况下更加安全,开发者可以创建并强制应用一些规则,管理网站允许加载的内容。
一个最简单的CSP配置规则如下
1
|
<span class=“nt”>header</span><span class=“o”>(</span><span class=“s2”>“Content-Security-Policy: default-src ‘self’; script-src ‘self’ https://lorexxar.cn;”</span><span class=“o”>);</span>
|
其中的规则指令分很多种,每种指令都分管浏览器中请求的一部分。
一般存在bypass csp的情况基本都是CSP 规则的配置问题导致的!
下面给出几组配置问题导致的bypass
1
|
header(“Content-Security-Policy: default-src ‘self ‘; script-src * “);
|
加载任何域的js,明显有问题!
1
|
<span class=“nt”>header</span><span class=“o”>(</span><span class=“s2”>“Content-Security-Policy: default-src ‘self’; script-src ‘self’ “</span><span class=“o”>);</span>
|
加载当前域的js,可能这是最常规的配置,想想也没什么问题啊。但是站内总会有上传图片的地方,如果我们上传一个内容为js的图片,图片就在网站的当前域下了。最后直接加载图片即可。
对csp的介绍就到这里!上述如有不当之处,敬请指出!
参考:
http://blog.csdn.net/tim_tsang/article/details/46124527
http://www.ruanyifeng.com/blog/2016/04/cors.html
https://paper.seebug.org/423/
http://sec.chinabyte.com/106/12923606_all.shtml
https://xianzhi.aliyun.com/forum/read/523.html
0x00 cms简介 云EC电商系统是由一套基于PHP+MYSQL开源的、免费的电商系统软件。支付整合了支付宝三端支付(PC、手机、APP),微信三端支付(PC扫码、微信公众号、APP),银联支付。 模块化设计,可方便快捷的接入其它第三方功能。 支持微信与QQ…
请登录后发表评论
注册