Fastjson反序列化漏洞基础
Fastjson反序列化
- 什么是序列化?
序列化是把对象转换为字符串 - 什么是反序列化?
把字符串转换为对象
fastjson是alibaba开发的一个序列化和反序列化的组件方便开发者的使用,通过在反序列化的过程中自动调用get\set方法将JSON字符串还原成对象,当这些自动调用的方法中存在可利用的潜在危险代码时漏洞便产生了
d16ef480-81a0-4cb4-8453-688ddfdd1919
fastjson漏洞版本
1.2.24 --首个fastjson的漏洞
1.2.41 --黑名单绕过
1.2.42 --黑名单绕过
1.2.45 --新的利用链
1.2.47 --AutoType绕过
1.2.68 --AutoType绕过
Fastjson反序列化漏洞基础
fastjson将JSON还原成对象的方法有以下三种:
- parse(String text)
- parseObject(String text)
- parseObject(String text,Class clazz)
*parse和parseObjetc的区别(转)
Fastjson中的 parse() 和 parseObject()方法都可以用来将JSON字符串反序列化成Java对象,parseObject() 本质上也是调用 parse() 进行反序列化的。但是 parseObject() 会额外的将Java对象转为 JSONObject对象,即 JSON.toJSON()。所以进行反序列化时的细节区别在于,parse() 会识别并调用目标类的 setter 方法及某些特定条件的 getter 方法,而 parseObject() 由于多执行了 JSON.toJSON(obj),所以在处理过程中会调用反序列化目标类的所有 setter 和 getter 方法。


当通过这三个方法将JSON还原成对象的时候,fastjson会自动调用类中的set方法和无参构造方法,以及满足条件的get方法。当类中定义的属性和方法满足下列的要求的时候fastjson会自动调用get方法
- 只存在get方法无set方法
- 方法名称长度大于等于4
- 非静态方法
- 方法名以get开头,且第四个字母为大写字母例如:getName()
- 方法无须入参
- 方法返回值继承自
Collection、Map、AtomicBoolean、AtomicInteger和AtomicLong的其中一个
漏洞基本原理
写一个实体类方便测试
package org.example;
import java.io.IOException;
public class Person {
private String name;
private int age;
public Person() {
System.out.println("无参构造方法被调用了....");
}
public String getName() {
System.out.println("get方法被调用了....");
return name;
}
public void setName(String name) {
System.out.println("set方法被调用了.....");
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试类
package org.example;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
//创建对象,并且给属性赋值
Person person = new Person();
person.setName("zhangsan");
person.setAge(18);
//将对象序列化称字符串
System.out.println(JSON.toJSONString(person));
}
}
当使用fastjson进行序列化对象的时候可以发现,set、get方法中的代码得到了执行

如果set、get方法中包含恶意的代码那么也会得到执行
如果想得到这个对象的完整路径,我们可以再序列化时加上SerializerFeature.WriteClassName参数,在转换为字符串的时候就会得到这个类的完整路径
在这里就得到这个类的完整路径(org.example.Person)和属性名(name,age)
将对象序列化之后得到字符串{"@type":"org.example.Person","age":18,"name":"zhangsan"}也可以利用parse()方法在将其还原成字符串
到了这一步,fastjson反序列化漏洞基本就清晰了,在1.2.24的版本中@type:跟着类的具体路径,后面是set和get方法,由前面可知如果序列化字符串中有@type则会按照该类型进行反序列化操作,而如果没有该属性,则默认都返回JSONObject对象(一种字典类型数据存储)。反序列化的对象是由客户端决定的,那么在反序列化时我们通过@type指引一个恶意的类,该类中有恶意代码,那么也会被解析执行
package org.example;
import java.io.IOException;
public class Exploit {
private String test;
public String getTest() {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
return test;
}
public void setTest(String test) {
this.test = test;
}
}

靶场复现
通过vulhub部署一个fastjson的靶场

浙公网安备 33010602011771号