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(意思是爱重构) ========= ...
随机推荐
- 流量回放专题-jvm-sanbox-repeater
流量回放介绍 一.前言 你是否和我一样遇到过以下的问题? 1)服务重构,一堆接口需要回归,让人头疼 2)每次迭代,都要花很多精力来进行回归测试 3)线上bug,线下复现不了 4)接口自动化用例写辛苦, ...
- JavaScript01 js基础语法,数据类型
JavaScript的概述: 1.组成 三部分组成 ecmaScript 基础语法 (es5) dom document object model 文档对象模型 (操作html文档内容) bom bo ...
- ArrayList如何实现插入的数据按自定义的方式有序存放?
编程思路是:实现一个类对ArrayList进行包装,当程序试图向ArrayList中放入数据时,程序将先检查该元素与ArrayList集合中其他元素的大小,然后将该元素插入到指定位置. class M ...
- python实现AES加密、解密
AES加密方式有五种:ECB, CBC, CTR, CFB, OFB 从安全性角度推荐CBC加密方法,本文介绍了CBC,ECB两种加密方法的python实现 python 在 Windows下使用AE ...
- 为什么要使用 kafka,为什么要使用消息队列?
缓冲和削峰:上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka在中间可以起到一个缓冲的作用,把消息暂存在kafka中,下游服务就可以按照自己的节奏进行慢慢处理. 解耦 ...
- 数组有没有length()方法?String有没有length()方法?
数组没有length()方法,有length 的属性.String 有length()方法.JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆.
- 基于redis实现未登录购物车
springboot 工程 主要说明购物车流程(故将登录用户信息保存至session) 未登录时 将用户临时key 保存至cookie 有不足之处 请大佬指点 项目源码: https://github ...
- 学习RabbitMQ(二)
MOM(message oriented middleware) 消息中间件(是在消息的传递过程中保存消息的容器,消息中间件再将消息从它的源中继到它的目标时,充当中间人的作用,队列的主要目的是提供路由 ...
- BMZCTF phar???
pchar??? 补充知识点 开始这题之前我们先补充一个知识点 phar 的文件包含 和上面类似先创建一个phar 标准包,使用 PharData 来创建,然后添加文件进去phar里面. 然后在文件包 ...
- 攻防世界 unserialize3
unserialize3 class xctf{ public $flag = '111'; public function __wakeup(){ exit('bad requests'); } } ...