导语

由于浏览器最核心、最基本的安全功能——同源策略,的限制,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。跨域的问题可以说是前端程序员的一坨心病,与此同时跨域安全也是安全程序员的一大坨心病,今天由我来简单说说~

同源策略是什么

同源策略是浏览器最核心、最基本的安全功能,是对不同域资源的管理策略。简单来说就是在没有明确授权的情况下,一个源的脚本能且仅能访问自己的源的资源。
这里的“资源”主要包括:

  1. 非同源网页的 Cookie、LocalStorage 和 IndexedDB
  2. 非同源网页的 DOM
  3. 非同源地址发送 AJAX 请求浏览器会拒绝响应

而要想搞明白同源策略,首先要知道怎么样算“同源”:如果两个页面的协议 协议域名端口 都相同的话,那么他们就是同源的。
举个栗子,针对 http://smartpillar.xyz 这个页面

URL 是否同源 Why?
http://smartpillar.xyz/跨域及安全 协议:http 域名:www.smartpillar.xyz 端口:默认(80)
https://smartpillar.xyz/分区表 不是 协议不同
http://api.smartpillar.xyz 不是 域名不同
http://smartpillar.xyz:27016 不是 端口不同

比如说你想在smartpillar.xyz的某个接口里读noobgun.club/flag.txt你就不能行

可以抽象一点:
你:浏览器老师,我想借我同桌的橡皮!
浏览器:不行,你同桌的橡皮不是你的橡皮!
你(心想):还能难住我?

怎么应对跨域

不同源怎么拿cookie

同源策略认为域和子域属于不同的域,如果两个页面主域相同而次域不同,比如api.smartpillar.xyz和cdn.smartpillar.xyz之间,可以通过设定document.domain为相同的值来共享cookie

抽象:浏览器老师知道你和你弟是亲戚,并且你和你弟都给老师说你们的橡皮(cookie)的所有者是你们的家族,浏览器老师想想,觉得合理,你和你弟就都可以用橡皮了。

不同源怎么ajax请求

同源政策规定,AJAX 请求只能发给同源的网址,否则就报错。
因此,一个非常直接的方法就是用代理服务器,通过一些方法设置代理,在请求发送(接收)之前加入中间层,将不同的域转换成相同的,就解决了问题。
抽象:你把你的橡皮给浏览器老师,浏览器老师给了中转服务器校长,并且说这个是你的橡皮,校长说,不对,这是XXX的橡皮。老师也就说,好好好,这是XXX的橡皮,然后XXX就可以用你的橡皮了

jsonp

跨域对某些资源是没有限制的,比如<script>、<image>、<link>和<iframe>标签
jsonp的核心思想就是通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
抽象:老师不让你们传橡皮,但是让你们传衣服,所以你把橡皮塞到衣服里,然后传给了同桌,这样同桌把橡皮从衣服里掏出来就能用了。

PostMessage

PostMeaage是H5新引入的实现跨域窗口之间的通讯,可以安全地实现windows对象之间的跨域通信
PostMessage主要依靠Window.postMessage方法,该方法有三个参数

  1. message:发送到其他窗口的数据
  2. targetOrigin:接受数据消息的目标窗口,当该值为星号(* )表示任意一个域都可以接受消息
  3. transfer: 可选项,代表纤细的所有权

除了发送之外,必然有一个接受消息的窗口,一般用window.addEventListener(“message”,receiveMessage.false),用以接受消息数据
他的消息流程如下图

抽象:老师不让传橡皮,但是班长规定了一个新的可以传橡皮的方法。

CORS

CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
简单来说就是在后端设一个Access-Control-Allow-Origin来确定与哪些域共享资源。如果共享资源包括cookie的话,还需在前端设一个对应的字段来说明。
抽象:你早上没写作业,打算问要一本别人的作业抄抄,众所周知,作业不能给别人抄,但是课代表(后端)知道谁谁谁和你关系好,你们经常臭味相投互相抄,于是就给了你一份。

同源策略存在的安全问题

jsonp

  1. 对于输入的callback函数名过滤不严格,导致输入的数据直接输出到前端造成XSS
    直接改函数名字,比如 http://XXXXXXX/index.php?callback=jsonp<img src=x onerror=alert(/xss/)\>就可以反射型XSS了,反射型XSS的危害就不赘述了。

  2. JSONP劫持漏洞,由于对于来源域没有严格限制,因此来源于不安全的域的请求也会被响应
    JSONP劫持,实质上算是一种读类型的CSRF,在恶意的网页中构造恶意的JS代码,当合法用户点击该网页,由于目标站点存在JSONP劫持漏洞的接口,因此会将用户的该接口对应的信息劫持,并将其发送到攻击者的服务器。比如说你与某网站的jsonp接口没有refer头的确认,也就是说这个接口就无脑响应,也就存在了jsonp劫持漏洞。
    假设你是用户,你先访问了wb,且你和wb有jsonp接口,而wb又没有做好防护,此时,你登陆了wb,同时你又访问了一个坏人的网站,这个网站直接在head里整了一个自动执行的脚本,功能是通过wb的jsonp请求并传数据到他手里,你直接一个个人信息的泄露。

PostMessage

PostMessage跨越一般威胁点在于对于目标域限制不严格导致的,大多数开发人员在发送时对于postmessage防范中targetOrigin参数默认为* ,因此只要包含了该方法页面,就能被任何人所接受监听。
或者说接受方直接就接收,而不去判断发送方的身份,这样就有可能被别有用心的人发送一些未经授权的消息。
而别用用心主要是在接收方设置的读为messageEle.innerHTML方式,这样发送消息的一方就可以发送类似于<img src='x' onerror=alert(1);>的代码进行XSS。

CROS

CORS一般最常见的安全威胁就是CORS错误配置导致资源信息泄漏,与JSONP劫持基本上一致。
比如嫌麻烦直接Access-Control-Allow-Origin设为*,然后让有心之人直接构造对应请求就完事了。

参考:
https://blog.csdn.net/qq_38128179/article/details/84956552
https://www.cnblogs.com/dfzj/p/13663301.html
https://www.freebuf.com/articles/web/208672.html
https://www.cnblogs.com/happystudyhuan/p/11583384.html