fastjson 的 “autoType” 特性是指在反序列化过程中,允许将 JSON 字符串自动转换为指定的 Java 类型。它提供了一种方便的方式,使得开发人员可以直接将 JSON 数据转换为相应的 Java 对象,而无需手动指定目标类。
然而,这个特性也存在一定的安全风险。攻击者可以构造恶意的 JSON 数据,其中包含对不受信任的类的引用。当 “autoType” 特性被启用时,Fastjson 会尝试根据 JSON 字符串中的类信息实例化相应的对象,从而可能导致潜在的安全问题,例如远程代码执行攻击。
例如:
String jsonString = "{\"@type\":\"com.example.EvilClass\",\"data\":\"Malicious Data\"}";
Object obj = JSON.parseObject(jsonString);
在上述示例中,JSON 字符串中的 “@type” 属性指定了一个名为 “com.example.EvilClass” 的类。如果 Fastjson 的 “autoType” 特性被启用,它将尝试将该 JSON 字符串转换为 “com.example.EvilClass” 类的实例,而不考虑该类是否可信或预期。
为了防止这种安全问题,Fastjson 默认情况下禁用了 “autoType” 特性,以提供一定的安全性。但是,在某些特定场景下,开发人员可能会手动启用该特性,例如在处理受信任的 JSON 数据时需要转换为多态对象。
可以在配置文件中设置
fastjson.parser.safeMode=true
也可以修改虚拟机启动参数-Dfastjson.parser.safeMode=true
。
在组件引入了fastjson2和spring-boot-starter的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.36</version>
</dependency>
开启 fastjson 的安全模式,关闭 autoType 特性
package com.zhl.index12306.framework.starter.bases.safa;
public class FastJsonSafeMode implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.setProperty("fastjson2.parser.safeMode", "true");
}
}
package com.zhl.index12306.framework.starter.bases.config;
public class ApplicationBaseAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(value = "framework.fastjson.safa-mode", havingValue = "true")
public FastJsonSafeMode congoFastJsonSafeMode() {
return new FastJsonSafeMode();
}
}
也可以选择其他的序列化工具,例如jackson,gson
jackson序列化的示例
@Data
public class User {
private Integer id;
private String name;
}
/**
* 测试 User对象 -> json/byte[]..
*/
@Test
public void objectToJSONTest() throws JsonProcessingException {
User user = new User();
user.setId(1);
user.setName("zzz");
ObjectMapper mapper = new ObjectMapper();
String strJson = mapper.writeValueAsString(user);
byte[] bytes = mapper.writeValueAsBytes(user);
System.out.println(new String(bytes));
System.out.println(strJson);
}
/**
* 测试 json -> User对象
*/
@Test
public void JSONToObjectTest() throws JsonProcessingException {
String str = "{\"id\":1,\"name\":\"zzz\"}";
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(str, User.class);
System.out.println(user);
}
/**
* 测试 反序列化的类中不存在的字段
*/
@Test
public void notExistFieldTest() throws JsonProcessingException {
String str = "{\"id\":1,\"name\":\"zzz\",\"sex\":1}";
ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
User user = mapper.readValue(str, User.class);
System.out.println(user);
}
参考
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-25845
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-18349
关于fastJson漏洞的总结说明