jsonp劫持
jsonp是一个非官方的协议,全称是 JSON with Padding ,是基于 JSON 格式的为解决跨域请求资源而产生的解决方案。实现的基本原理是利用script元素的开放策略,网页可以得到从其他来源动态产生的json数据,因此可以用来实现跨域。
web程序如果通过JSONP的方式来跨域传递用户认证后的敏感信息时,攻击者完全可以在自己的虚假页面中发起恶意的jsonp请求,诱导被攻击者访问来达到截取用户敏感信息的目的。
1 | <script> |
如果服务器端的userinfo接口支持jsonp,那就会使虚假页面成功执行useUserInfo函数,从而导致安全问题。
Callback 可定义导致的安全问题
在早期 JSON 出现时候,大家都没有合格的编码习惯。再输出 JSON 时,没有严格定义好 Content-Type( Content-Type: application/json )然后加上 callback 这个输出点没有进行过滤直接导致了一个典型的 XSS 漏洞
1 | http://www.test.com/userinfo?callback=<script>alert(/xss/)</script> |
json劫持
json劫持攻击又为”JSON Hijacking”,攻击过程有点类似于csrf,只不过csrf只管发送http请求,但是json-hijack的目的是获取敏感数据。
一些web应用会把一些敏感数据以json的形式返回到前端,攻击者通过伪装成受害者的浏览器,利用浏览器的授权(如身份验证cookie,类似csrf) 发出一个请求,这个请求可以到获取到拥有敏感数据的JSON数组。攻击者通过将请求的JSON数组载入到script中以替换重写成可执行的脚本语句,从而窃取到这些数据(脚本语句会将窃取到的数据发送给攻击者)。
在以下条件下,会出现这个漏洞:首先暴露JSON服务,并且该服务会返回敏感数据;返回JSON数组;对GET请求做出响应;发送这个请求的浏览器启用了JavaScript并且支持_defineSetter_方法。
这里以漏洞靶场bWAPP 为例
比如访问http://10.240.240.202:32769/sqli_10-2.php?title=Iron+Man
在已登录的情况下会返回json格式的数据:
1 | [{"0":"2","id":"2","1":"Iron Man","title":"Iron Man","2":"2008","release_year":"2008","3":"action","genre":"action","4":"Tony Stark","main_character":"Tony Stark","5":"tt0371746","imdb":"tt0371746","6":"53","tickets_stock":"53"}] |
攻击者可以在自己的钓鱼虚假页面中,加入如下代码:
1 | <html> |
如果当前浏览器已经登录了bWAPP,并且cookie未过期,然后访问了攻击者的虚假页面,那么该页面就可以拿到json形式的用户敏感信息,因为script标签会自动解析json数据,生成对应的js对象。利用了__defineSetter__
这个特殊方法在原型对象调用属性设置方法的时候进行覆盖,来触发自己的恶意代码。
但是这个函数在当前的新版本chrome和firefox中都已经失效了,Firefox 3.0.11测试成功。
解决方法
其实json劫持和jsonp劫持属于CSRF( Cross-site request forgery 跨站请求伪造)的攻击范畴,所以解决的方法和解决csrf的方法一样。
- 严格安全的实现 CSRF 方式调用 JSON 文件:限制 Referer 、部署一次性 Token 等。
- 严格按照 JSON 格式标准输出 Content-Type 及编码( Content-Type : application/json; charset=utf-8 )。
- 严格过滤 callback 函数名及 JSON 里数据的输出。
- 严格限制对 JSONP 输出 callback 函数名的长度(如防御上面 flash 输出的方法)。
- 其他一些比较“猥琐”的方法:如在 Callback 输出之前加入其他字符(如:/**/、回车换行)这样不影响 JSON 文件加载,又能一定程度预防其他文件格式的输出。还比如 Gmail 早起使用 AJAX 的方式获取 JSON ,听过在输出 JSON 之前加入 while(1) ;这样的代码来防止 JS 远程调用。
其他
在服务器上开启web服务
http://10.240.180.201:39999
攻击者在页面中构造了自己的回调函数,如果受害者在已经经过身份认证的情况下访问了攻击者构造的页面,将把获取的数据都发送到了自己的服务器上。
jsonp劫持,构造html页面,
1 | <html> |
json劫持,构造html页面
1 | <html> |
火狐浏览器历史版本下载
http://ftp.mozilla.org/pub/firefox/releases/
参考
http://blog.knownsec.com/2015/03/jsonp_security_technic/
通过上面的攻防对抗演练,很多开发者可能会感觉有点悲剧的味道,各种防御机制好像都有办法绕过。这里我想到一个真理:没有绝对的安全!那么我们防御的意义在哪里呢?我认为防御的意义就是虽然没办法让开发的程序最安全(绝对安全),但是可以让它更安全!提高攻击者的技术成本的门槛是安全防御的一个主要的重要的方向。