CORS跨域资源共享
CORS基础
CORS(Cross-Origin Resource Sharing)跨源资源共享,是HTML5的一个新特性,其思想是使用自定义的HTTP头部让浏览器与服务器进行沟通,它允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服AJAX只能同源使用的限制。
CORS的基本原理是,第三方网站服务器生成访问控制策略,指导用户浏览器放宽 SOP(同源策略) 的限制,实现与指定的目标网站共享数据。
同源策略我之前的文章有讲,这里就简单说一下
同源策略包括以下三个方面:同端口、同协议、同域名,这三者相同,则认为是同源的,若不同,则认为不同源。
简单请求
简单请求
浏览器直接发出CORS请求, 即浏览器自动在请求header中加上Origin字段, 告诉服务器这个请求来自哪个源(请求协议+域名+端口).
服务器收到请求后, 会对比这个字段, 如果字段值不在服务器的许可范围内, 服务器会返回一个正常的HTTP响应, 但是其响应头中不会包含Access-Control-Allow-Origin字段, 浏览器发现后, 就会抛出一个异常提示响应头中没有这个字段. 如果这个源在服务器的许可范围内, 服务器的响应头会加上以下字段:
1 | Access-Control-Allow-Origin:http://ip:port |
非简单请求
预检请求
请求方式为OPTIONS,这个请求是来询问的,请求头要包含以下字段
- Origin:请求源
- Access-Control-Request-Method:cors请求会用到的请求方式
- Access-Control-Request-Headers:cors请求会额外发送的请求头字段
服务器收到预检请求后会检查上面三个字段的值确定是否允许跨区请求,如果任意一个字段不满足要求,都不允许进行跨域访问
漏洞产生的原因
其实漏洞产生完全是因为配置不当造成的。Origin源未严格校验,从而造成跨域问题。
可以直接利用:
Access-Control-Allow-Origin: https://0xtunan.com
Access-Control-Allow-Credentials: true可能可以利用:
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true梦想的组合但无法利用:
下面这组配置组合虽然看起来很完美但是CORS机制已经默认禁止了这种组合
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true单一的情况,最常见的吧
Access-Control-Allow-Origin:*
各种情况
- CORS服务端的 Access-Control-Allow-Origin 设置为了 *,并且 Access-Control-Allow-Credentials 设置为false,这种情况下任何网站都可以获取该服务端的数据。
- 有一些网站的Access-Control-Allow-Origin他的设置并不是固定的,而是根据用户跨域请求数据的Origin来定的。有时候就是你请求的源是什么,它的acao就是什么,这其实和那个*差不多。
- 有时候很多网站会用正则去匹配acao,然后判断是否应该允许它获取数据,这样有时候就可能出现包含这个域名就可以获取数据。可以通过一些简单的方法去测试下。
攻击流程
- 假设用户登陆一个含有CORS配置不当的网站
test.com
,同时又访问了攻击者提供的一个链接tunan.com
。 tunan.com
向test.com
这个网站发起请求获取敏感数据。- 此时
tunan.com
就可以获取到用户的敏感数据,如果ACAC被设置为ture,还会导致cookie泄露。
其实和CSRF漏洞很像,只是CSRF只能完成相应的功能,无法盗取到用户cookie,以及其他敏感信息。
防御
CORS防御
- 不要配置
Access-Control-Allow-Origin: *
,而且更重要的是,要严格校验来自请求数据数据包中的Origin
的值,注意正则的写法。 - 避免使用
Access-Control-Allow-Credentials:true
,当出现CORS漏洞时可以减少危害,不至于cookie被盗。 - 减少
Access-Control-Allow-Methods
所允许的方法