CORS介绍及其漏洞检测
一、学习链接
https://zhuanlan.zhihu.com/p/83099266
二、CORS实现原理
在当前页面添加如下头:
Access-Control-Allow-Origin: http://a.com 服务端接受来自http://a.com的跨域请求
Access-Control-Allow-Credentials: true 表示是否允许发送Cookie,true即发送cookie
这样就可以从其他页面(允许的页面)跨域访问该页面。
说到这里,有个常见的关于同源策略的误区需要指出一下,同源策略并不限制请求的发起和响应,只是浏览器拒绝了js对响应资源的操作。
三、CORS常见漏洞
1、反射Origin头
有些开发者为了方便,直接使用请求者的origin作为ACAO的域名,例如下面的Nginx配置:
add_header "Access-Control-Allow-Origin" $http_origin;
add_header "Access-Control-Allow-Credentials" "true";
这种配置非常危险,相当于任意网站可以直接跨域读取其资源内容。
2、Origin校验错误
由于前面那种反射Origin的做法过于暴力,一般也是不可取的,常用做法是通过自定义规则来校验Origin头,但是在校验过程中也会出现错误。这些错误可以分为四类:
前缀匹配:例如想要允许http://example.com访问,但是只做了前缀匹配,导致同时信任了http://example.com.attack.com的访问。
后缀匹配:例如想要允许http://example.com访问,由于后缀匹配出错,导致允许http://attackexample.com访问。
没有转义.:例如想要允许www.example.com访问,但正则匹配没有转义.,导致允许wwwaexample.com访问。
包含匹配:例如想要允许http://example.com,但是Origin校验出错,出现允许http://ample.com访问。
3、信任null
当配置信任名单为null,可以用来和本地file页面共享数据,如下所示:
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
但是攻击者也可以构造Origin为null的跨域请求,比如通过iframe sandbox:
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src='data:text/html,<script>
var xhr=new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
alert(xhr.responseText);
}
}
xhr.open("GET", "http://www.vuln.com/a.php", true);
xhr.withCredentials = true;
xhr.send();</script>'>
</iframe>
4、HTTPS域信任HTTP域
但是如果该HTTPS网站配置了CORS且信任HTTP域,那么中间人攻击者可以先劫持受信任HTTP域,然后通过这个域发送跨域请求到HTTPS网站,间接读取HTTPS域下的受保护内容.
5、信任自身全部子域
很多网站为了方便会将CORS配置为信任全部自身子域,这种配置会扩大子域 XSS的危害。
比如某子站存在xss时,可以通过此xss发送跨域请求,从而获取敏感内容。
6、Origin:*与 Credentials:true 共用
Access-Control-Allow-Origin:*用于表示允许任意域访问,这种配置只能用于共享公开资源。
所以下面这种配置是错误的,浏览器不允许这两种配置同时出现。(对于共享公开资源,不应该需要身份认证)
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
7、缺少Vary: Origin头
如果一个资源享有多个域名,它需要对不同域名的请求包生成不同的ACAO头。如果一个请求的响应被缓存,且返回中没有Vary: Origin字段,可能会导致其它域名的请求失效。
比如http://c.com同时允许http://a.com和http://b.com共享。http://c.com资源内容首先被http😕/a.com脚本跨域访问后被缓存,其中缓存响应头为Access-Control-Allow-Origin:http://a.com这时,b.com脚本则不能读取缓存响应内容,因为缓存响应头是允许a.com共享,而不是b.com。

浙公网安备 33010602011771号