Fastjsonfan反序列化(一)
前置知识
Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。
Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象(通过远程调用的方式)
//序列化
String text = JSON.toJSONString(obj);
//反序列化
VO vo = JSON.parse(); //解析为JSONObject类型或者JSONArray类型
VO vo = JSON.parseObject("{...}"); //JSON文本解析成JSONObject类型
VO vo = JSON.parseObject("{...}", VO.class); //JSON文本解析成VO.class类
对象转字符串(序列化)
实体类User
package org.example;
public class User {
public int id;
public String name;
public int age;
public User() {
}
public User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
定义一个测试类
package org.example;
import org.example.User;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
public class Test {
public static void main(String[] args) {
User user = new User();
user.setId(1);
user.setName("zhangsan");
user.setAge(18);
//对象转字符串
String s1 = JSON.toJSONString(user);
String s2 = JSON.toJSONString(user, SerializerFeature.WriteClassName);
System.out.println(s1);
System.out.println(s2);
}
}
输出结果
{"age":18,"id":1,"name":"zhangsan"}
{"@type":"org.example.User","age":18,"id":1,"name":"zhangsan"}
字符串转对象(反序列化)
package org.example;
import org.example.User;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
public class fastjsonTest {
public static void main(String[] args) {
User user = new User();
user.setId(1);
user.setName("zhangsan");
user.setAge(18);
//对象转字符串
String s1 = JSON.toJSONString(user);
String s2 = JSON.toJSONString(user, SerializerFeature.WriteClassName);
System.out.println(s1);
System.out.println(s2);
System.out.println("s1==========================s1");
//字符串转对象
Object o1 = JSON.parse(s1);
JSONObject jo1 = JSON.parseObject(s1);
User user1 = JSON.parseObject(s1, User.class);
System.out.println(o1);
System.out.println(jo1);
System.out.println(user1);
System.out.println("s2=========================s2");
Object o2 = JSON.parse(s2);
JSONObject jo2 = JSON.parseObject(s2);
User user2 = JSON.parseObject(s2, User.class);
System.out.println(o2);
System.out.println(jo2);
System.out.println(user2);
}
}
输出结果
{"age":18,"id":1,"name":"zhangsan"}
{"@type":"org.example.User","age":18,"id":1,"name":"zhangsan"}
s1==========================s1
{"name":"zhangsan","id":1,"age":18}
{"name":"zhangsan","id":1,"age":18}
User{id=1, name='zhangsan', age=18}
s2=========================s2
User{id=1, name='zhangsan', age=18}
{"name":"zhangsan","id":1,"age":18}
User{id=1, name='zhangsan', age=18}
fastjson通过JSON.toJSONString()
将对象转为字符串(序列化),当使用SerializerFeature.WriteClassName
参数时会将对象的类名写入@type
字段中,在重新转回对象时会根据@type
来指定类,进而调用该类的set
、get
方法。因为这个特性,我们可以指定@type
为任意存在问题的类,造成一些问题
利用
漏洞是利用fastjson autotype在处理json对象的时候,未对@type
字段进行完全的安全性验证,攻击者可以传入危险类,并调用危险类连接远程rmi主机
,通过其中的恶意类执行代码。攻击者通过这种方式可以实现远程代码执行漏洞的利用,获取服务器的敏感信息泄露,甚至可以利用此漏洞进一步对服务器数据进行修改,增加,删除等操作,对服务器造成巨大的影响。
set,get,is自动调用问题
构造Evil类
package org.example;
public class Evil {
private String cmd;
public Evil(){
System.out.println("Evil()"+ this.hashCode());
}
public String getCmd() {
System.out.println("getCmd()"+this.hashCode());
return cmd;
}
public void setCmd(String cmd) {
System.out.println("setCmd"+this.hashCode());
this.cmd = cmd;
}
}
写一个test测试下
package org.example;
import com.alibaba.fastjson.JSON;
public class Test {
public static void main(String[] args) {
String evil = "{\"@type\":\"org.example.Evil\",\"cmd\":\"calc\"}";
JSON.parse(evil);
System.out.println("-------------------");
JSON.parseObject(evil);
System.out.println("------------------");
JSON.parseObject(evil, Object.class);
}
}
跟进parseObject(evil)
发现其方法发现也是使用parse解析的,但是多了一个(JSONObject)toJSON(obj)
这个方法调用的get,堆栈如下
getCmd:11, Evil (org.example)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
get:451, FieldInfo (com.alibaba.fastjson.util)
getPropertyValue:105, FieldSerializer (com.alibaba.fastjson.serializer)
getFieldValuesMap:439, JavaBeanSerializer (com.alibaba.fastjson.serializer)
toJSON:902, JSON (com.alibaba.fastjson)
toJSON:824, JSON (com.alibaba.fastjson)
parseObject:206, JSON (com.alibaba.fastjson)
main:13, Test (org.example)
那么setter在哪调用的?
在com.alibaba.fastjson.util.JavaBeanInfo#build
中
在通过@type
拿到类之后,通过反射拿到该类所有的方法存入methods,接下来遍历methods进而获取get、set方法,如上图。总结set方法自动调用的条件为:
- 方法名长度大于4
- 非静态方法
- 返回值为void或当前类
- 方法名以set开头
- 参数个数为1
当满足条件之后会从方法名截取属性名,截取时会判断_
,如果是set_name
会截取为name
属性,具体逻辑如下:
当截取完但是找不到这个属性
会判断传入的第一个参数类型是否为布尔型,是的话就在截取完的变量前加上is
,截取propertyName的第一个字符转大写和第二个字符,并且然后重新尝试获取属性字段。
比如:public boolean setBoy(boolean t) 会寻找isBoy
字段。
set的整个判断就是:如果有setCmd()会绑定cmd属性,如果该类没有cmd属性会绑定isCmd属性。
get的判断
总结下就是:
- 方法名长度大于等于4
- 非静态方法
- 以get开头且第4个字母为大写
- 无传入参数
- 返回值类型继承自Collection Map AtomicBoolean AtomicInteger AtomicLong
当程序绑定了对应的字段之后,如果传入json字符串的键值中存在这个值,就会去调用执行对应的setter、构造方法
小结:
- parse(jsonStr) 构造方法+Json字符串指定属性的setter()+特殊的getter()
- parseObject(jsonStr) 构造方法+Json字符串指定属性的setter()+所有getter() 包括不存在属性和私有属性的getter()
- parseObject(jsonStr,Object.class) 构造方法+Json字符串指定属性的setter()+特殊的getter()
Fastjsonfan反序列化(一)的更多相关文章
- C#反序列化XML异常:在 XML文档(0, 0)中有一个错误“缺少根元素”
Q: 在反序列化 Xml 字符串为 Xml 对象时,抛出如下异常. 即在 XML文档(0, 0)中有一个错误:缺少根元素. A: 首先看下代码: StringBuilder sb = new Stri ...
- C# 序列化与反序列化几种格式的转换
这里介绍了几种方式之间的序列化与反序列化之间的转换 首先介绍的如何序列化,将object对象序列化常见的两种方式即string和xml对象; 第一种将object转换为string对象,这种比较简单没 ...
- 迟来的Json反序列化
源码发布 搞了一个下午,终于搞定了这个号称中国的github...以后源码直接在这里发布了(github实在用不来,英文实在太烂了) https://code.csdn.net/jy02305022/ ...
- .Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json、反序列化json示例教程
JSON作为一种轻量级的数据交换格式,简单灵活,被很多系统用来数据交互,作为一名.NET开发人员,JSON.NET无疑是最好的序列化框架,支持XML和JSON序列化,高性能,免费开源,支持LINQ查询 ...
- 使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON、.net 的json的序列化与反序列化(一)
在开发中,我非常喜欢动态语言和匿名对象带来的方便,JSON.NET具有动态序列化和反序列化任意JSON内容的能力,不必将它映射到具体的强类型对象,它可以处理不确定的类型(集合.字典.动态对象和匿名对象 ...
- 【.NET深呼吸】如何反序列化动态JSON
.net本身除了支持SOAP.XML.二进制等序列化和反序列化,后来也加入了对JSON的序列化的支持.然而,在实际开发中,常常会遇到结构不确定的JSON对象,这些对象可能是其他代码动态生成的,你事先无 ...
- Java 序列化与反序列化
1.什么是序列化?为什么要序列化? Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程. 我们都知道,在进行浏览器访问的时候,我们看到的文本.图片.音频. ...
- C#中怎样实现序列化和反序列化
我们想要将数据进行持久化的操作的话,也就是将数据写入到文件中,我们在C#中可以通过IO流来操作,同时也可以通过序列化来操作,本人是比较推荐使用序列化操作的 因为我们如果想要将一个对象持久化到文件中 如 ...
- Java序列化与反序列化
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...
- 让Visual Studio 2013为你自动生成XML反序列化的类
Visual Sutdio 2013增加了许多新功能,其中很多都直接提高了对代码编辑的便利性.如: 1. 在代码编辑界面的右侧滚动条上显示不同颜色的标签,让开发人员可以对所编辑文档的修改.查找.定位情 ...
随机推荐
- C++ 二级指针与 const 关键字
可用七种不同的方式将 const 关键字用于二级指针,如下所示: //方式一:所指一级指针指向的数据为常量,以下几种为等效表示 const int ** pptc; //方式一 int const * ...
- Deployment控制器(pod)更新策略
最小就绪时间: 配置时,用户可以使用Deplpoyment控制器的spec.minReadySeconds属性来控制应用升级的速度.新旧更替过程中,新创建的Pod对象一旦成功响应就绪探测即被视作可用, ...
- 《Vision Permutator: A Permutable MLP-Like ArchItecture For Visual Recognition》论文笔记
论文题目:<Vision Permutator: A Permutable MLP-Like ArchItecture For Visual Recognition> 论文作者:Qibin ...
- vue2.x引入threejs
@ 目录 vue2.x引入threejs npm安装 使用指定版本: 其他插件 实例 强调 vue2.x引入threejs npm安装 npm install three 使用指定版本: npm in ...
- PAT (Basic Level) Practice 1032 挖掘机技术哪家强 分数 20
为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛.现请你根据比赛结果统计出技术最强的那个学校. 输入格式: 输入在第 1 行给出不超过 105 的正整数 N,即参赛人数.随后 N ...
- 数据火器库八卦系列之瑞士军刀随APP携带的SQLite
来源:云数据库技术 数据库打工仔喃喃自语的八卦历史 1. 为导弹巡洋舰设计,用在手机上的数据库 2. Small and Simple, and Better 3. 如何看出是自己的娃:产品定位,特点 ...
- [笔记] 兰道定理 Landau's Theorem
兰道定理的内容: 一个竞赛图强连通的充要条件是:把它的所有顶点按照入度d从小到大排序,对于任意\(k\in [0,n-1]\)都不满足\(\sum_{i=0}^k d_i=\binom{k+1}{2} ...
- QML 信号与响应方法的总结
以下内容为本人的著作,如需要转载,请声明原文链接微信公众号「englyf」https://www.cnblogs.com/englyf/p/16748191.html 如果面试过程中,面试官想了解你对 ...
- sql查数据库表中的条数
select count(*) from <>表名 例 select count(*) from user_info
- C++面向对象编程之类模板、函数模板等一些补充
1.static数据 和 static函数: 对于 非static函数 在内存中只有一份,当类对象调用时,其实会有该对象的this pointer传进去,那个函数就知道要对那个对象进行操作: stat ...