fastjson漏洞修复过程

724 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

背景 针对fastjson最近的反序列化漏洞最近闹得是沸沸扬扬,不出意思,本人所在公司得项目也有这个问题,前几天领导安排我做一下升级。下面的本人的升级过程和方案,供大家参考。

由于Fastjson支持了AutoType能力,所谓的AutoType是对象在进行序列化的时候会将类型抹去,故反序列化时无法获取到原始类型,fastjson为了避免此问题使用了AutoType,即在序列化通过设置SerializerFeature.WriteClassName将序列化的类型记录下来

{
    "@type":"com.test.Zoo",
    "animal":{
        "@type":"com.test.Cat",
        "sound":"miao"
    },
    "name":"cat"
}

后续反序列化时即可得到具体的Cat类型。

引入这一特性虽然带来了方便,但是经常会出现能绕过AutoType黑名单的漏洞问题,阿里为了解决此问题在高版本中增加了safeMode的配置项,启用该配置项将完全禁用AutoType功能,理论上能杜绝此类漏洞的发生。

但完全禁用AutoType能力会给历史已存在的应用带来一定问题,因为如果应用中之前使用了AutoType功能,那么禁用AutoType功能后会无法正常反序列化到具体的类型,而是将直接抛出相关异常,因此需要对此种情况做定制化配置改造。

过程

升级fastjson版本

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

开启safeMode配置

@Configuration
@Data
@EqualsAndHashCode(callSuper = false)
@ConfigurationProperties(prefix="fastjson")
public class FastJsonConfig {
    private List<String> autoTypeClass;
    @PostConstruct
    public void init() {
        ParserConfig.getGlobalInstance().setSafeMode(true);
    }

}

使用ParserConfig.AutoTypeCheckHandler替代fastjson的AutoType功能

  • 添加自定义的类型处理器
@Service
public class FastJsonCheckAutoTypeHandler implements ParserConfig.AutoTypeCheckHandler {

    private static final Logger logger = LoggerFactory.getLogger(FastJsonCheckAutoTypeHandler.class);

    @Override
    public Class<?> handler(String className, Class<?> aClass, int i) {
        FastJsonConfig fastJsonConfig = (FastJsonConfig)SpringContextUtil.getBean("fastJsonConfig");
        logger.info("Checking autoType className: {}", className);
        try {
            if (fastJsonConfig.getAutoTypeClass().size()==0) {
                return null;
            }
            List<String> clazzNameArr = fastJsonConfig.getAutoTypeClass();
            for (String clazzName : clazzNameArr) {
                if (clazzName.equals(className)) {
                    return Class.forName(className);
                }
            }
        } catch (Exception e) {
            logger.error("AutoTypeHandler handle exception!", e);{}", className);
        }
        return null;
    }

}
  • 配置需要接管的类 在配置文件中增加名为fastjson.autoTypeClass的配置,将需要使用AutoType的类配置上:
fastjson:
  autoTypeClass:
    - "com.xxxx.xxx"
  • 在需要自动转换的父类指定FastJsonCheckAutoTypeHandler 在父类定义处增加@JSONType(autoTypeCheckHandler = FastJsonCheckAutoTypeHandler.class)配置即可

总结 看到很多项目都只是升级到1.2.83就可以了,但是还是默认开启了AutoType的功能,按照fastjson这个节奏,说不准下次又出什么坑,所以干脆给AutoType禁用掉,使用ParserConfig.AutoTypeCheckHandler接管这个功能就行了,一劳永逸。看似一个小功能,其实里面还是有道道的呀!