关于同源策略的理解与跨源

简介

同源策略是Web安全中一项用以保护Web文档信息的手段,原来一直以为自己对其有所了解,然而在BackdoorCTF中遇到的内容让我查阅了一些资料,做此总结。
以下内容如有错误请指正。

同源

如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。
下表给出了相对http://store.company.com/dir/page.html同源检测的示例:

源的继承

data:URLs获得一个新的,空的安全上下文。
在页面中用 about:blank 或 javascript:URL 执行的脚本会继承打开该 URL 的文档的源,因为这些类型的 URLs 没有明确包含有关原始服务器的信息。
例如,about:blank 通常作为父脚本写入内容的新的空白弹出窗口的 URL(例如,通过 Window.open() 机制)。 如果此弹出窗口也包含代码,则该代码将继承与创建它的脚本相同的源。

跨源网络访问

跨源访问

跨源访问分为读(read)、写(write)、嵌入(embed)
在这三种行为之中,通常情况下只有Cross-origin read是不被允许的,其余的两种是允许的,例如Cross-origin write中的links,重定向以及表单提交,Cross-origin embedding中的资源嵌入。

允许跨域写

表单提交,例如我模拟了一个表单提交到我的一个其它站点。
同源策略主要限制的是不同源之间的交互操作,对于跨域内嵌的资源不受该策略限制。

允许跨域嵌入

<script src="……"></script> 标签嵌入脚本,语法错误信息只能在同源脚本中捕捉到。
<link rel="stylesheet" href="……"> 标签嵌入css。由于CSS的松散的语法规则,CSS的跨域需要一个设置正确的Content-Type 消息头。不同浏览器有不同的限制
<img src="" alt=""> 标签嵌入图片
<video></video><audio></audio> 标签嵌入多媒体资源
@font-face
<iframe src="……" frameborder="0"></iframe> 载入的任何资源。可以使用x-frame-options消息头来阻止这种形式的交互。

不允许跨域读

需要注意的是,页面内的引入的文件的域并不重要,重要的是加载该文件的页面所在的域。例如说我在博客的首页引入了 //cdn.bootcss.com/jquery/3.1.1/jquery.min.js 的jquery文件,这时 jquery.min.js 的源应该就是我的博客地址 http://www.xmsec.cc

如何跨源访问

CORS

同域可读可写,跨域请求不能检查到 Access-Control-Allow-Origin 的情况下会被拦截。

// www.xmsec.cc:4000
// 跨域请求
var url = "http://www.xmsec.cc/demo.php";
var params = "test1=1&test2=2";
var http = new XMLHttpRequest();
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
    alert(http.responseText);
}
}
http.send(params);

> XMLHttpRequest cannot load http://www.xmsec.cc/demo.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.xmsec.cc:4000' is therefore not allowed access.

上面错误提示可以设置 Access-Control-Allow-Origin ,于是在header中添加设置即可实现跨域请求。

HTTP访问控制(CORS)详细介绍

JSONP

cors的方式可以发起post请求,或者说其它形式的请求,但是jsonp只能使用get的方式获取数据。

<script>
    function abc(data) {
        console.log(data);
    }abc('{"abc":"123"}');
</script>

<script src="http://xx/demo.php?callback=jsonp"></script>

简单说就是定义好回调处理方法,把回调函数的名称传递给后端,后端拿到数据名称后返回会的数据就是对于回调方法的执行。

<script src="http://xx/demo.js"></script>
/**
 * demo.js的内容
 * jsonp({"abc":"123"});
 */

跨源脚本API访问

Javascript的APIs中,如 iframe.contentWindow, window.parent, window.open 和 window.opener 允许文档间直接相互引用。当两个文档的源不同时,这些引用方式将对 Window 和 Location对象的访问添加限制。

Window

允许以下对 Window 属性的跨源访问:

Location

允许以下对 Location 属性的跨源访问:

为了在不同源中文档进一步交流,可以使用window.postMessage,在之前的BackdoorCTF中有过出现,见WriteUp

Refer:
https://segmentfault.com/a/1190000007417064
https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy
https://lightless.me/archives/review-SOP.html

作者:xmsec
Chief Water dispenser Manager, delivering but striving.
GitHub