接着昨天的来说,由于fastjson调试起来过程比较复杂,在这里直接看关键点:首先会获取字符串的第一对引号中的内容
如果内容为@type就会加载下一对引号中的类
在JavaBeanInfo.class中会获取类中所有详细详细 在这里匹配以set开头的方法
methodName.length() >= 4 &&
!Modifier.isStatic(method.getModifiers()) &&
(method.getReturnType().equals(Void.TYPE) ||
method.getReturnType().equals(method.getDeclaringClass())))
函数名长度大于等于4非静态方法,以get开头且第4个字母为大写,无参数,返回值类型继承自Collection或Map或AtomicBoolean,或Atomiclnteger或AtomicLon的方法
methodName.length() >= 4 &&
!Modifier.isStatic(method.getModifiers()) &&
methodName.startsWith("get") &&
Character.isUpperCase(methodName.charAt(3)) &&
method.getParameterTypes().length == 0 &&
(Collection.class.isAssignableFrom(method.getReturnType()) ||
Map.class.isAssignableFrom(method.getReturnType()) ||
AtomicBoolean.class == method.getReturnType() ||
AtomicInteger.class == method.getReturnType() ||
AtomicLong.class == method.getReturnType()))
其实本质就是fastjson会利用反序列化通过无参构造创建一个对象,不通过setter或getter方法进行赋值与输出操作 因此我们只需要找到满足条件的类就行,这里一般利用的是 TemplatesImpl链来加载字节码,从而rce等操作 下面我们来证明一下我们的观点 在setter方法中添加一段命令执行的代码
package com.naihe;
public class User {
private String name;
private int age;
public User() {}
public User(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
Demo:
package com.naihe;
import com.alibaba.fastjson.JSONObject;
public class Demo1 {
public static void main(String[] args) {
String str = "{\"@type\":\"com.naihe.User\",\"age\":1000,\"name\":\"老李\"}";
Object obj1 = JSONObject.parse(str);
}
}