当jsonp劫持遇到POST三两事

About JSONP

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

但是jsonp虽然可在其它的域下来请求数据。但是也不能设置成任意域下均可访问,否则就可能造成传递的数据被劫持。JSON劫持又称“JSON Hijacking”,这个问题属于CSRF(Cross-site request forgery跨站请求伪造)攻击范畴,当某网站通过JSONP的方式跨域(一般为子域)传递用户认证后的敏感信息时,攻击者可以构造恶意的JSONP调用页面,诱导被攻击者访问,以达到截取用户敏感信息的目的。一个例子:
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></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" src="http://10.0.0.11/jsonp/jsonp.php?callback=callback"></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发现也没返回数据,抓包查看请求:

 发现还是以GET方式发送了请求,$.ajax对jsonp进行了封装看起来像是ajax请求。由于jsonp是针对get请求的跨域解决,即使type设置了post,在jsonp的时候,也会自动转换成get,只有去手动设置crossDomain为true,或者实际上是跨域,才能修改type。
假设把Poc中的’dataType’:’JSONP’,删去,抓包发现,POST请求就发出去了在响应里也能看到返回的数据,但是的但是,被浏览器的同源策略拦截了:

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

 

当POST遇到json

当时遇到的问题比这个还复杂点,是POST请求,而且请求为发送的是json,构造HTML表单默认content-type为application/x-www-form-urlencoded,后台默认的接受到的是一个字符串string。想到一个办法,自定义headers可修改content-type,代码为:
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></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行。请求:

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

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

 

 

 

写在最后

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

   By:iDer

 

 

 

 

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注