现在的位置: 首页 > 综合 > 正文

JSONP存在的JSON Hijacking漏洞以及与csrf/xss漏洞的关系

2019年04月26日 ⁄ 综合 ⁄ 共 3953字 ⁄ 字号 评论关闭

在实习过程中接触过所谓的JSON Hijacking 漏洞,但最近在写论文时发现理解得不深,好像跟xss与csrf又有点区别与联系,索

性深入学习了下JSONP(JSON with Padding)


下面一段话截取自:http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about   仔细看看就比较清晰了。

Say you're on domain abc.com, and you want to make a request to domain xyz.com. To do so, you need to cross domain boundaries, a no-no in most of browserland.

The one item that bypasses this limitation is <script> tags. When you use a script tag, the domain limitation is ignored, but under normal circumstances, you can't really DO anything with the results, the script just gets evaluated.

Enter JSONP. When you make your request to a server that is JSONP enabled, you pass a special parameter that tells the server a little bit about your page. That way, the server is able to nicely wrap up its response in a way that your page can handle.

For example, say the server expects a parameter called "callback" to enable its JSONP capabilities. Then your request would look like:

http://www.xyz.com/sample.aspx?callback=mycallback

Without JSONP, this might return some basic JavaScript object, like so:

{ foo: 'bar' }

However, with JSONP, when the server receives the "callback" parameter, it wraps up the result a little differently, returning something like this:

mycallback({ foo: 'bar' });

As you can see, it will now invoke the method you specified. So, in your page, you define the callback function:

mycallback = function(data){
  alert(data.foo);
};

And now, when the script is loaded, it'll be evaluated, and your function will be executed. Voila, cross-domain requests!


大概解释一下。举例:在abc.com 有这么一段 <script src="http://www.xyz.com/sample.aspx?callback=mycallback"></script>

在 xyz.com 的 sample.aspx 可能是如下实现的:


 PHP Code 
1
2
3
4
5
6
<?php
header('Content-Type:text/html;charset=utf-8');
$callback = $_GET['callback'];
$data     = "{foo:
'bar'
}";
echo $callback . "(" . $data . ");";
?>

src 标签请求返回即 <script> mycallback({foo: 'bar'});</script> 也就是会执行函数mycallback,这里需要明确的是mycallback
肯定是在

abc.com 上实现的,把 {foo: 'bar' }
作为参数传递,以便下一步操作。callback只是个key,也可以写成jsonp,当然server获取的key也得变换。


讲到这里,对于正常的请求,jsonp并没有什么安全问题。但是,对于一些在登陆态会暴露敏感信息如用户id和昵称的cgi来说,我们直接用浏览器访问

http://www.a.com/json.php?mod=pay&func=openvip&callback=loginInfoCallback   虽然我们并没有实现loginInfoCallback ,但如上所述,server端会返

回 loginInfoCallback({"ret":-1102321,"data":{"_id":1032412,"_nick":"jnusimba"}});  当然这是在 jnusimba
在浏览器的另一个tab已经登录过 a.com 的情

形下。所以攻击的手法是 在第三方站点通过<script
src=http://
www.a.com/json.php?mod=pay&func=openvip&callback=loginInfoCallback></script>

的形式就可以在函数loginInfoCallback 参数里面取得当前用户的id号和昵称。


上述讲到的JSON Hijacking 漏洞可以认为是 csrf漏洞的一种,也就是 csrf 写-读 。基本原理还是因为浏览器的会话机制在第三方站点请求 a.com 时

也会把a.com 相关的cookie 发送出去。防御来说,校验refer/ 请求带上form token 都是比较好的办法,也就是带有第三方无法预测的值。


对于上面server端的php代码来说,返回 {foo: 'bar'}  没有带有登陆态信息,故没有什么实质的风险。但不知道有人注意到没有,它返回的头部

Content-Type:text/html; 即类型设置错误了,应该是content-type:text/javascript;  (or application/javascript) 设置成html格式,容易造成xss攻击,比

callback=<script>alert('aaa')</script>,即浏览器会弹框(注意,在高版本的ie和chrome下面可能已经限制了xss攻击,测试在firefox下查看即可)。

前10来天写论文时挖到的一个youku站点因为jsonp产生的反射xss漏洞,今天再次访问已经被修复了,可我找不到当初哥提交乌云的链

接了哭~。(注:The MIME media type for JSON text is application/json. The default encoding is UTF-8. 

For JSONP with callback :application/javascript )

如果大家想玩一玩,可以看 http://lorrylockie.github.io/2015/01/27/jsonp-safe/ 这里的一个例子,如下图:

访问链接 http://login.koudai.com/weidian/sendCodeToBuyerPhone?param=%20{%22telephone%22:%2218601662827%22,%22country_code%22:%2286%22}&callback=%3Cscript%3Ealert%28/xxs/%29;%3C/script%3E%3Cdiv%20style=%22font-size:100px;%22%3EKOU%20DAI%20TONG%20DA%20SHA%20B%3C/div%3E&ver=1031

注:搞安全的需要职业素养,原po主已经提交给乌云以及口袋通方面了,没修就不是白帽子的责任了,当然大家也别去恶搞呀。



可以看到响应头是html,故造成了xss攻击,查看网页源代码以及点击确定后的浏览器输出:



从中也可以验证我们上面所说关于jsonp的应用,比如 正常的请求访问 http://login.koudai.com/weidian/sendCodeToBuyerPhone?param=%20{%22telephone%22:%2218601662827%22,%22country_code%22:%2286%22}&callback=mycallback&ver=1031

可以猜想 输入的telephone值在server端进行验证,用返回的status_code表示是否有效,进而作为mycallback的参数进行下一步操

作,比如正确则发送验证码之类。如果我们把号码换成18601662826 进行访问,返回的是

mycallback({"status":{"status_code":0,"status_reason":""}})   基于猜想,我认为这个号码是真实存在的哈。


对于此类由jsonp引起的反射xss漏洞,一来响应头应该设置正确;二来应该对callback参数进行过滤或者编码,避免可以直接执行js。

参考链接:

http://lorrylockie.github.io/2015/01/27/jsonp-safe/

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

http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about


抱歉!评论已关闭.