JSON

扯谈web安全之JSON

字号+ 作者:H5之家 来源:H5之家 2017-01-28 13:02 我要评论( )

这篇博客详细讨论了JSON安全的各个方面。

原文出处: hengyunabc

前言

JSON(Object Notation),可以说是事实的浏览器,服务器交换数据的标准了。目测其它的格式如XML,或者其它自定义的格式会越来越少。

为什么JSON这么流行?

和JavaScript无缝对接是一个原因。还有一个重要原因是可以比较轻松的实现跨域。如果是XML,或者其它专有格式,则很难实现跨域,要通过flash之类来实现。任何一种数据格式,如何解析处理不当,都会存在安全漏洞。下面扯谈下JSON相关的一些安全东东。

在介绍之前,先来提几个问题:

JSON注入

有的时候,可能是为了方便,有人会手动拼接下JSON,但是这种随手代码,却可能带来意想不到的安全隐患。

第一种方式,利用字符串拼接:

String user = "test01"; String password = "12345', admin:'true"; String json = "{user:'%s', password:'%s'}"; System.out.println(String.format(json, user, password)); //{user:'test01', password:'12345', admin:'true'}

用户增加了管理员权限。

第二种,利用Parameter pollution, 类似http parameter pollution

String string = "{user:'test01',password:'hello', password:'world'}"; JSONObject parse = JSON.parseObject(string); String password = parse.getString("password"); System.out.println(password); //world

当JSON数据key重复了会怎么处理?大部分JSON解析库都是后面的参数覆盖了前面的。

下面的演示了修改别人密码的例子:

//user%3Dtest01%26password%3D12345%27%2Cuser%3Dtest02" //user=test01&password=12345',user=test02 HttpServletRequest request = null; String user = request.getParameter("user"); //检查test01是否登陆 String password = request.getParameter("password"); String content = "{user:'" + user + "', password:'" + password + "'}"; User user = JSON.parseObject(content, User.class); //{"password":"12345","user":"test02"} updateDb(user);

所以说,不要手动拼接JSON字符串

浏览器端应该如何处理JSON数据?

像eval这种方式,自然是不能采用的。

现在的浏览器都提供了原生的方法 JSON.parse(str) 来转换为JS对象。如果是IE8之前的浏览器,要使用这个库来解析:https://github.com/douglascrockford/JSON-js

参考:

jQuery里内置了JSON解析库

JSONP Callback注入

简单介绍jsonp的工作原理。

jsonp工作原理:

用js在document上插入一个<script>标签,标签的src指向远程服务器的API地址。客户端和服务器约定一个回调函数的名字,然后服务器返回回调函数包裹着的数据,然后浏览器执行回调函数,取得数据。

比如jquery是这样子实现的:

var url = ':8080/testJsonp?callback=?'; $.getJSON(url, function(data){ alert(data) });

jquery自动把?转成了一个带时间戳特别的函数(防止缓存):

:8080/testJsonp?callback=jQuery1102045087050669826567_1386230674292&_=1386230674293

相当于插入了这么一个<script>标签:

<script src=":8080/testJsonp?callback=jQuery1102045087050669826567_1386230674292&_=1386230674293"></script>

服务器返回的数据是这样子的:

jQuery1102045087050669826567_1386230674292({'name':'abc', 'age':18})

浏览器会执行直接执行这个JS函数。

所以,如果在callback函数的名字上做点手脚,可以执行任意的JS代码。所以说callback名字一定要严格过滤。当然,callback函数的名字通常是程序自己控制的,但是不能排除有其它被利用的可能。那么callback函数的名字,如何过滤?应当只允许合法的JS函数命名,用正则来匹配应该是这样子的:

^[0-9a-zA-Z_.]+$

正则可能比较慢,可以写一个函数来判断:

static boolean checkJSONPCallbackName(String name) { try { for (byte c : name.getBytes("US-ASCII")) { if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') { continue; } else { return false; } } return true; } catch (Throwable t) { return false; } }

实际上对callback函数名字进行严格检验还有其它的一个好处,就是防范了很多UTF-7编码攻击。因为UTF-7编码的头部都是带有特殊字符的,如”+/v8″,”+/v9″,这样就过滤掉非法编码的请求了。

update: 2016-3-22

spring4.1里有一个AbstractJsonpResponseBodyAdvice ,里面是用正则匹配来判断是否合法的jsonp函数名。

public abstract class AbstractJsonpResponseBodyAdvice extends AbstractMappingJacksonResponseBodyAdvice { /** * Pattern for validating jsonp callback parameter values. */ private static final Pattern CALLBACK_PARAM_PATTERN = Pattern.compile("[0-9A-Za-z_\\.]*"); jsonp的请求的验证

jsonp在使用的时候,还有容易犯的错误是没有验证用户的身份。

第一,操作是否是用户自己提交的,而不是别的网页用<script>标签,或者用<form>提交的
所以要检查request的refer,或者验证token。这个实际是CSRF防护的范畴,但是很容易被忽略。

第二,要验证用户的权限。
很多时候,可能只是验证了用户是否登录 。却没有仔细判断用户是否有权限。比如通过JSONP请求修改了别的用户的数据。所以说,一定要难证来源。判断refer,验证用户的身份。

到乌云上搜索,可以找到不少类似的漏洞,都是因为没有严格验证用户的权限。?q=jsonp

JSON hijacking

在JS里可以为对象定义一些setter函数,这样的话就存在了可以利用的漏洞。比如在浏览器的JS Console里执行:

window.__defineSetter__('x', function() { alert('x is being assigned!'); }); window.x=1;

会很神奇地弹出一个alert窗口,说明我们定义的setter函数起作用了。

结合这个,当利用<script>标签请求外部的一个JSON API时,如果返回的是数组型,就可以利用窃取数据。比如有这样的一个API:

返回的数据是JSON Array:

{'user':'test01','age':18},{'user':'test02,'age':19},{'user':'test03','age':20}]

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 遍历 JSON 的键值对

    遍历 JSON 的键值对

    2017-01-28 14:02

  • TurboGears JSON渲染

    TurboGears JSON渲染

    2017-01-28 13:01

  • jquery处理json数据返回数组和输出的方法

    jquery处理json数据返回数组和输出的方法

    2017-01-28 11:04

  • JSON--List集合转换成JSON对象详解

    JSON--List集合转换成JSON对象详解

    2017-01-27 18:06

网友点评