浏览器的同源策略约束着不同源的资源交互,但这也带来诸多的不便,例如随着WEB应用的发展,有些网站由于自身业务的需求,需要实现一些跨域的功能,让不同域的页面之间能够相互访问各自页面的内容,而浏览器的同源策略会限制这种请求,因此需要采用CORS以实现跨域访问,这本身是一种功能。CORS(Cross-Origin Resource Sharing)即跨域资源共享,是用于绕过SOP(同源策略)来实现跨域资源访问的一种技术,是HTML5提供的一种机制。
CORS请求可以分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。只要同时满足以下两个条件就属于简单请求否则属于非简单请求:
①请求方法是(HEAD,GET,POST)三种之一;
②HTTP的头信息不超出(Accept,Accept-Language,Content-Language,Lat-Event-ID,Content-Type)这几种字段。
对于简单请求,浏览器会自动在头信息中增加了一个Origin的字段,用来表示这次的请求来自哪个域名。当服务器接收到请求后发现Origin字段指定的域名在许可范围内,服务器会在响应包中增加三个与CORS相关的字段,分别是:
Access-Control-Allow-Origin、Access-Control-Allow-Credentials、Access-Control-Expose-Headers。其中Access-Control-Allow-Origin字段是必须存在的,它的值可能是Origin字段的值或者是一个通配符“*”,表示可以接受指定或任意域名的请求。很显然,服务器如果配置了通配符的话,信息泄露的风险骤然加大。
三个字段当中,Access-Control-Allow-Credentials字段不是必选字段,它的值是一个布尔值且只能设置为true,表示服务器允许浏览器将cookie包含在请求中,否则就不添加此字段。但需要注意的是,如果要发送cookie,Access-Control-Allow-Origin就不能设为星号,必须明确指定与请求网页一致的域名,同时Cookie依然遵循同源策略。而Access-Control-Expose-Headers字段主要是指定想要获取XMLHttpRequest对象中getResponseHeader()方法的其他服务器字段。
对于非简单请求,浏览器会在正式通信之前,增加一次HTTP查询请求,称之为“预检请求”。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单里以及可以使用哪些HTTP动词和头信息字段。只有获得了肯定响应,浏览器才会正式发出XMLHttpRequest请求否则就报错。
从渗透测试的角度,一般以发起简单请求为主,因此本文关注的重点也是放在简单请求上。
应用CORS技术的一个重要安全前提是跨域请求中的Origin头不能被伪造,但是这个前提并不是总是成立。Origin头最早被提出用于防御CSRF攻击,它的语法格式在RFC 6564中被定义。RFC 6564规定,如果请求来自隐私敏感上下文时,Origin头的值应该为null,但是它却没有明确界定什么是隐私敏感上下文。
但如果对请求源过分信任,则容易导致安全问题,攻击者可以修改Origin字段为任意指定的值,实现绕过浏览器同源策略的限制,基于CORS漏洞发起恶意请求,实现对目标资源的恶意跨域访问,并读取服务器的响应结果,从而造成服务器的信息泄露。
因此CORS漏洞的成因,本质上就是服务端配置的规则不当所导致的。
首先下载CORS-vulnerable-Lab靶场,地址为:
https://github.com/incredibleindishell/CORS-vulnerable-Lab
下载后将其安装到虚拟机中,利用 phpstudy 进行快速搭建。
下载完毕后,解压项目源代到phpstudy的网站 www 目录下的CORS文件夹中:
创建一个MySQL数据库,名字叫 ica_lab ,并将项目源码 database 目录下的 ica_lab.sql 文件导入到该数据库中
导入的时候注意,字符集选择UTF-8:
打开c0nnection.php,并修改连接数据库配置信息:
最后,访问靶场地址即可:
出现如图所示的页面即表示靶场搭建成功。
进入靶场首页。登陆口令默认已经设置好了,直接点击let me in
按钮即可,页面如下:
该靶场内置了3个 CORS 的漏洞场景。探测之前,首先获取虚拟机的内网ip,打开命令行,输入:
ipconfig
,得到内网ip为:192.168.181.128
接下去分别展开漏洞探测。
这种情况下,服务器将接受来自任何 Origin 的 CORS 请求。该代码将 Origin 值放在 HTTP 响应头 Access-Control-Allow-Origin 中,此配置将允许来自任何 Origin 的脚本向服务器发出 CORS 请求,从而窃取数据。
进入靶场,浏览器开启代理,并开启burp抓包。点击第一个靶场链接:
在抓取的数据包中,加一行请求头,然后抓取返回包:
看到服务器返回的数据包中已经将origin设置为我们指定的域名。之后若每次都带着该域名去访问该网站,则可被认为是同源网站,不会被浏览器的同源策略所拦截。
靶场用正则表达式要求Origin的值包含box.com,据此可以构造数据包来绕过该限制。
首先抓取数据包,然后构造数据包:
抓取返回包如下:
可以看到已经成功绕过了正则表达式的限制。
在CORS标准中缺乏对跨域请求Origin中null明确的定义和限制。有些开发者在网站上配置信任 null,用于与本地file页面共享数据,如下所示:
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
在这种情况下,攻击者可以使用各种技巧来生成跨域请求,该请求构造的Origin为null值。这将满足白名单的要求,从而导致跨域访问。
这就意味着任何配置有Access-Control-Allow-Origin: null
和Access-Control-Allow-Credentials:true
的网站等同于没有浏览器SOP的保护,都可以被其他任意域以这种方式读取内容。
CORScanner 是一个 python 工具,旨在发现网站的 CORS 错误配置漏洞。 它可以帮助网站管理员和渗透测试人员检查他们所针对的域/url 是否具有不安全的 CORS 策略。
项目地址:https://github.com/chenjj/CORScanner
linux系统下载命令:
git clone https://github.com/chenjj/CORScanner.git
安装依赖项:
sudo pip install -r requirements.txt
Linux中使用的界面如下:
下面重点以windows系统为例,介绍如何使用这个工具。
首先下载该工具的安装包,然后分别下载需要的库,在命令行中直接按分别执行命令如下:
pip install requests
pip install gevent
pip install tldextract
pip install colorama
pip install argparse
库安装完毕后,在该工具所在的文件夹中打开cmd,然后输入如下命令:
python cors_scan.py -h
CORS漏洞主要是由于配置错误而引起的。所以,预防漏洞变成了一个配置问题。下面介绍了一些针对CORS攻击的有效防御措施。
本文介绍了CORS漏洞的原理、靶场搭建方法、漏洞挖掘方法、自动化扫描工具、及CORS漏洞的修复建议,希望对大家学习渗透测试有一定的帮助。