0x01 浏览器的同源策略(What?)
1 同源策略(Same-Origin Policy)
同源策略是 Netscape 公司引入的安全策略,目前所有浏览器都会实行 SOP 策略,是浏览器最核心、最基本的安全功能
最初,它的含义是指,A 网页设置的 Cookie,B 网页不能打开,除非这两个网页 “同源” 。所谓 “同源” 指的是 “三个相同” 。
同源策略仅存在于浏览器客户端,不存在 Android、iOS、NodeJS、Python、Java 等其他环境。
flash、java applet、silverlight、googlegears等浏览器加载的第三方插件也有各自的同源策略,只是这些同源策略不属于浏览器原生的同源策略,如果有漏洞则可能被黑客利用,从而留下 XSS 攻击的后患
2 同源的定义
如果两个页面的协议、端口(如果有指定)和主机都相同,则两个页面具有相同的源。可以称为:tuple
1 | tuple:协议、域名、端口 # 或者简单地叫做"tuple",即元 |
- 例子:判断下面给出相对http://abc.jjp.com/app/page.html的同源检测结果:
| url | 结果 | 原因 |
|---|---|---|
| http://abc.jjp.com/app/page2.html | 同源 | 只有路径不同 |
| http://abc.jjp.com/source/page2.html | 同源 | 只有路径不同 |
| https://abc.jjp.com/app/dist/page3.html | 不同源 | 协议不相同 |
| http://efg.jjp.com/app/page2.html | 不同源 | 域名不相同 |
| http://abc.jjp.com:8080/app/page2.html | 不同源 | 端口不相同 |
IE例外:IE 非标准的策略
- 范围:两个相互之间高度互信的域名,如公司域名,不遵守同源策略的限制
- 端口:IE 未将端口号加入到同源策略的组成部分之中,即同域名不同端口属于同源
3 源的继承
被创建的窗口从创建它的脚本那里继承对应的源,如:弹窗?
4 源的更改
同源策略认为域和子域属于不同的域,例如: child1.a.com 与 a.com
对于这种情况,可以在两个方面各自设置 document.domain='a.com' 来改变其源来实现以上任意两个页面之间的通信。
22 年更新:目前已被弃用,虽然一些浏览器可能仍然支持,但从标准中删除。因为它破坏了同源策略所提供的安全保护,并使浏览器中的源模型复杂化,导致互操作性问题和安全漏洞。
5 同源策略限制的范围
Cookie、LocalStorage 和 IndexDB 无法读取,localStorage、IndexedDB等数据存储会以源进行分割,每个源拥有自己独立的存储空间,一个源的 js 脚本不能对属于其他源的数据进行读写操作
DOM 无法获得(Document Object Model 译为文档对象模型,是HTML 和 XML 文档的编程接口)
Ajax 请求不能发送
0x02 同源策略的目的(Why?)
- 防止敏感信息泄露:A 网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取 A 网站的 Cookie,那么就会泄露用户的隐私信息(比如:存款总额)
- 防止非授权访问:Cookie 往往保存用户的登录状态,如果用户没有退出登录,且黑客盗取了用户的 Cookie 则可以冒充用户进行任何操作(浏览器规定,提交表单不受同源政策的限制)
0x03 实现跨域读取的方案(How?)
为什么要实现跨域请求?
工程服务化后,不同职责的服务分散在不同的工程中,往往这些工程的域名是不同的,但一个需求可能对应到多个服务,这时便需要调用不同服务的接口,因此会出现跨域。
注意:跨域请求能成功发送,服务端能接收请求并正常返回结果,只是结果被浏览器拦截了。
跨源网络访问
跨域写:通常允许。比如:链接、重定向和表单提交(因为表单提交不需要反馈数据)
跨域资源嵌入:通常允许。避免跨域资源嵌入:需要确保html文档中没有允许跨域资源嵌入的标签
跨域读:通常不允许。比如:在使用 XMLHttpRequest 的时候会发生跨域问题,不过通过某些方法仍可以进行跨域读
1 代理
浏览器请求同源服务器,再由后者请求外部服务
2 JSONP
简单适用,老式浏览器全部支持。思想:网页通过添加一个<script>元素,向服务器请求 JSON 数据,请求的查询字符串有一个callback参数,用来指定回调函数的名字;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
安全问题:JSONP 劫持
3 WebSocket
WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
4 CORS
CORS是跨源资源分享(Cross-Origin Resource Sharing)是W3C标准,是跨源 AJAX 请求的根本解决方法。相比 JSONP 只能发GET请求,CORS允许任何类型的请求。
CORS请求大致和Ajax请求类似,但是在HTTP头信息中加上了Origin字段表明请求来自哪个源。
5 跨窗口的跨域通信
片段识别符
window.name
window.postMessage:跨文档通信API(Cross-document messaging)
0x04 阻止跨域读取
避免跨域写:在发起写请求中携带一个隐藏的token,然后服务器端对这个token进行验证,多用来防范CSRF攻击
避免跨域读:要保证返回给客户端的资源是不可嵌入的,不可以是上面列出的允许跨域资源嵌入的标签
0x05 Cookie的跨域访问控制
- cookies 同样只有同源网页才能共享,设置其
domain、path、secure、HttpOnly属性可以来限定其访问性
| 属性 | 作用 |
|---|---|
| domain | 指定cookies对哪个域有效,cookies 只会发向该域,默认值是设置 cookie 的那个域 |
| path | 表示相对于 domain 的路径,只有在该路径下才能拿到cookies,默认值为 / |
| secure | 设置了该属性或者设置了 ‘secure=true’ 表示只能在 HTTPS 连接中传递 cookies |
| HttpOnly | 设置了该属性或这设置了 ‘HttpOnly=true’ 表示 js 脚本不能读取到cookie信息 |
Reference
1 | https://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html |