fastjson远程代码执行漏洞修复方案, 为了安全我升级到了fastjson2

harry发布

一、漏洞概述

5 月 23 日, 官方发布公告称在 1.2.80 及以下版本中存在新的反序列化风险,在特定条件下可绕过默认 autoType 关闭限制,从而反序列化有安全风险的类,攻击者利用该漏洞可实现在目标机器上的远程代码执行

spring cloud alibaba sentinel 中依赖 fastjson 传递依赖引入,请相关用户尽快采取防护措施。

影响范围

受影响版本

  • Fastjson ≤ 1.2.80

不受影响版本

  • Fastjson = 1.2.83

二、罪魁祸首 AutoType

fastjson、jackson 都支持 AutoType 功能,这个功能在序列化的 JSON 字符串中带上类型信息,在反序列化时,不需要传入类型,实现自动类型识别。

三、fastjson1 安全问题

fastjson 1.x 内部维护了一个白名单,java 发展近 30 年难免有些漏网之鱼,这也造成近几年 fastjson 安全漏洞频发,养活了一大票安全人员。

四、jackson AutoType 处理

同样,jackson 也支持 AutoType,jackson 爆出的几次安全漏洞也跟它有关。Jackson 的 json 解析跟 ObjectMapper 绑定,我们可以根据不同的需求来定制 ObjectMapper。

例如:只在 redis 序列化和反序列时激活 DefaultTyping。(示例代码,mica-redis 中采用 ObjectMapper copy 生成新的 ObjectMapper bean 避免污染全局 ObjectMapper 造成不安全)

public RedisSerializer<Object> redisSerializer(ObjectProvider<ObjectMapper> objectProvider) {
 // jackson findAndRegisterModules,use copy
 ObjectMapper objectMapper = objectProvider.getIfAvailable(ObjectMapper::new).copy();
 objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
 // findAndRegisterModules
 objectMapper.findAndRegisterModules();
 // class type info to json
 GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);
 objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), DefaultTyping.NON_FINAL, As.PROPERTY);
 return new GenericJackson2JsonRedisSerializer(objectMapper);
}

五、fastjson2 的设计

  • fastjson2 AutoType 必须显示打开才能使用,没有任何白名单,也不包括任何 Exception 类的白名单。这可以保证缺省配置下是安全的。

序列化带上类型信息

序列化是带上类型信息,需要使用 JSONWriter.Feature.WriteClassName。比如:

Bean bean = ...;
String jsonString = JSON.toJSONString(bean, JSONWriter.Feature.WriteClassName);

很多时候,root对象是可以知道类型的,里面的对象字段是基类或者不确定类型,这个时候不输出root对象的类型信息,可以减少序列化结果的大小,也能提升反序列化的性能。

Bean bean = ...;
String jsonString = JSON.toJSONString(bean, JSONWriter.Feature.WriteClassName, JSONWriter.Feature.NotWriteRootClassName);

反序列化打开AutoType功能支持自动类型

Bean bean = (Bean) JSON.parseObject(jsonString, Object.class, JSONReader.Feature.SupportAutoType);
  • fastjson2 AutoType 支持配置 safeMode,在 safeMode 打开后,显式传入 AutoType 参数也不起作用,具体配置如下:

-Dfastjson2.parser.safeMode=true
  • fastjson2 AutoType 会经过内置黑名单过滤。该黑名单能拦截大部分常见风险,这个机制不能保证绝对安全,打开 AutoType 不应该在暴露在公网的场景下使用。这点无可厚非,毕竟 AutoType 的场景不是在 web api,

六、升级到 fastjson2

6.1 兼容模式升级

升级可以通过兼容模式升级,兼容模式不需要改代码,但在深度使用的场景,如果原来使用fastjson 1.2.x版本,可以使用兼容包,兼容包不能保证100%兼容,请仔细测试验证,发现问题请及时反馈。 https://github.com/alibaba/fastjson2/issues

Fastjson v1兼容模块,Maven依赖,如当前版本<version>2.0.4</version>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>${fastjson2.version}</version>
</dependency>

6.2 使用新API升级

使用新API是建议的升级方式,使用新的API能获得更多的功能。

  • 包名编程 FASTJSON v2和1.x版本使用不同的package,新的package名称是com.alibaba.fastjson2,新package和之前不同,可以实现1.x和2.x共存

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONArray;
  • Maven依赖 Maven依赖的groupId和1.x不同,使用了新的groupIdcom.alibaba.fastjson2

<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>${fastjson2.version}</version>
</dependency>

如果你需要用到spring支持的功能,还需要依赖fastjson2-extension

<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2-extension</artifactId>
    <version>${fastjson2.version}</version>
</dependency>

笔者尝试升级的一个项目依赖比较少,并且也没有强制依赖 fastjson1,另外项目中也没用到一些奇淫技巧。所以选择了比较激进的直接升级新 API。

另外有使用 FastJsonHttpMessageConverter 也是更改一下包名即可。

import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;

更改为:

import com.alibaba.fastjson2.support.config.FastJsonConfig;
import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter;
@Configuration(proxyBeanMethods = false)
public class FastJsonConfiguration {

    @Bean
    public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        converter.setFastJsonConfig(new FastJsonConfig());
        converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, new MediaType("application", "*+json")));
        return converter;
    }

}

最后

fastjson2 在性能和安全上都得到了很好的提升,特别是支持了 jsonb,在缓存、rpc 等场景优先考虑 jsonb


0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注