在实习过程中接触过所谓的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
在 xyz.com 的 sample.aspx 可能是如下实现的:
1
2 3 4 5 6 |
header(
'Content-Type:text/html;charset=utf-8');
$callback = $_GET[ 'callback']; $data = "{ foo: 'bar' }"; echo $callback . "(" . $data . ");"; ?> |
src 标签请求返回即 也就是会执行函数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 的情
形下。所以攻击的手法是 在第三方站点通过“”
的形式就可以在函数loginInfoCallback 参数里面取得当前用户的id号和昵称。
上述讲到的JSON Hijacking 漏洞可以认为是 csrf漏洞的一种,也就是 csrf 写-读 。基本原理还是因为浏览器的会话机制在第三方站点请求 a.com 时
也会把a.com 相关的cookie 发送出去。防御来说,校验refer/ 请求带上form token 都是比较好的办法,也就是带有第三方无法预测的值。
注意:jsonp 只支持 get 请求。
对于上面server端的php代码来说,返回 {foo: 'bar'} 没有带有登陆态信息,故没有什么实质的风险。但不知道有人注意到没有,它返回的头部
Content-Type:text/html; 即类型设置错误了,应该是content-type:text/javascript; (or application/javascript) 设置成html格式,容易造成xss攻击,比
如callback=,即浏览器会弹框(注意,在高版本的ie和chrome下面可能已经限制了xss攻击,测试在firefox下查看即可)。
(注:The MIME media type for JSON text is application/json. The default encoding is UTF-8. For JSONP with callback :application/javascript )
对于此类由jsonp引起的反射xss漏洞,一来响应头应该设置正确;二来应该对callback参数进行过滤或者编码,避免可以直接执行js。
关于 csrf 的防御:
1. 检查 http referer 是否是同域
如果网站有客户端,需要对此开绿灯,可能是个隐患。
注意:ajax 跨域发起请求时是不可以添加 cookie、user-agent、referer、 x_forward_for 等http 头的,可以看下w3c给出的一份头部黑名单。
否则 referer 校验就无效了。
此外在某些情况下,浏览器也不会发送referer,比如从https 跳转到 http;flash 的请求等。
2. 限制 cookie 的生命周期(减少发生概率)
3. 使用一次性 token
token 是一段随机的数字字母值,经常出现在表单的隐藏项中,原理是 无法通过 ajax 获取到外域页面的 token 值(虽然可以通过 html 标签带动 ajax 跨域请求,如 ,但无法通过 javascript 读取返回的内容)。
4. 使用验证码(降低用户体验)
当同域页面上有xss 漏洞时,可以通过 ajax 获取到其他页面的 token;
token 如果出现在 get 参数中,也容易通过 refer的方式泄露;
此时只能通过验证码来防范csrf 了。
参考链接:
http://en.wikipedia.org/wiki/JSONP
http://stackoverflow.com/questions/2067472/what-is-jsonp-all-about