JAVA_Fastjson

0x00前言

Fastjson 是 Alibaba 开发的 Java 语言编写的高性能 JSON 库,用于将数据在 JSON 和 Java Object 之间互相转换。

提供两个主要接口来分别实现序列化和反序列化操作。

JSON.toJSONString 将 Java 对象转换为 json 对象,序列化的过程。

JSON.parseObject/JSON.parse 将 json 对象重新变回 Java 对象;反序列化的过程

所谓JOSN就可以简单的理解成一串有格式的字符串,然后既然它存在序列化和反序列化,那么中间代码会不会就出现问题呢,就是我们要研究的地方

0x03 代码 demo

0x01漏洞原理

这里的话回去写一些demo就是fastjson的demo关于它解析对象有一些奇奇怪怪的的操作把、

直接看第一个代码

class test3{
    public static void main(String[] args) {
        String JsonString="{\"age\":22,\"name\":\"me\"}";
        Object jsonObject = JSON.parseObject(JsonString,Hacker.class);
        System.out.println(jsonObject.getClass().getName());
    }
}

他的结果是这样的

image-20230104215635104它调用出来的对象是被强制要求成了Hacker对象,这里的话比较安全因为强制序列化这个对象的话就很难找到后续的利用率

看第二个代码

class test2{
    public static void main(String[] args) {
        String JsonString="{\"@type\":\"Hacker\",\"age\":22,\"name\":\"me\"}";
        Object jsonObject = JSON.parseObject(JsonString);
        System.out.println(jsonObject.getClass().getName());
    }
}

image-20230104215940134

这里的区别就在于我们客户端传入的值有一个叫@type的东西,如果存在这个字符串那么。服务端就会把我们传过来的值当做这个对象去解析。

然后我们进去看看这些方法的调用,在我没有传type对象时候只调用set和构造方法,而有type字符串的时候呢调用了set,get 和构造方法我们调试进去看看这个反序列化是怎么操作的,是怎么调用这些方法的

调试进来,会调用一个只接受String对象方parseObject 方法image-20230104221843527

然后更近这个parse这个方法一直跟到

image-20230104222558237

DefaultJSONParser进来这个就是一个默认的Parse处理嘛,跟进去以后里面都是

DefaultJSONParser parser = new DefaultJSONParser(text, ParserConfig.getGlobalInstance(), features);

跟进去一直往下走也没什么处理的地方这个就是应该是一个处理器的获取

image-20230104223136780

跟进里面发现的是一些赋值,和判断这里的判断的话,根据后面它把我们的字符串,做成了一个scanner应该是去判断之后去返回一个我们需要Parser,还值得一提的是这个feture这个属性值

一直跟出来,上面那个获取parser其实跟没有特别必要去跟,里面很多都是些跟我们无关纯判断之类,我现在来看现在已经是拿到那个parser了我们跟进去看看是怎么处理的

image-20230104225142066

进来之后这里有个switch嘛然后判断是token,这个token的话应该是通过字符串的第一个数字去转换的,转成image-20230104225456467

这里token12对应的是{这个字符串然后就会调用一个New JOSNObject

image-20230104225754544

然后我们就去看下一个方法 parseObject这个方法跟进去

image-20230104230046274

进来之后发现还是那些token去判断

image-20230104230246741

这里往下跟的话其实就是一些逻辑上的问题,就简单看几个逻辑点吧,其实他就是把传入的JSON对象,键值对,分成两个部分来看嘛

先看到这个,这个会遇到,会进行跳过,就是我们JSON对象中就键值对直接就会存在逗号

image-20230104230511328

往下走,看到它会去构造一个key然后又开始判断,判断 第一个是什么符号,这符号的话因为是JSON格式的所以就只能判断一些单引号,双引号之类的然后去中间把值拿出来比如我传的值是“@type”,然后它会匹配这个两个值

image-20230104230633076

然后就都是判断,我们直接一路跟到匹配完,我们拿到这个key

看这个几个判断就是它会根据我们拿到的可以去执行不同的操作,我们这个是@type,就是类了它后面就要做java的反序列化了,

到这里其实就感觉很接近我们的漏洞点了,我们知道fastjson就是通过反序列化来执行的操作嘛

image-20230104231542967

还是看一下这个loadClass这个方法把

image-20230104231935281

image-20230104232116685

进来之后首先是一个判断把,判断这个mappings中有没有缓存然后去加载,随后就是判断第一个值把,第一个是数组还是什么就用不同的方法去加载

image-20230104232255193

最后就是去获取一个上下文的Classloader,然后把这个类加载了放到缓存mappings中

走出来以后就到这里

image-20230104232417789

这里就是获取一个反序列化器,然后用反序列化器反序列化,跟进来这里面的代码其实很复杂也很鸡肋吧,感觉是有用的,但是里面其实很多判断和逻辑是我暂时利用不到的,就快速的过一下,看到一些有用的就记录一下

image-20230104234854015

这儿的话还是有一个逻辑就说,它会根据不同的类去调用不同的构造

然后就经过一些类的匹配,如果所有类都没匹配到最后就会创建一个 creat一个

image-20230104235824353

然后这里面就一些很杂的东西,走都后面会调用一个方法

image-20230105000109617

这个build的话,就简单介绍一下它什么功能然后介绍一些流程,它是要去获取我们传入类的所有参数然后去形成一个新的beaninfo

然后中间获取的话,这个逻辑比较重要就是它怎么获取的,可以看到它遍历了两遍method,这两遍分别就是一个遍历set,另一个遍历get,中间的代码我就只是大概的过了一下,就是一些判断,然后那些东西要那些东西不要,

image-20230105000330497

然后后面的流程就比较复杂了,还是提两句吧,从那个方法出来以后就可以看到这个 deserialze

image-20230105001939769

这个反序列化你直接跟是跟不进去的,因为它的反序列化器是临时的,这里要跟进去的话得去你的bean构建一个只有get方法的map属性,这是里面的一个逻辑,我也没有具体的进去跟了, 然后我直接去看了最后的源码就是JavaBeanDeserializer

这里再说一下漏洞的大概逻辑吧,其实就是它在反序列化的时候会调用set方法赋值,那get方法呢?,get方法其实实在image-20230105002534230

最后这个 JSON.toJSON(obj)去输出,然后就会调用get方法,利用方式呢也很简单,就是说我们找到一个恶意的set方法然后把它用@type绑定进去随后再传进去那些恶意参数去执行就行了

0x02漏洞利用

poc

若反序列化指定类型的类如Student obj = JSON.parseObject(text, Student.class);,该类本身的构造函数、setter方法、getter方法存在危险操作,则存在Fastjson反序列化漏洞;

若反序列化未指定类型的类如Object obj = JSON.parseObject(text, Object.class);,该若该类的子类的构造方法、setter方法、getter方法存在危险操作,则存在Fastjson反序列化漏洞

{
"@type":"xxx.xxx.xxx",
"xxx":"xxx",
...
}
//type,更上恶意类,后续更上参数就行

实例

实现方法很简单在刚刚那个bean类里面随便一个恶意的方法的话然后调用fastjson

image-20230105175212064

public static void main(String[] args) {
    String JsonString="{\"@type\":\"Hacker\",\"age\":22,\"name\":\"me\"}";
    Object jsonObject = JSON.parseObject(JsonString);
    System.out.println(jsonObject.getClass().getName());
}

image-20230105175407018

这里的调用的话是Object类去反序列化,然后Object是所有类的父类,然后我们使用@Type去指向Hacker类然后就可以造成反序列化漏洞,其实还有一种触发方式,其实我觉得都差不多吧,就是直接触发那个类的PareObject方法

Student obj = JSON.parseObject(jsonstring, Hacker.class, Feature.SupportNonPublicField);

0x03小结

这个东西怎么说呢,可以去跟一下漏洞原理但是我自己也没有完全跟明白只是大概的去理了一下逻辑,也有些地方自己没理清楚然后看了别的师傅的文章以后补充一点,但是感觉这个中间的过程说重要也重要说不重要也不重要,

posted @ 2023-01-05 23:17  不成大哥不改名  阅读(236)  评论(0编辑  收藏  举报