Fastjson反序列化漏洞


Fastjson反序列化漏洞fastjson基础反序列化漏洞autotype@type处理流程漏洞例子JdbcRowSetImpl分析


Fastjson是一个由Alibaba开发的一个Java库,可以将Java 对象转换为JSON 格式,当然它也可以将JSON 字符串转换为Java 对象

自2017年3月15日,fastjson官方主动爆出其在1.2.24及之前版本存在远程代码执行高危安全漏洞以来,各种新型绕过姿势层出不穷。之前一直没机会看(懒),最近稍微看一看学一学,先看看最开始的地方。

 

fastjson基础

对于使用者来说还是很友好的

pom.xml中直接导入,并修改想用的版本号即可

一般是直接import com.alibaba.fastjson.JSON;

然后就可以直接用

当然不止这两种处理形式,这里只是比较常见的两种方法

提供一个demo(注意nameprivate,必须有gettersetter,否则转成JSON时会为空,但如果name直接是public则不需要。还有一个注意点是执行parseObject()时,必须要有个无参的构造方法,否则会报错default constructor not found. class Test$User

输出:

 

反序列化漏洞

为何为产生反序列化漏洞?

autotype

这里需要先介绍一下autotype

fastjson提供特殊字符段@type,这个字段可以指定反序列化任意类,并且会自动调用类中属性的特定的setget方法。

上面给的demo代码中有这么一句

JSON.parseObject()这里传入了两个参数,第二个参数确定了到底要用哪个类

而如果每解析一个json字符串的地方都需要提前指定一个类,代码会显得很臃肿。所以fastjson提供了单参数的parseObject()@type,具体如下:

把这段代码续在demo之后可以看到输出

成功调用了Test$UsersetNamegetName,且其中的name为我们提供的值

我们即能够传入任意的类、任意的值(当然,得服务端有)

所以如果存在某个类的getXxx或者setXxx(或布尔类型的isXxx)存在一些比较危险的操作时,就会有问题

PS.

其实在toJSONString()时,第二个参数传入SerializerFeature.WriteClassName

打印json会输出{"@type":"Test$User","name":"cccc"}

 

@type处理流程

稍微跟了一跟parseObject()的处理流程,具体就不贴了,网上到处都有,推荐两篇Fastjson 流程分析及 RCE 分析Fastjson反序列化漏洞史中的解析流程

简单来讲也就是一位位判断,获取到keyJSON.DEFAULT_TYPE_KEY,也就是为@type的时候,再用TypeUtils.loadClass()加载其value中的内容,也就是上面的Test$User

最终再通过deserializer.deserialze()完成反序列化

 

漏洞例子

看一个反序列化漏洞的例子,来加深下印象

先搭建环境

JNDI.java:

Exp.java:

Test.java:

Exp.java编译成Exp.class后运行JNDI开启服务,再用Test去触发即可弹出计算器,接下来分析

JdbcRowSetImpl分析

之前说的一些fastjson内部干的事就跳过了,快进到set方法,我们传入了dataSourceNameautoCommit,在反序列化的时候会一次按传入顺序操作,所以首先会调用

setDataSourceName()

getDataSourceName()是获取dataSource的值

this.getDataSourceName()这里为null,直接进入else语句调用super.setDataSourceName(var1);

也就是调用BaseRowSetdataSource赋为var1的值

接着经过一些处理再进入setAutoCommit()

this.connnull,进入else分支调用this.connect()

最终触发InitialContext.lookup(this.getDataSourceName())