Fastjson反序列化漏洞原理分析

2024-09-20 1 0

0x01 前言

最近学习了Fastjson反序列化漏洞,看视频、读文章,才勉勉强强搞明白原理。这里我把学习到的内容简单总结出来,希望对各位理解Fastjson反序列化漏洞有所帮助。如果文章中有错误之处,还请批评指正,我会尽快修改。

0x02 前置知识

什么是json字符串?

形如下面的字符串,就被称为一个json字符串,也就是字典的形式

{

"name":"BossFrank",

"age":23

}

Fastjson是什么?

一个开源的java工具库,用来把Java对象序列化成json字符串或者把json字符串反序列化成一个Java对象

对象属性动态赋值的方式

1、调用对象的getter/setter方法

2、反射赋值

安全问题

FastJson引入了一个特性,即可以通过@type字段来指定反序列化出来的对象,该字段的值为对象所属类的全限定名。由于这个@type,在Fastjson反序列化的时候,可以指定任意反序列化的类。如果用户传入恶意的JSON字符串,那么就会产生安全问题

FastJson的序列化和反序列化函数

序列化函数:JSON.toJSONString(Object object)

反序列化函数:Fastjson反序列化采用JSON.parseObject()和JSON.parse()这两个方法

parseObject():返回JSON对象

第一处parse返回出来的对象,就是我们普通的java对象,然后会进行逻辑判断,最终转成JSON对象返回出来,所以,无论是否使用@type来指定对象,返回出来的只会是JSON对象。

Fastjson反序列化漏洞原理分析插图1

Fastjson反序列化漏洞原理分析插图2

而调用parseObject想要获取到普通的对象,有两者方式,一种是对parseObject传第二个参数,即想要返回对象的类

Fastjson反序列化漏洞原理分析插图3

实际上呢,这里调用的并非前面的那个parseObject,而是它的一个同名函数

Fastjson反序列化漏洞原理分析插图5

而第二种方式呢,就是拿到JSON对象之后,调用toJavaObject函数

Fastjson反序列化漏洞原理分析插图6

Fastjson反序列化漏洞原理分析插图7

Parse():返回我们本身的类对象

Fastjson反序列化漏洞原理分析插图8

可以看到我们用@type指定类型之后,返回出来的是person对象

Fastjson反序列化漏洞原理分析插图9

同时我们注意到,在调用parse和parseObject的时候,会自动调用person类的getter和setter方法,至于为什么会调用,后面流程分析会知道。同时还发现两者调用的getter/setter方法有差异,即parseObject会调用getter和setter方法,而parse时只会调用setter方法

这里差别的原因可以先粗浅理解为:parseObject会先创建一个普通的java类对象,这里是person对象,前面我们知道,给对象属性赋值,要么反射,要么set方法,这里要给person对象的属性赋值,所以要调用set方法,又因为返回时要转成JSON对象{"name":"mike","age":17},所以要调用get方法来获取每个属性的值

0x03流程分析

在parseObject处下个断点,跟进去看,发现调用了只接受字符串的parse函数

Fastjson反序列化漏洞原理分析插图10

继续往里跟,然后调用到parse(String text, int features),也就是说只接受字符串的parseObject函数和parse函数最后都会调用到这里

Fastjson反序列化漏洞原理分析插图11

这里实例化了一个默认的Json解析器,然后调用了一个不接受参数的parse函数,继续往里跟,最后会来到一个接受Object类型参数的parse函数,这个函数里面的逻辑是,获取令牌,根据令牌的类型进行解析,比如说左大括号、JSON数组、左方括号等等

Fastjson反序列化漏洞原理分析插图12

因为我们是JSON字符串,也就是左大括号,然后会走到这里

Fastjson反序列化漏洞原理分析插图13

new了一个JSON对象,然后传给了DefaultJSONParser里面的parseObject(final Map object, Object fieldName)函数,继续跟进去,开头有一些边界值的检查,核心逻辑就是这里try里面的内容

Fastjson反序列化漏洞原理分析插图14

继续往下走,定义了一个key,下面就是一些if-else来获取到key的值

Fastjson反序列化漏洞原理分析插图15

然后就会走到这里,对key值进行判断,我们实际上key值就是JSON.DEFAULT_TYPE_KEY,也就是下面会按照Java对象解析,所以会走到这个if里面

Fastjson反序列化漏洞原理分析插图16Fastjson反序列化漏洞原理分析插图17

if里面首先把类加载进来,然后就是一些if判断,最主要的还是最后这里

Fastjson反序列化漏洞原理分析插图18

获取了person类的反序列化器,然后用这个反序列化器进行反序列化,这里返回就是我们的person对象了,我们跟进去getDeserializer这个函数

Fastjson反序列化漏洞原理分析插图19

这个函数里面,先根据我们的type尝试从缓存中获取一个已经存在的反序列化器,这里是没有的,所以不会直接返回,然后就调用到ParserConfig里的一个同名函数getDeserializer((Class<?>) type, type),我们跟进去

Fastjson反序列化漏洞原理分析插图20

在这里有一个黑名单,继续往下走过一些大大小小的if之后,最后会来到这里,创建一个JavaBean反序列化器,跟进去

Fastjson反序列化漏洞原理分析插图21

先看到里面有个按钮asmEnable,默认为true

Fastjson反序列化漏洞原理分析插图22

然后下面有一些if判断,可以改变asmEnable的值,接着到这里,新建一个JavaBeanInfo。这里要知道的是,在创建类的反序列化器的时候,要先了解类里面的一些内容,比如字段、构造函数、setter/getter函数等,然后把这些内容放到JavaBeanInfo里面去,我们跟进去

Fastjson反序列化漏洞原理分析插图23

这里获取person类的所有字段和方法

Fastjson反序列化漏洞原理分析插图24

然后继续往下走到这里,大概说一下这三处循环的作用,分别是获取这个类满足条件的所有setter方法、字段和getter方法

Fastjson反序列化漏洞原理分析插图25

简单说一下第一处循环的逻辑,遍历所有的方法,开头有一些if判断,目的是找到满足以下条件的方法:

  • 方法名长度大于4
  • 不是静态函数
  • 返回值为void
  • 函数接受一个参数
  • set开头

接着截取setxxx后面的字段名,转成小写,然后把获取到的信息放到new出来的FieldInfo,加到fieldList里面去

Fastjson反序列化漏洞原理分析插图26

第二处循环的大概逻辑是添加了public、private、未在列表中存在等一些字段到fieldList中

第三处循环与第一处差不多,找到满足条件的方法加到fieldList,其实也就是getter方法,这里要满足的条件大概是:

  • 方法名长度大于4
  • 不是静态函数
  • get开头
  • 返回值必须为Collection、Map、AtomicBoolean、AtomicInteger、AtomicLong其中之一
  • 函数接受参数为0
  • 并且前面没有被加到过FileList的字段,也就是说没有对应的setter方法

然后也会上面处理set一样,截取getxxx后面的字段名,转成小写,加到fieldList里面

处理完这三个循环之后,就把这些信息封装成JavaBeanInfo返回出去,接着根据JavabeanInfo来创建并返回JavaBean反序列化器

Fastjson反序列化漏洞原理分析插图27

Fastjson反序列化漏洞原理分析插图28

一路返回,我们回来到这里

Fastjson反序列化漏洞原理分析插图29

我们跟进deserialze函数,看看是怎么反序列化的,发现只有值的变化,具体的代码执行调试不了,因为asmEnable这个按钮是开着的,我们返回的是asm临时创建的反序列化器

Fastjson反序列化漏洞原理分析插图30

我们要想要调试,那么就需要返回JavaBeanDeserializer,也就是要把asmEnable的值改成flase,我们可以在反序列化前修改一下配置,修改asmEnable的值

Fastjson反序列化漏洞原理分析插图31

可以调试后,我们跟进deserialze函数,过掉一些if后,这里把我们前面加到FiledList里面的字段拿到

Fastjson反序列化漏洞原理分析插图32

然后这里构造对象

Fastjson反序列化漏洞原理分析插图33

Fastjson反序列化漏洞原理分析插图34

继续往下走调用赋值函数

Fastjson反序列化漏洞原理分析插图35

然后里面呢,就会调用到对应setter函数和相应的只有getter的函数,所以我们一开始看到的调用parseObject函数会把setter函数给调用了,同时这里我们还知道,对于只有getter的函数,也是在返回person对象的过程中调用的

Fastjson反序列化漏洞原理分析插图36

Fastjson反序列化漏洞原理分析插图37

而对于有对应setter函数的getter函数,而是在返回person对象之后,调用toJSON函数调用的,也就是下面这个地方,所以调用parse()时并不会自动调用到setter函数

Fastjson反序列化漏洞原理分析插图38

我们编写一个恶意类来试试

Fastjson反序列化漏洞原理分析插图39

Fastjson反序列化漏洞原理分析插图40

可以看到弹出来计算器了,同时我们注意到,JSON字符串中存在类里面没有setter/getter函数对应的字段或者不存在的字段也是可以的,因为前面我们知道它会在setter/getter函数的处理来截取后面的部分作为字段,所以传入的JSON字符串的变量名用的是setter/getter函数的后面部分,值才会传进对应的stter/getter函数。我们实际利用中大概率也不会直接能在stter函数里面找到恶意代码,通常是以setter/getter函数为入口点,往下找反序列化的链子。


4A评测 - 免责申明

本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。

不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。

本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!

程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。

侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)

相关文章

Rust 的风,终究还是吹到了前端
【验证码逆向专栏】xx邮政滑块逆向分析
内存马第三弹——Controller内存马
codeql自动化漏洞检测入门
艾体宝干货丨OIDA之二:掌握数据包分析-学会识别
Patchwork更新武器库,首次利用Brute Ratel C4和PGoshell增强版发起攻击

发布评论