简介
同源策略是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 的源应该就是我的博客地址 / 。
如何跨源访问
CORS
CORS中关键的几个HTTP头字段如下:
- Access-Control-Allow-Origin:指定哪些外域可以访问本域资源;
- Access-Control-Allow-Credentials:指定浏览器是否将使用请求发送Cookie。仅当设置为true时,才会发送Cookie;
- Access-Control-Allow-Methods:指定可以使用哪些HTTP请求方法(GET、POST、PUT、DELETE等)来访问资源;
- Access-Control-Allow-Headers:指定可以在请求报文中添加的HTTP头字段;
- Access-Control-Max-Age:指定超时时间;
同域可读可写,跨域请求不能检查到 Access-Control-Allow-Origin 的情况下,response 会被拦截。
// 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 jsonp(data) {
console.log(data);
}jsonp('{"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