CORS跨域资源共享漏洞

目录

CORS跨域资源共享

简单跨域请求

非简单请求

CORS的安全问题


有关于浏览器的同源策略和如何跨域获取资源,传送门——> 浏览器同源策略和跨域的实现方法

CORS跨域资源共享

跨域资源共享(CORS)是一种放宽同源策略的机制,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制,以使不同的网站可以跨域获取数据。

我们先来简单分析一下CORS跨域获取资源的过程:

CORS定义了两种跨域请求:简单请求非简单请求。简单跨域请求就是使用设定的请求方式请求数据,而非简单跨域请求则是在使用设定的请求方式请求数据之前,先发送一个OPTIONS预检请求,验证请求源是否为服务端允许源。只有"预检"通过后才会再发送一次请求用于数据传输。

当我们需要发送一个跨域请求的时候,浏览器会首先检查这个请求,如果它是简单跨域请求,浏览器就会立刻发送这个请求。如果它是非简单跨域请求,这时候浏览器不会马上发送这个请求,而是有一个跟服务器预检验证的过程。

简单跨域请求


 
 
  1. 1) 请求方法是以下三种方法之一:
  2. HEAD
  3. GET
  4. POST
  5. 2)HTTP的头信息不超出以下几种字段:
  6. Accept
  7. Accept-Language
  8. Content-Language
  9. Last- Event-ID
  10. Content-Type:application/x-www-form-urlencoded、 multipart/form-data、 text/plain

只有同时满足以上两个条件时,才是简单请求,否则为非简单请求。

浏览器判断该请求为简单请求时,会在Request Header中添加 Origin 字段,它表示我们的请求源。

如下,简单请求头:

CORS服务端会将该字段作为跨源标志。CORS接收到此次请求后, 首先会判断Origin是否在允许源(由服务端决定)范围之内。

如果Origin指定的源在许可范围内,即验证通过,服务端会在Response Header 添加下面几个字段

  • Access-Control-Allow-Origin:该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
  • Access-Control-Allow-Credentials:该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。当设置为true时,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可
  • Access-Control-Expose-Headers:该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

如下,CROS服务端的回应:

如果Origin指定的源不在许可范围内,即验证失败,服务器也会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息中的Access-Control-Allow-Origin字段不包含访问源,就知道出错了,从而抛出同源检测异常的错误。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

上面说到,CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。

Access-Control-Allow-Credentials:true
 
 

另一方面,开发者必须在AJAX请求中打开withCredentials属性 


 
 
  1. var xhr = new XMLHttpRequest();
  2. xhr.withCredentials = true;

否则,即使服务器同意浏览器发送Cookie,浏览器也不会发送。或者,服务器要求设置Cookie,浏览器也不会处理。

但是,如果省略withCredentials设置,有的浏览器还是会一起发送Cookie。这时,可以显式关闭withCredentials

xhr.withCredentials = false;
 
 

需要注意的是,如果要发送Cookie,即Access-Control-Allow-Credentials:true时,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。

总结:简单请求只需要CORS服务端在接受到携带Origin字段的跨域请求后,在response header中添加Access-Control-Allow-Origin等字段给浏览器做同源判断。

非简单请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json。非简单请求的CORS请求,会在正式通信之前,增加一次OPTIONS方法的预检请求。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

下面简单分析一下非简单跨域请求的过程。浏览器先发送一个OPTIONS方法的预检请求。带有如下字段:

  • Origin: 在CORS中专门作为Origin信息供后端比对,表明来源域。
  • Access-Control-Request-Method:  接下来请求的方法,例如PUT、DELETE等等
  • Access-Control-Request-Headers: 自定义的头部,所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中

然后如果服务器配置了CORS,会返回对应对的字段,具体字段含义在返回结果是一并解释。

  • Access-Control-Allow-Origin:   允许进行跨域请求的域名
  • Access-Control-Allow-Methods:  允许进行跨域请求的方式
  • Access-Control-Allow-Headers:  允许进行跨区请求的头部

如下,OPTIONS预检的请求与相应

然后浏览器再根据服务器的返回值判断是否发送非简单请求。然后服务器处理完请求之后,会再返回结果中加上如下控制字段:

  • Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符"*"。这里要注意Origin规则只对域名有效,并不会对子目录有效。即http://foo.example/subdir/ 是无效的。但是不同子域名需要分开设置,这里的规则可以参照同源策略
  • Access-Control-Allow-Credentials: 是否允许请求带有验证信息
  • Access-Control-Expose-Headers: 允许脚本访问的返回头,请求成功后,脚本可以在XMLHttpRequest中访问这些头的信息
  • Access-Control-Max-Age: 缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数
  • Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开
  • Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感

然后浏览器通过返回结果的这些控制字段来决定是将结果开放给客户端脚本读取还是屏蔽掉。如果服务器没有配置CORS,返回结果没有控制字段,浏览器会屏蔽脚本对返回信息的读取,并报出同源检测异常的错误!

通过上面叙述,我们得知借助CORS我们不必关心发出的请求是否跨域,浏览器会帮我们处理这些事情,但是服务端需要支持CORS,服务端实现CORS的原理也很简单,在服务端完全可以对请求做上下文处理,已达到接口允许跨域访问的目的。

当然,也有很多第三方的CORS插件,例如:Spring MVC 在4.2以上版本也支持了CORS配置,这样,服务端也无需自己操心了!

CORS的安全问题

CORS非常有用,可以共享许多内容,不过这里存在风险。因为它完全是一个盲目的协议,只是通过HTTP头来控制的。那么,CORS跨域资源共享漏洞是怎么发生的呢?由于程序员配置不当,Origin源不严格,从而造成跨域问题。

由以上可知,网站可以通过发送以下HTTP响应头部来启用CORS:

Access-Control-Allow-Origin: https://example.com
 
 

这样的话,就可以允许指定的源(http://example.com)来跨域请求服务器端的资源,并且服务器会响应。在默认情况下,发送跨域请求时不会携带cookie或其他凭据。因此,它不能用于窃取与用户相关的敏感信息(如CSRF令牌)。不过,网站服务器可以使用以下头部来启用凭据传输:

Access-Control-Allow-Credentials:true
 
 

这样浏览器在请求数据的时候就需要带上cookie。

实现对单个域的信任是非常容易的事情。不过,如果需要信任多个域的话,那该怎么办呢?根据相关规范的建议,只需列出相关的域,并用空格加以分隔即可,例如:

Access-Control-Allow-Origin:http://a.example.com  http://example.com
 
 

但是,没有哪个浏览器真正支持这一特性。

于是,我们可以通过使用通配符来信任所有子域,具体方法是:

Access-Control-Allow-Origin:  *.example.com
 
 

可是有一些偷懒的程序员,将Access-Control-Allow-Origin设置为允许来自所有域*的跨域请求。

Access-Control-Allow-Origin:*
 
 

这样,所有的网站都可以对其进行跨域资源请求了,这是非常危险的。不过先别高兴的太早。其实这里在设计的时候有一个很好的限制。xmlhttprequest发送的请求需要使用 "withCredentials" 来带上Cookie,如果一个目标域设置成了允许任意域的跨域请求,这个请求又带着 Cookie 的话,这个请求是不合法的。(就是如果需要实现带 Cookie 的跨域请求,CORS服务端需要明确的配置允许来源的域,使用任意域的配置是不合法的)浏览器会屏蔽掉返回的结果。Javascript 就没法获取返回的数据了。这是CORS模型最后一道防线。假如没有这个限制的话,那么 Javascript 就可以获取返回数据中的 Cookie 和 CSRF Token,以及各种敏感数据。这个限制极大的降低了CORS的风险。

如下,这是不允许的:


 
 
  1. Access-Control-Allow-Origin: *
  2. Access-Control-Allow-Credentials: true

这时,将在浏览器控制台中收到错误消息:当凭证标志为true时,无法在Access-Control-Allow-Origin中使用通配符(各个浏览器报错显示的不一样)。

那么,CORS的漏洞到底出现在哪里呢?

1:CORS服务端的 Access-Control-Allow-Origin 设置为了 *,并且 Access-Control-Allow-Credentials 设置为false,这样任何网站都可以获取该服务端的任何数据了。

2:有一些网站的Access-Control-Allow-Origin他的设置并不是固定的,而是根据用户跨域请求数据的Origin来定的。这时,不管Access-Control-Allow-Credentials 设置为了 true 还是 false。任何网站都可以发起请求,并读取对这些请求的响应。意思就是任何一个网站都可以发送跨域请求来获得CORS服务端上的数据。

下面的代码是通过AJAX来跨域请求获取服务端的数据


 
 
  1. <html lang= "en">
  2. <head>
  3. <meta charset="UTF-8">
  4. <title>Ajax </title>
  5. <script type="text/javascript">
  6. function foo(){
  7. var xmlhttp= new XMLHttpRequest();
  8. var url= "http://127.0.0.1/1.txt"; //要跨域访问的资源
  9. xmlhttp.open( "POST",url, true);
  10. //xmlhttp.setRequestHeader('X-PINGOTHER','AAAA'); //自定义头部,如果这样的话,就属于非简单请求了
  11. //xmlhttp.setRequestHeader('Content-Type','text/xml'); //自定义头部,如果这样的话,就属于非简单请求了
  12. xmlhttp.send();
  13. xmlhttp.onreadystatechange= function()
  14. {
  15. if (xmlhttp.readyState== 4 && xmlhttp.status== 200)
  16. {
  17. document.getElementById( "my").innerHTML=xmlhttp.responseText;
  18. }
  19. }
  20. }
  21. </script>
  22. </head>
  23. <body>
  24. <button id="btn" οnclick="foo()">确定 </button>
  25. <p id="my">hello,word! </p>
  26. </body>
  27. </html>

CORS漏洞的利用 

CORS(跨域资源共享)错误配置漏洞的高级利用

参考文章:对五家主流网站托管服务商进行的一次渗透测试

                  HTTP访问控制(CORS)

                  跨域——CORS详解

                  跨域资源共享 CORS 详解

                  如何利用CORS配置错误漏洞攻击比特币交易所

                

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CORS(Cross-Origin Resource Sharing)是一种跨域资源共享机制。它允许web应用程序向其他域(域名、协议、端口不同)请求资源,比如调用第三方API接口。CORS由浏览器实现,它通过HTTP头部来告诉浏览器哪些跨域请求是安全的。CORS跨域资源共享漏洞指的是攻击者利用CORS机制的漏洞获取敏感信息或进行恶意操作。 CORS跨域资源共享漏洞的原理是:当一个网站想要向另一个域名的服务器发起跨域请求时,浏览器会先向服务器发送一个OPTIONS请求,询问服务器是否允许该网站跨域请求。如果服务器允许,则浏览器会发送真正的跨域请求。攻击者可以通过构造特定的请求,绕过浏览器的CORS机制,从而获取敏感信息或进行恶意操作。 常见的CORS跨域资源共享漏洞包括: 1.未正确配置Access-Control-Allow-Origin头部,导致攻击者可以跨域访问敏感接口。 2.使用通配符“*”来允许所有域名跨域请求,导致攻击者可以利用其他网站的漏洞来攻击目标网站。 3.未正确限制Access-Control-Allow-Methods头部,导致攻击者可以使用其他HTTP方法来调用敏感接口。 4.未正确限制Access-Control-Allow-Headers头部,导致攻击者可以发送任意HTTP头部来调用敏感接口。 要防范CORS跨域资源共享漏洞,可以采取以下措施: 1.正确配置Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers头部,只允许必要的域名、HTTP方法和HTTP头部访问敏感接口。 2.对敏感接口进行身份验证和授权,只允许授权用户访问。 3.限制跨域请求的频率和流量,避免恶意攻击。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值