FastJson数据格式化问题以及漏洞
前言
json数据是java中常见的数据格式,形成类似于map+数组的数据结构,阿里也为此专门设计了有关java的fastjson,足以可见其中对json的业务需求,具体的发展历史不多赘述。最近业务上对此的使用也颇多,干脆一次性来个简单的总结。
本人主要钻研在后端,前端有所学习,但谈不上工程级别,为此叙述的过程中对前端的说法不一顶准确,多多见谅
对象和json的区别
这和主流的框架处理方式有关,这边讨论java的spring框架
在后端用对象封装好之后,留给前端的就是json数据,字符串型的使用“”括住,数值型的则没有
但是前端传回时,就不再有引号了(缺少转义符),对此json转化最会出错
当然,后端也可以使用json字符串直接返回给前端,在fastJson中toJsonString,返回给前端的数据则会用反斜杠 \ 来区分引号中的引号(此处也可以在fastJson的配置信息中更改,变成和前者一样的标准json)
fastJson的用法
jsonObject
类似于map结构,可以存入各式各样的对象在value中,fastJson会自行形成对应的结构
JSON.parseObject
从字符串解析 JSON 对象
- JSON.parseArray
从字符串解析 JSON 数组
JSON.toJSONString(obj/array)
将 JSON 对象或 JSON 数组转化为字符串
JSONObject.getObject(String key, Class
clazz)
将json转为对象
json转列表
JSONArray students = jsonObject.getJSONArray("list"); List<Student> students = JSONObject.parseArray(students.toString(), Student.class);
问题
fastJson的主要特点就是序列化比较快了,是已知的几个(字符串方式)序列化方式中最快的,为了实现快的目的,使用了全局缓存、仅仅序列父类类型(借用AutoType曲线救国)、避免使用反射、算法优化等等
fastJson的问题还是比较出名的了,原因就主要出在这个“快”上面:fastJson是通过遍历实体类中的所有getter方法来取值,对比gosn是通过反射遍历成员变量的属性,因此前者它就很快了。
问题就来了:当一个类中包含了一个接口(或抽象类)的时候,在使用fastjson进行序列化的时候,会将子类型抹去,只保留接口(抽象类)的类型,使得反序列化时无法拿到原始类型。
对此fastJson就引入了AutoType,使用全类名的方式,将指定子类的类型,因此黑客仅仅需要更改
- AutoType类型的值
- 从上文中提过的更改全局缓存中的type值
- 利用异常绕过序列化校验等方式,重写type的值
指定加载特定的类,比如com.sun.rowset.JdbcRowSetImpl(远程调用)等,黑客甚至可以去指定自己要想执行的系统指令。尽管经历了围绕AutoType无数次的博弈、修改,目前都有了对应的修复,但是最终还是额外提供了一种方式,即safeMode,简单得说,就是禁用AutoType
补充:
个人比较喜欢在浏览json数据时使用vscode新建json数据,格式化后查看非常方便直观